Skip to content

Commit

Permalink
Added unit test for counting the number of objective calls. And test …
Browse files Browse the repository at this point in the history
…to ensure finite evolve
  • Loading branch information
HenrikMettler committed Nov 4, 2020
1 parent dba154c commit 1250a58
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
8 changes: 4 additions & 4 deletions cgp/ea/mu_plus_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def __init__(
self.local_search = local_search
self.k_local_search = k_local_search

self.n_objective_calls = 0
self.n_objective_calls: int = 0

def initialize_fitness_parents(
self, pop: Population, objective: Callable[[IndividualBase], IndividualBase]
Expand Down Expand Up @@ -104,8 +104,6 @@ def step(
# population instead of the other way around
combined = offsprings + pop.parents

self.update_n_objective_calls(combined)

# we follow a two-step process for selection of new parents:
# we first determine the fitness for all individuals, then, if
# applicable, we apply local search to the k_local_search
Expand Down Expand Up @@ -150,6 +148,8 @@ def _compute_fitness(
self, combined: List[IndividualBase], objective: Callable[[IndividualBase], IndividualBase]
) -> List[IndividualBase]:

self.update_n_objective_calls(combined)

# computes fitness on all individuals, objective functions
# should return immediately if fitness is not None
if self.n_processes == 1:
Expand Down Expand Up @@ -193,5 +193,5 @@ def update_n_objective_calls(self, combined: List[IndividualBase]) -> None:
i.e., for which the objective function will be evaluated.
"""
for individual in combined:
if individual.fitness is not None:
if individual.fitness is None:
self.n_objective_calls += 1
40 changes: 40 additions & 0 deletions test/test_ea_mu_plus_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,43 @@ def test_create_new_parent_population(population_params, genome_params, ea_param
# we picked the first three individuals
new_parents = ea._create_new_parent_population(3, pop.parents)
assert new_parents == pop.parents[:3]


def test_update_n_objective_calls(population_params, genome_params, ea_params):
def objective(individual):
individual.fitness = float(individual.idx)
return individual

n_objective_calls_expected = 0
pop = cgp.Population(**population_params, genome_params=genome_params)
ea = cgp.ea.MuPlusLambda(**ea_params)
assert ea.n_objective_calls == n_objective_calls_expected

ea.initialize_fitness_parents(pop, objective)
n_objective_calls_expected = population_params["n_parents"]
assert ea.n_objective_calls == n_objective_calls_expected

n_generations = 100
for _ in range(n_generations):
offsprings = ea._create_new_offspring_generation(pop)
combined = offsprings + pop.parents
n_objective_calls_expected += sum([1 for ind in combined if ind.fitness is None])
combined = ea._compute_fitness(combined, objective)
assert n_objective_calls_expected == ea.n_objective_calls


def test_update_n_objective_calls_mutation_rate_one(population_params, genome_params, ea_params):
def objective(individual):
individual.fitness = float(individual.idx)
return individual

population_params["mutation_rate"] = 1.0
pop = cgp.Population(**population_params, genome_params=genome_params)
ea = cgp.ea.MuPlusLambda(**ea_params)
ea.initialize_fitness_parents(pop, objective)
n_objective_calls_expected = population_params["n_parents"]
n_step_calls = 100
for idx_current_step in range(n_step_calls):
ea.step(pop, objective)
n_objective_calls_expected += ea_params["n_offsprings"]
assert ea.n_objective_calls == n_objective_calls_expected
18 changes: 18 additions & 0 deletions test/test_hl_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,24 @@ def f1(x):
assert abs(pop.champion.fitness) == pytest.approx(0.0)


def test_finite_max_generations_or_max_objective_calls(
population_params, genome_params, ea_params
):
def objective(individual):
individual.fitness = float(individual.idx)
return individual

pop = cgp.Population(**population_params, genome_params=genome_params)
ea = cgp.ea.MuPlusLambda(**ea_params)
evolve_params = {
"max_generations": np.inf,
"min_fitness": 0,
"max_objective_calls": np.inf,
}
with pytest.raises(ValueError):
cgp.evolve(pop, objective, ea, **evolve_params)


def _objective_speedup_parallel_evolve(individual):

time.sleep(0.25)
Expand Down

0 comments on commit 1250a58

Please sign in to comment.