def test_point_mutation(monkeypatch): """ Test for simple point mutation """ def mock_values_generator(): for v in [0, 1, 1, 1]: yield v values_generator = mock_values_generator() def mock_values(): return next(values_generator) monkeypatch.setattr('pycgp.mutation.choice', lambda x: mock_values()) genes = [2, 0, 1, 2, 1, 1, 2, 2, 2, 3] bounds = [2, 1, 1, 2, 2, 2, 2, 3, 3, 4] individual = Individual(genes, bounds, Params(2, 1)) mutated_individual, _ = point_mutation(individual) assert mutated_individual.genes == [1, 0, 1, 2, 1, 1, 2, 2, 2, 3] assert mutated_individual.function_nodes[0].function_index == 1 mutated_individual, _ = point_mutation(individual) assert mutated_individual.genes == [2, 1, 1, 2, 1, 1, 2, 2, 2, 3] assert not mutated_individual.function_nodes[0].active assert mutated_individual.function_nodes[1].active assert not mutated_individual.function_nodes[2].active
def mo_individual(): """as multi-output individual""" mo_bounds = bounds[:] mo_bounds.append(6) mo_genes = [1, 0, 0, 1, 1, 1, 0, 4, 2, 2, 3, 1, 6, 3] return Individual(mo_genes, mo_bounds, Params(3, 2, funset=funset))
def single_mutation(individual, _=None): """ perform a 'single' mutation - mutate until active gene is changed """ active_changed = False genes = individual.genes[:] bounds = individual.bounds agenes = individual.active_genes changed_indices = [] while not active_changed: indices = [i for i, x in enumerate(bounds) if x != 0] index = choice(indices) changed_indices.append(index) possible_values = [x for x in range(0, bounds[index] + 1) if x != genes[index]] genes[index] = choice(possible_values) if agenes[index] == 1: active_changed = True return Individual(genes, bounds, individual.params), changed_indices
def apply(self, individual: Individual) -> Individual: if individual.active_genes[self.index] == 0: return None self.n_uses += 1 genes = individual.genes[:] genes[self.index] = self.mutated return Individual(genes, individual.bounds, individual.params)
def jewellerybox(): box = JewelleryBox(MatchPMStrategy()) parent_genes = [1, 0, 0, 1, 1, 1, 0, 4, 2, 2, 1, 3, 6] mutated_genes_1 = [1, 0, 0, 1, 3, 1, 0, 4, 2, 2, 1, 3, 6] mutated_genes_2 = [1, 0, 0, 1, 1, 1, 0, 4, 2, 2, 5, 3, 6] parent = Individual(parent_genes, bounds, params) mutated_1 = Individual(mutated_genes_1, bounds, params) mutated_2 = Individual(mutated_genes_2, bounds, params) mutated_1.fitness = 95 mutated_2.fitness = 90 parent.fitness = 100 box.add(GemSingleGene(mutated_1, parent, 4)) box.add(GemSingleGene(mutated_2, parent, 10)) return box
def test_add_to_full(individual: Individual, jewellerybox: JewelleryBox): """ Should replace the gem with least value """ # there are already two individuals in jewellerybox (from conftest.py) jewellerybox.max_size = 2 # individual fixture has no fitness individual.fitness = 100 # get the smallest min_value = min(jewellerybox.gems.values()) assert min_value == 5 # add another better_ind = Individual(individual.genes[:], individual.bounds, individual.params) better_ind.fitness = 30 new_gem = GemSingleGene(better_ind, individual, 7) jewellerybox.add(new_gem) min_value = min(jewellerybox.gems.values()) assert min_value == 10
def test_equality(self, individual): """ Test the equality of two individuals """ # create a new, same individual new_same_ind = Individual(individual.genes, individual.bounds, individual.params) # create individual with modified active gene mod_active_genes = individual.genes[:] mod_active_genes[2] = 2 mod_act_ind = Individual(mod_active_genes, individual.bounds, individual.params) # create individual with modified inactive gene mod_inact_genes = individual.genes[:] mod_inact_genes[4] = 2 mod_inact_ind = Individual(mod_inact_genes, individual.bounds, individual.params) assert individual == new_same_ind assert not (individual == mod_act_ind) assert individual != mod_act_ind assert individual == mod_inact_ind
def probabilistic_mutation(individual, rate=0.25): """ Perform a probabilistic mutation - at each gene position there is a chance it will mutate """ genes = individual.genes[:] bounds = individual.bounds changed_indices = [] for index in range(0, len(genes)): chance = random() if chance < rate: possible_values = [x for x in range(0, bounds[index] + 1) if x != genes[index]] if len(possible_values) == 0: continue changed_indices.append(index) genes[index] = choice(possible_values) return Individual(genes, bounds, individual.params), changed_indices
def point_mutation(individual, _=None): """ perform a point mutation on given individual """ genes = individual.genes[:] bounds = individual.bounds # this does not change # handle case, when there is only one possible value # of gene at certain position indices = [i for i, x in enumerate(bounds) if x != 0] index = choice(indices) # construct the list of acceptable values possible_values = [x for x in range( 0, bounds[index] + 1) if x != genes[index]] genes[index] = choice(possible_values) return Individual(genes, bounds, individual.params), index
def active_mutation(individual, _=None): """ Perform an active mutation - to-be mutated gene is chosen only from active genes """ genes = individual.genes[:] bounds = individual.bounds agenes = individual.active_genes # simultaneously handle genes with only one possible values # and inactive genes indices = [i for i, (b, a) in enumerate( zip(bounds, agenes)) if b != 0 and a == 1] index = choice(indices) possible_values = [x for x in range( 0, bounds[index] + 1) if x != genes[index]] genes[index] = choice(possible_values) return Individual(genes, bounds, individual.params), index
def test_hash(individual): """ Hash should be the same for Gems with same parameters """ mutated_genes = individual.genes[:] mutated_genes_2 = individual.genes[:] mutated_genes[1] = 2 mutated_genes_2[1] = 1 mutated = Individual(mutated_genes, individual.bounds, individual.params) mutated2 = Individual(mutated_genes_2, individual.bounds, individual.params) mutated.fitness = 100 mutated2.fitness = 100 individual.fitness = 100 g = GemSingleGene(mutated, individual, 1) gg = GemSingleGene(mutated, individual, 1) ggg = GemSingleGene(mutated2, individual, 1) assert hash(g) == hash(gg) assert hash(g) != hash(ggg) assert hash(g) == hash(g)
def individual(): genes = [1, 0, 0, 1, 1, 1, 0, 4, 2, 2, 3, 1, 6] #active [1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1] return Individual(genes, bounds, params)
def apply(self, individual: Individual) -> Individual: self.n_uses += 1 genes = individual.genes[:] for m_index, mutated in zip(self.m_indices, self.mutated): genes[m_index] = mutated return Individual(genes, individual.bounds, individual.params)
def apply(self, individual: Individual) -> Individual: new_genes = individual.genes[:] new_genes[self.gene_index] = self.mutated return Individual(new_genes, individual.bounds, individual.params)
def build(self): genes, bounds = self.gfactory.create() return Individual(genes, bounds, self.params)