diff --git a/test/test_ea_mu_plus_lambda.py b/test/test_ea_mu_plus_lambda.py index c9fd10d9..ab81c36b 100644 --- a/test/test_ea_mu_plus_lambda.py +++ b/test/test_ea_mu_plus_lambda.py @@ -69,6 +69,7 @@ def objective(ind): return ind population_params["n_parents"] = 1 + pop = cgp.Population(**population_params, genome_params=genome_params) ea = cgp.ea.MuPlusLambda(10, 10, 1) @@ -125,3 +126,96 @@ def objective(ind): for idx in range(k_local_search, population_params["n_parents"]): assert pop[idx].genome._parameter_names_to_values[""] == pytest.approx(1.0) + +def test_n_offspring_less_than_n_breeding(): + n_offsprings = 10 + n_breedings = 5 + with pytest.raises(ValueError): + _ = cgp.ea.MuPlusLambda(n_offsprings, n_breedings, 1) + + +def test_fitness_wrong_return_type(population_params, genome_params): + def objective(individual): + individual.fitness = 5 + return individual + + pop = cgp.Population(**population_params, genome_params=genome_params) + ea = cgp.ea.MuPlusLambda(10, 10, 1) + ea.initialize_fitness_parents(pop, objective) + + with pytest.raises(ValueError): + ea.step(pop, objective) + + +def test_fitness_initialization(population_params, genome_params): + def objective(individual): + individual.fitness = -1.0 + return individual + + pop = cgp.Population(**population_params, genome_params=genome_params) + + ea = cgp.ea.MuPlusLambda(10, 10, 1) + ea.initialize_fitness_parents(pop, objective) + assert all([ind.fitness is not None for ind in pop.parents]) + + +def test_one_step(population_params, genome_params): + def objective(individual): + individual.fitness = float(individual.idx) + return individual + + pop = cgp.Population(**population_params, genome_params=genome_params) + n_offsprings = 10 + ea = cgp.ea.MuPlusLambda(n_offsprings, 10, 1) + ea.initialize_fitness_parents(pop, objective) + old_parent_ids = sorted([ind.idx for ind in pop.parents]) + ea.step(pop, objective) + new_parent_ids = sorted([ind.idx for ind in pop.parents]) + # After one step, the new parent population should have IDs that + # are offset from the old parent ids by n_offsprings + # This is by construction in this test because the fitness is equal to the id + assert all( + [new_id == old_id + n_offsprings for new_id, old_id in zip(new_parent_ids, old_parent_ids)] + ) + + +def test_fitness_sort(population_params, genome_params): + def objective(individual): + individual.fitness = float(individual.idx) + return individual + + pop = cgp.Population(**population_params, genome_params=genome_params) + n_offsprings = 10 + ea = cgp.ea.MuPlusLambda(n_offsprings, 10, 1) + ea.initialize_fitness_parents(pop, objective) + sorted_parents = ea._sort(pop.parents) + # Assert that the sorting inverted the list of parents (because the fitness is equal to the id) + assert sorted_parents == pop.parents[::-1] + + +def test_create_new_populations(population_params, genome_params): + def objective(individual): + individual.fitness = float(individual.idx) + return individual + + pop = cgp.Population(**population_params, genome_params=genome_params) + n_offsprings = 10 + ea = cgp.ea.MuPlusLambda(n_offsprings, 10, 1) + + ea.initialize_fitness_parents(pop, objective) + + offsprings = ea._create_new_offspring_generation(pop) + assert len(offsprings) == n_offsprings + assert all([ind.idx >= pop.n_parents for ind in offsprings]) + # Assert that all offspring dna are different from all parents dna + offspring_dna = [ind.genome.dna for ind in offsprings] + parent_dna = [ind.genome.dna for ind in pop.parents] + assert all([odna != pdna for odna in offspring_dna for pdna in parent_dna]) + + # Create new "parent" population from the offsprings and assert + # that we picked the 5 best ones (here, by construction, the 5 + # highest ids) + offsprings = ea._compute_fitness(offsprings, objective) + offsprings = ea._sort(offsprings) + new_parents = ea._create_new_parent_population(pop.n_parents, offsprings) + assert [ind.idx for ind in new_parents] == [ind.idx for ind in offsprings[: pop.n_parents]]