123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- import numpy as np
- from scripts.logger.lemon_logger import Logger
- import random
- #np.random.seed(20200501)
- class Roulette:#轮盘赌选择种子模型
- class Mutant:
- def __init__(self, name, selected=0):
- self.name = name
- self.selected = selected
- @property
- def score(self):#公式4,伪代码26行
- return 1.0 / (self.selected + 1)
- def __init__(self, mutant_names=None, capacity=101):
- self.capacity = capacity
- if mutant_names is None:
- self._mutants = []
- else:
- self._mutants = [Roulette.Mutant(name) for name in mutant_names]
- @property
- def mutants(self):
- mus = {}
- for mu in self._mutants:
- mus[mu.name] = mu
- return mus
- @property
- def pool_size(self):
- return len(self._mutants)
- def add_mutant(self, mutant_name, total=0):
- self._mutants.append(Roulette.Mutant(mutant_name, total))
- def pop_one_mutant(self, ):
- np.random.shuffle(self._mutants)
- self._mutants.pop()
- def is_full(self):
- if len(self._mutants) >= self.capacity:
- return True
- else:
- return False
- def choose_mutant(self):
- #对应伪代码3-14行,这里没有计算公式5的pi,而是直接把随机数乘sum,原理是一样的
- sum = 0
- for mutant in self._mutants:
- sum += mutant.score
- rand_num = np.random.rand() * sum
- for mutant in self._mutants:
- if rand_num < mutant.score:
- return mutant.name
- else:
- rand_num -= mutant.score
- class MCMC:#蒙特卡洛选择变异算子
- class Mutator:
- def __init__(self, name, total=0, delta_bigger_than_zero=0, epsilon=1e-7):
- self.name = name
- self.total = total
- self.delta_bigger_than_zero = delta_bigger_than_zero
- self.epsilon = epsilon
- @property
- def score(self, epsilon=1e-7):#公式3,伪代码27行
- mylogger = Logger()
- rate = self.delta_bigger_than_zero / (self.total + epsilon)
- mylogger.info("Name:{}, rate:{}".format(self.name, rate))
- return rate
- def __init__(self, mutate_ops=None):
- self.mylogger = Logger()
- self.mylogger.info(f"Using {self.__class__.__name__} as selection strategy!")
- if mutate_ops is None:
- from scripts.mutation.model_mutation_generators import all_mutate_ops
- mutate_ops = all_mutate_ops()
- self.p = 1 / len(mutate_ops)
- self._mutators = [self.Mutator(name=op) for op in mutate_ops]#变异算子列表
- @property
- def mutators(self):#用变异算子名称返回这个算子对象
- mus = {}
- for mu in self._mutators:
- mus[mu.name] = mu
- return mus
- def choose_mutator(self, mu1=None):
- if mu1 is None:#第一个变异算子是随机选择的(伪代码第1行)
- # which means it's the first mutation
- return self._mutators[np.random.randint(0, len(self._mutators))].name
- else:#伪代码15-20行
- self.sort_mutators()#根据每个算子的得分降序排序
- k1 = self.index(mu1)#当前算子排名
- k2 = -1
- prob = 0
- while np.random.rand() >= prob:
- k2 = np.random.randint(0, len(self._mutators))
- prob = (1 - self.p) ** (k2 - k1) #计算每个种子模型被选取的概率
- mu2 = self._mutators[k2]
- return mu2.name
- def sort_mutators(self):
- import random
- random.shuffle(self._mutators)
- self._mutators.sort(key=lambda mutator: mutator.score, reverse=True)
- def index(self, mutator_name):
- for i, mu in enumerate(self._mutators):
- if mu.name == mutator_name:
- return i
- return -1
|