diff --git a/cgp/individual.py b/cgp/individual.py index b6db334c..428c9d27 100644 --- a/cgp/individual.py +++ b/cgp/individual.py @@ -32,6 +32,7 @@ def __init__(self, fitness: Union[float, None]) -> None: """ self.fitness: Union[float, None] = fitness self.idx: int + self.parent_idx: int def clone(self): raise NotImplementedError() @@ -105,7 +106,9 @@ def __repr__(self): return f"Individual(idx={self.idx}, fitness={self.fitness}, genome={self.genome}))" def clone(self) -> "IndividualSingleGenome": - return IndividualSingleGenome(self.fitness, self.genome.clone()) + ind = IndividualSingleGenome(self.fitness, self.genome.clone()) + ind.parent_idx = self.idx + return ind def mutate(self, mutation_rate: float, rng: np.random.RandomState) -> None: only_silent_mutations = self._mutate_genome(self.genome, mutation_rate, rng) @@ -149,7 +152,9 @@ def __init__(self, fitness: Union[float, None], genome: List[Genome]) -> None: self.genome: List[Genome] = genome def clone(self) -> "IndividualMultiGenome": - return IndividualMultiGenome(self.fitness, [g.clone() for g in self.genome]) + ind = IndividualMultiGenome(self.fitness, [g.clone() for g in self.genome]) + ind.parent_idx = self.idx + return ind def mutate(self, mutation_rate: float, rng: np.random.RandomState) -> None: for g in self.genome: diff --git a/test/test_ea_mu_plus_lambda.py b/test/test_ea_mu_plus_lambda.py index 8a258a4d..5ed9f750 100644 --- a/test/test_ea_mu_plus_lambda.py +++ b/test/test_ea_mu_plus_lambda.py @@ -59,6 +59,25 @@ def objective(ind): assert ind.idx == len(pop.parents) + idx +def test_offspring_individuals_are_assigned_correct_parent_indices( + population_params, genome_params +): + def objective(ind): + ind.fitness = 0.0 + return ind + + population_params["n_parents"] = 1 + pop = cgp.Population(**population_params, genome_params=genome_params) + + ea = cgp.ea.MuPlusLambda(10, 10, 1) + ea.initialize_fitness_parents(pop, objective) + + offsprings = ea._create_new_offspring_generation(pop) + + for ind in offsprings: + assert ind.parent_idx == 0 + + def test_local_search_is_only_applied_to_best_k_individuals( population_params, local_search_params ):