Note
Click here to download the full example code
Example demonstrating the use of the caching decorator with functional equivalance checkingΒΆ
Caches the results of fitness evaluations in a pickle file
(example_fec_caching_cache.pkl
). To illustrate its practical use,
compare the runtime of this script when you first call it vs. the
second time and when you comment out the decorator on
inner_objective.
import functools
import multiprocessing as mp
import time
import numpy as np
import cgp
We define the target function for this example.
def f_target(x):
return x ** 2 + x + 1.0
We then define the objective function for the evolutionary algorithm: It consists of an inner objective which we wrap with the caching decorator. This decorator specifies a pickle file that will be used for caching results of fitness evaluations. In addition the decorator accepts keyword arguments that specifiy the statistic of the samples used for evaluation. The inner objective is then used by the objective function to compute (or retrieve from cache) the fitness of the individual.
@cgp.utils.disk_cache(
"example_fec_caching_cache.pkl",
compute_key=functools.partial(
cgp.utils.compute_key_from_numpy_evaluation_and_args,
_seed=12345,
_min_value=-10.0,
_max_value=10.0,
_batch_size=5,
),
file_lock=mp.Lock(),
)
def inner_objective(ind):
"""The caching decorator uses the return values generated from
providing random inputs to ind.to_numpy() to identify functionally
indentical individuals and avoid reevaluating them. Note that
caching only makes sense for deterministic objective functions, as
it assumes that identical phenotypes will always return the same
fitness values.
"""
f = ind.to_func()
loss = []
for x_0 in np.linspace(-2.0, 2.0, 100):
y = f(x_0)
loss.append((f_target(x_0) - y) ** 2)
time.sleep(0.25) # emulate long fitness evaluation
return np.mean(loss)
def objective(individual):
if not individual.fitness_is_None():
return individual
individual.fitness = -inner_objective(individual)
return individual
Next, we define the parameters for the population, the genome of individuals, and the evolutionary algorithm.
params = {
"population_params": {"n_parents": 10, "seed": 8188211},
"ea_params": {
"n_offsprings": 10,
"tournament_size": 1,
"mutation_rate": 0.05,
"n_processes": 1,
},
"genome_params": {
"n_inputs": 1,
"n_outputs": 1,
"n_columns": 10,
"n_rows": 2,
"levels_back": 2,
"primitives": (cgp.Add, cgp.Sub, cgp.Mul, cgp.ConstantFloat),
},
"evolve_params": {"max_generations": 200, "termination_fitness": -1e-12},
}
We then create a Population instance and instantiate the evolutionary algorithm.
pop = cgp.Population(**params["population_params"], genome_params=params["genome_params"])
ea = cgp.ea.MuPlusLambda(**params["ea_params"])
Finally, we call the evolve method to perform the evolutionary search.
cgp.evolve(pop, objective, ea, **params["evolve_params"], print_progress=True)
print(f"evolved function: {pop.champion.to_sympy()}")
Out:
[2/200] max fitness: -2.360269360269361[K
[3/200] max fitness: -2.360269360269361[K
[4/200] max fitness: -2.360269360269361[K
[5/200] max fitness: -1.0[K
[6/200] max fitness: -1.0[K
[7/200] max fitness: -1.0[K
[8/200] max fitness: -1.0[K
[9/200] max fitness: -1.0[K
[10/200] max fitness: -1.0[K
[11/200] max fitness: -1.0[K
[12/200] max fitness: -1.0[K
[13/200] max fitness: -1.0[K
[14/200] max fitness: -1.0[K
[15/200] max fitness: -1.0[K
[16/200] max fitness: -1.0[K
[17/200] max fitness: -1.0[K
[18/200] max fitness: -1.0[K
[19/200] max fitness: -1.0[K
[20/200] max fitness: -1.0[K
[21/200] max fitness: -1.0[K
[22/200] max fitness: -1.0[K
[23/200] max fitness: -1.0[K
[24/200] max fitness: -1.0[K
[25/200] max fitness: -1.0[K
[26/200] max fitness: -1.0[K
[27/200] max fitness: -1.0[K
[28/200] max fitness: -1.0[K
[29/200] max fitness: -1.0[K
[30/200] max fitness: -1.0[K
[31/200] max fitness: -1.0[K
[32/200] max fitness: -1.0[K
[33/200] max fitness: -1.0[K
[34/200] max fitness: -1.0[K
[35/200] max fitness: -1.0[K
[36/200] max fitness: -1.0[K
[37/200] max fitness: -1.0[K
[38/200] max fitness: -1.0[K
[39/200] max fitness: -1.0[K
[40/200] max fitness: -1.0[K
[41/200] max fitness: -1.0[K
[42/200] max fitness: -1.0[K
[43/200] max fitness: -1.0[K
[44/200] max fitness: -1.0[K
[45/200] max fitness: -1.0[K
[46/200] max fitness: -1.0[K
[47/200] max fitness: -1.0[K
[48/200] max fitness: -1.0[K
[49/200] max fitness: -1.0[K
[50/200] max fitness: -1.0[K
[51/200] max fitness: -1.0[K
[52/200] max fitness: -1.0[K
[53/200] max fitness: -1.0[K
[54/200] max fitness: -1.0[K
[55/200] max fitness: -1.0[K
[56/200] max fitness: -1.0[K
[57/200] max fitness: -1.0[K
[58/200] max fitness: -1.0[K
[59/200] max fitness: -1.0[K
[60/200] max fitness: -1.0[K
[61/200] max fitness: -1.0[K
[62/200] max fitness: -1.0[K
[63/200] max fitness: -1.0[K
[64/200] max fitness: -1.0[K
[65/200] max fitness: -1.0[K
[66/200] max fitness: -1.0[K
[67/200] max fitness: -1.0[K
[68/200] max fitness: -1.0[K
[69/200] max fitness: -1.0[K
[70/200] max fitness: -1.0[K
[71/200] max fitness: -1.0[K
[72/200] max fitness: -1.0[K
[73/200] max fitness: -1.0[K
[74/200] max fitness: -1.0[K
[75/200] max fitness: -1.0[K
[76/200] max fitness: -1.0[K
[77/200] max fitness: -1.0[K
[78/200] max fitness: -1.0[K
[79/200] max fitness: -1.0[K
[80/200] max fitness: -1.0[K
[81/200] max fitness: -1.0[K
[82/200] max fitness: -1.0[K
[83/200] max fitness: -1.0[K
[84/200] max fitness: -1.0[K
[85/200] max fitness: -1.0[K
[86/200] max fitness: -1.0[K
[87/200] max fitness: -1.0[K
[88/200] max fitness: -1.0[K
[89/200] max fitness: -1.0[K
[90/200] max fitness: -1.0[K
[91/200] max fitness: -1.0[K
[92/200] max fitness: -1.0[K
[93/200] max fitness: -1.0[K
[94/200] max fitness: -1.0[K
[95/200] max fitness: -1.0[K
[96/200] max fitness: -1.0[K
[97/200] max fitness: -1.0[K
[98/200] max fitness: -1.0[K
[99/200] max fitness: -1.0[K
[100/200] max fitness: -1.0[K
[101/200] max fitness: -1.0[K
[102/200] max fitness: -1.0[K
[103/200] max fitness: -1.0[K
[104/200] max fitness: -1.0[K
[105/200] max fitness: -1.0[K
[106/200] max fitness: -1.0[K
[107/200] max fitness: -1.0[K
[108/200] max fitness: -1.0[K
[109/200] max fitness: -1.0[K
[110/200] max fitness: -1.0[K
[111/200] max fitness: -1.0[K
[112/200] max fitness: -1.0[K
[113/200] max fitness: -1.0[K
[114/200] max fitness: -1.0[K
[115/200] max fitness: -1.0[K
[116/200] max fitness: -1.0[K
[117/200] max fitness: -1.0[K
[118/200] max fitness: -1.0[K
[119/200] max fitness: -1.0[K
[120/200] max fitness: -1.0[K
[121/200] max fitness: -1.0[K
[122/200] max fitness: -4.930380657631324e-34[K
evolved function: x_0**2 + x_0 + 1.0
Total running time of the script: ( 0 minutes 13.252 seconds)