mutator_selection_logic.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import numpy as np
  2. from scripts.logger.lemon_logger import Logger
  3. import random
  4. #np.random.seed(20200501)
  5. class Roulette:#轮盘赌选择种子模型
  6. class Mutant:
  7. def __init__(self, name, selected=0):
  8. self.name = name
  9. self.selected = selected
  10. @property
  11. def score(self):#公式4,伪代码26行
  12. return 1.0 / (self.selected + 1)
  13. def __init__(self, mutant_names=None, capacity=101):
  14. self.capacity = capacity
  15. if mutant_names is None:
  16. self._mutants = []
  17. else:
  18. self._mutants = [Roulette.Mutant(name) for name in mutant_names]
  19. @property
  20. def mutants(self):
  21. mus = {}
  22. for mu in self._mutants:
  23. mus[mu.name] = mu
  24. return mus
  25. @property
  26. def pool_size(self):
  27. return len(self._mutants)
  28. def add_mutant(self, mutant_name, total=0):
  29. self._mutants.append(Roulette.Mutant(mutant_name, total))
  30. def pop_one_mutant(self, ):
  31. np.random.shuffle(self._mutants)
  32. self._mutants.pop()
  33. def is_full(self):
  34. if len(self._mutants) >= self.capacity:
  35. return True
  36. else:
  37. return False
  38. def choose_mutant(self):
  39. #对应伪代码3-14行,这里没有计算公式5的pi,而是直接把随机数乘sum,原理是一样的
  40. sum = 0
  41. for mutant in self._mutants:
  42. sum += mutant.score
  43. rand_num = np.random.rand() * sum
  44. for mutant in self._mutants:
  45. if rand_num < mutant.score:
  46. return mutant.name
  47. else:
  48. rand_num -= mutant.score
  49. class MCMC:#蒙特卡洛选择变异算子
  50. class Mutator:
  51. def __init__(self, name, total=0, delta_bigger_than_zero=0, epsilon=1e-7):
  52. self.name = name
  53. self.total = total
  54. self.delta_bigger_than_zero = delta_bigger_than_zero
  55. self.epsilon = epsilon
  56. @property
  57. def score(self, epsilon=1e-7):#公式3,伪代码27行
  58. mylogger = Logger()
  59. rate = self.delta_bigger_than_zero / (self.total + epsilon)
  60. mylogger.info("Name:{}, rate:{}".format(self.name, rate))
  61. return rate
  62. def __init__(self, mutate_ops=None):
  63. self.mylogger = Logger()
  64. self.mylogger.info(f"Using {self.__class__.__name__} as selection strategy!")
  65. if mutate_ops is None:
  66. from scripts.mutation.model_mutation_generators import all_mutate_ops
  67. mutate_ops = all_mutate_ops()
  68. self.p = 1 / len(mutate_ops)
  69. self._mutators = [self.Mutator(name=op) for op in mutate_ops]#变异算子列表
  70. @property
  71. def mutators(self):#用变异算子名称返回这个算子对象
  72. mus = {}
  73. for mu in self._mutators:
  74. mus[mu.name] = mu
  75. return mus
  76. def choose_mutator(self, mu1=None):
  77. if mu1 is None:#第一个变异算子是随机选择的(伪代码第1行)
  78. # which means it's the first mutation
  79. return self._mutators[np.random.randint(0, len(self._mutators))].name
  80. else:#伪代码15-20行
  81. self.sort_mutators()#根据每个算子的得分降序排序
  82. k1 = self.index(mu1)#当前算子排名
  83. k2 = -1
  84. prob = 0
  85. while np.random.rand() >= prob:
  86. k2 = np.random.randint(0, len(self._mutators))
  87. prob = (1 - self.p) ** (k2 - k1) #计算每个种子模型被选取的概率
  88. mu2 = self._mutators[k2]
  89. return mu2.name
  90. def sort_mutators(self):
  91. import random
  92. random.shuffle(self._mutators)
  93. self._mutators.sort(key=lambda mutator: mutator.score, reverse=True)
  94. def index(self, mutator_name):
  95. for i, mu in enumerate(self._mutators):
  96. if mu.name == mutator_name:
  97. return i
  98. return -1