Example for evolutionary regression with genome reordering

Example demonstrating the effect of genome reordering.

References

Goldman B.W., Punch W.F. (2014): Analysis of Cartesian Genetic Programming’s Evolutionary Mechanisms DOI: 10.1109/TEVC.2014.2324539

# The docopt str is added explicitly to ensure compatibility with
# sphinx-gallery.
docopt_str = """
   Usage:
     example_reorder.py [--max-generations=<N>]

   Options:
     -h --help
     --max-generations=<N>  Maximum number of generations [default: 300]
"""

import matplotlib.pyplot as plt
import numpy as np
import scipy.constants
from docopt import docopt

import cgp

args = docopt(docopt_str)

We first define a target function.

def f_target(x):
    return x ** 2 + 1.0

Then we define the objective function for the evolution. It uses the mean-squared error between the output of the expression represented by a given individual and the target function evaluated on a set of random points.

def objective(individual):
    if not individual.fitness_is_None():
        return individual

    n_function_evaluations = 1000

    np.random.seed(1234)

    f = individual.to_func()
    loss = 0
    for x in np.random.uniform(-4, 4, n_function_evaluations):
        # the callable returned from `to_func` accepts and returns
        # lists; accordingly we need to pack the argument and unpack
        # the return value
        y = f(x)
        loss += (f_target(x) - y) ** 2

    individual.fitness = -loss / n_function_evaluations

    return individual

Next, we set up the evolutionary search. We first define the parameters for the population, the genome of individuals, and two evolutionary algorithms without (default) and with genome reordering.

population_params = {"n_parents": 1, "seed": 818821}

genome_params = {
    "n_inputs": 1,
    "n_outputs": 1,
    "n_columns": 12,
    "n_rows": 1,
    "levels_back": None,
    "primitives": (cgp.Add, cgp.Sub, cgp.Mul, cgp.ConstantFloat),
}

ea_params = {"n_offsprings": 4, "mutation_rate": 0.03, "n_processes": 2}
ea_params_with_reorder = {
    "n_offsprings": 4,
    "mutation_rate": 0.03,
    "n_processes": 2,
    "reorder_genome": True,
}

evolve_params = {"max_generations": int(args["--max-generations"]), "termination_fitness": 0.0}

We create two populations that will be evolved

pop = cgp.Population(**population_params, genome_params=genome_params)
pop_with_reorder = cgp.Population(**population_params, genome_params=genome_params)

and two instances of the (mu + lambda) evolutionary algorithm

ea = cgp.ea.MuPlusLambda(**ea_params)
ea_with_reorder = cgp.ea.MuPlusLambda(**ea_params_with_reorder)

We define two callbacks for recording of fitness over generations

history = {}
history["fitness_champion"] = []


def recording_callback(pop):
    history["fitness_champion"].append(pop.champion.fitness)


history_with_reorder = {}
history_with_reorder["fitness_champion"] = []


def recording_callback_with_reorder(pop):
    history_with_reorder["fitness_champion"].append(pop.champion.fitness)

and finally perform the evolution of the two populations

cgp.evolve(
    pop, objective, ea, **evolve_params, print_progress=True, callback=recording_callback,
)

cgp.evolve(
    pop_with_reorder,
    objective,
    ea_with_reorder,
    **evolve_params,
    print_progress=True,
    callback=recording_callback_with_reorder,
)

Out:

[2/300] max fitness: -107.98528863498699
[3/300] max fitness: -107.98528863498699
[4/300] max fitness: -73.78312067622548
[5/300] max fitness: -67.0965931324104
[6/300] max fitness: -67.0965931324104
[7/300] max fitness: -67.0965931324104
[8/300] max fitness: -67.0965931324104
[9/300] max fitness: -67.0965931324104
[10/300] max fitness: -67.0965931324104
[11/300] max fitness: -67.0965931324104
[12/300] max fitness: -67.0965931324104
[13/300] max fitness: -67.0965931324104
[14/300] max fitness: -67.0965931324104
[15/300] max fitness: -67.0965931324104
[16/300] max fitness: -67.0965931324104
[17/300] max fitness: -54.97072455431481
[18/300] max fitness: -54.97072455431481
[19/300] max fitness: -1.0
[20/300] max fitness: -1.0
[21/300] max fitness: -1.0
[22/300] max fitness: -1.0
[23/300] max fitness: -1.0
[24/300] max fitness: -1.0
[25/300] max fitness: -1.0
[26/300] max fitness: -1.0
[27/300] max fitness: -1.0
[28/300] max fitness: -1.0
[29/300] max fitness: -1.0
[30/300] max fitness: -1.0
[31/300] max fitness: -1.0
[32/300] max fitness: -1.0
[33/300] max fitness: -1.0
[34/300] max fitness: -1.0
[35/300] max fitness: -1.0
[36/300] max fitness: -1.0
[37/300] max fitness: -1.0
[38/300] max fitness: -1.0
[39/300] max fitness: -1.0
[40/300] max fitness: -1.0
[41/300] max fitness: -1.0
[42/300] max fitness: -1.0
[43/300] max fitness: -1.0
[44/300] max fitness: -1.0
[45/300] max fitness: -1.0
[46/300] max fitness: -1.0
[47/300] max fitness: -1.0
[48/300] max fitness: -1.0
[49/300] max fitness: -1.0
[50/300] max fitness: -1.0
[51/300] max fitness: -1.0
[52/300] max fitness: -1.0
[53/300] max fitness: -1.0
[54/300] max fitness: -1.0
[55/300] max fitness: -1.0
[56/300] max fitness: -1.0
[57/300] max fitness: -1.0
[58/300] max fitness: -1.0
[59/300] max fitness: -1.0
[60/300] max fitness: -1.0
[61/300] max fitness: -1.0
[62/300] max fitness: -1.0
[63/300] max fitness: -1.0
[64/300] max fitness: -1.0
[65/300] max fitness: -1.0
[66/300] max fitness: -1.0
[67/300] max fitness: -1.0
[68/300] max fitness: -1.0
[69/300] max fitness: -1.0
[70/300] max fitness: -1.0
[71/300] max fitness: -1.0
[72/300] max fitness: -1.0
[73/300] max fitness: -1.0
[74/300] max fitness: -1.0
[75/300] max fitness: -1.0
[76/300] max fitness: -1.0
[77/300] max fitness: -1.0
[78/300] max fitness: -1.0
[79/300] max fitness: -1.0
[80/300] max fitness: -1.0
[81/300] max fitness: -1.0
[82/300] max fitness: -1.0
[83/300] max fitness: -1.0
[84/300] max fitness: -1.0
[85/300] max fitness: -1.0
[86/300] max fitness: -1.0
[87/300] max fitness: -1.0
[88/300] max fitness: -1.0
[89/300] max fitness: -1.0
[90/300] max fitness: -1.0
[91/300] max fitness: -1.0
[92/300] max fitness: -1.0
[93/300] max fitness: -1.0
[94/300] max fitness: -1.0
[95/300] max fitness: -1.0
[96/300] max fitness: -1.0
[97/300] max fitness: -1.0
[98/300] max fitness: -1.0
[99/300] max fitness: -1.0
[100/300] max fitness: -1.0
[101/300] max fitness: -1.0
[102/300] max fitness: -1.0
[103/300] max fitness: -1.0
[104/300] max fitness: -1.0
[105/300] max fitness: -1.0
[106/300] max fitness: -1.0
[107/300] max fitness: -1.0
[108/300] max fitness: -1.0
[109/300] max fitness: -1.0
[110/300] max fitness: -1.0
[111/300] max fitness: -1.0
[112/300] max fitness: -1.0
[113/300] max fitness: -1.0
[114/300] max fitness: -1.0
[115/300] max fitness: -1.0
[116/300] max fitness: -1.0
[117/300] max fitness: -1.0
[118/300] max fitness: -1.0
[119/300] max fitness: -1.0
[120/300] max fitness: -1.0
[121/300] max fitness: -1.0
[122/300] max fitness: -1.0
[123/300] max fitness: -1.0
[124/300] max fitness: -1.0
[125/300] max fitness: -1.0
[126/300] max fitness: -1.0
[127/300] max fitness: -1.0
[128/300] max fitness: -1.0
[129/300] max fitness: -1.0
[130/300] max fitness: -1.0
[131/300] max fitness: -1.0
[132/300] max fitness: -1.0
[133/300] max fitness: -1.0
[134/300] max fitness: -1.0
[135/300] max fitness: -1.0
[136/300] max fitness: -1.0
[137/300] max fitness: -1.0
[138/300] max fitness: -1.0
[139/300] max fitness: -1.0
[140/300] max fitness: -1.0
[141/300] max fitness: -1.0
[142/300] max fitness: -1.0
[143/300] max fitness: -1.0
[144/300] max fitness: -1.0
[145/300] max fitness: -1.0
[146/300] max fitness: -1.0
[147/300] max fitness: -1.0
[148/300] max fitness: -1.0
[149/300] max fitness: -1.0
[150/300] max fitness: -1.0
[151/300] max fitness: -1.0
[152/300] max fitness: -1.0
[153/300] max fitness: -1.0
[154/300] max fitness: -1.0
[155/300] max fitness: -1.0
[156/300] max fitness: -1.0
[157/300] max fitness: -1.0
[158/300] max fitness: -1.0
[159/300] max fitness: -1.0
[160/300] max fitness: -1.0
[161/300] max fitness: -1.0
[162/300] max fitness: -1.0
[163/300] max fitness: -1.0
[164/300] max fitness: -1.0
[165/300] max fitness: -1.0
[166/300] max fitness: -1.0
[167/300] max fitness: -1.0
[168/300] max fitness: -1.0
[169/300] max fitness: -1.0
[170/300] max fitness: -1.0
[171/300] max fitness: -1.0
[172/300] max fitness: -1.0
[173/300] max fitness: -1.0
[174/300] max fitness: -1.0
[175/300] max fitness: -1.0
[176/300] max fitness: -1.0
[177/300] max fitness: -1.0
[178/300] max fitness: -1.0
[179/300] max fitness: -1.0
[180/300] max fitness: -1.0
[181/300] max fitness: -1.0
[182/300] max fitness: -1.0
[183/300] max fitness: -1.0
[184/300] max fitness: -1.0
[185/300] max fitness: -1.0
[186/300] max fitness: -1.0
[187/300] max fitness: -1.0
[188/300] max fitness: -1.0
[189/300] max fitness: -1.0
[190/300] max fitness: -1.0
[191/300] max fitness: -1.0
[192/300] max fitness: -1.0
[193/300] max fitness: -1.0
[194/300] max fitness: -1.0
[195/300] max fitness: -1.0
[196/300] max fitness: -1.0
[197/300] max fitness: -1.0
[198/300] max fitness: -1.0
[199/300] max fitness: -1.0
[200/300] max fitness: -1.0
[201/300] max fitness: -1.0
[202/300] max fitness: -1.0
[203/300] max fitness: -1.0
[204/300] max fitness: -1.0
[205/300] max fitness: -1.0
[206/300] max fitness: -1.0
[207/300] max fitness: -1.0
[208/300] max fitness: -1.0
[209/300] max fitness: -1.0
[210/300] max fitness: -1.0
[211/300] max fitness: -1.0
[212/300] max fitness: -1.0
[213/300] max fitness: -1.0
[214/300] max fitness: -1.0
[215/300] max fitness: -1.0
[216/300] max fitness: -1.0
[217/300] max fitness: -1.0
[218/300] max fitness: -1.0
[219/300] max fitness: -1.0
[220/300] max fitness: -1.0
[221/300] max fitness: -1.0
[222/300] max fitness: -1.0
[223/300] max fitness: -1.0
[224/300] max fitness: -1.0
[225/300] max fitness: -1.0
[226/300] max fitness: -1.0
[227/300] max fitness: -1.0
[228/300] max fitness: -1.0
[229/300] max fitness: -1.0
[230/300] max fitness: -1.0
[231/300] max fitness: -1.0
[232/300] max fitness: -1.0
[233/300] max fitness: -1.0
[234/300] max fitness: -1.0
[235/300] max fitness: -1.0
[236/300] max fitness: -1.0
[237/300] max fitness: -1.0
[238/300] max fitness: -1.0
[239/300] max fitness: -1.0
[240/300] max fitness: -1.0
[241/300] max fitness: -1.0
[242/300] max fitness: -1.0
[243/300] max fitness: 0.0

[2/300] max fitness: -49.56594653387306
[3/300] max fitness: -1.0
[4/300] max fitness: -1.0
[5/300] max fitness: -1.0
[6/300] max fitness: -1.0
[7/300] max fitness: -1.0
[8/300] max fitness: -1.0
[9/300] max fitness: -1.0
[10/300] max fitness: -1.0
[11/300] max fitness: -1.0
[12/300] max fitness: -1.0
[13/300] max fitness: -1.0
[14/300] max fitness: -1.0
[15/300] max fitness: -1.0
[16/300] max fitness: -1.0
[17/300] max fitness: -1.0
[18/300] max fitness: -1.0
[19/300] max fitness: -1.0
[20/300] max fitness: -1.0
[21/300] max fitness: -1.0
[22/300] max fitness: -1.0
[23/300] max fitness: -1.0
[24/300] max fitness: -1.0
[25/300] max fitness: -1.0
[26/300] max fitness: -1.0
[27/300] max fitness: -1.0
[28/300] max fitness: -1.0
[29/300] max fitness: -1.0
[30/300] max fitness: -1.0
[31/300] max fitness: -1.0
[32/300] max fitness: -1.0
[33/300] max fitness: -1.0
[34/300] max fitness: -1.0
[35/300] max fitness: -1.0
[36/300] max fitness: -1.0
[37/300] max fitness: -1.0
[38/300] max fitness: -1.0
[39/300] max fitness: -1.0
[40/300] max fitness: -1.0
[41/300] max fitness: -1.0
[42/300] max fitness: -1.0
[43/300] max fitness: -1.0
[44/300] max fitness: -1.0
[45/300] max fitness: -1.0
[46/300] max fitness: -1.0
[47/300] max fitness: -1.0
[48/300] max fitness: -1.0
[49/300] max fitness: -1.0
[50/300] max fitness: -1.0
[51/300] max fitness: -1.0
[52/300] max fitness: -1.0
[53/300] max fitness: -1.0
[54/300] max fitness: -1.0
[55/300] max fitness: -1.0
[56/300] max fitness: -1.0
[57/300] max fitness: -1.0
[58/300] max fitness: -1.0
[59/300] max fitness: -1.0
[60/300] max fitness: -1.0
[61/300] max fitness: -1.0
[62/300] max fitness: -1.0
[63/300] max fitness: -1.0
[64/300] max fitness: -1.0
[65/300] max fitness: -1.0
[66/300] max fitness: -1.0
[67/300] max fitness: -1.0
[68/300] max fitness: -1.0
[69/300] max fitness: -1.0
[70/300] max fitness: -1.0
[71/300] max fitness: -1.0
[72/300] max fitness: -1.0
[73/300] max fitness: -1.0
[74/300] max fitness: -1.0
[75/300] max fitness: -1.0
[76/300] max fitness: -1.0
[77/300] max fitness: -1.0
[78/300] max fitness: -1.0
[79/300] max fitness: -1.0
[80/300] max fitness: -1.0
[81/300] max fitness: -1.0
[82/300] max fitness: -1.0
[83/300] max fitness: -1.0
[84/300] max fitness: -1.0
[85/300] max fitness: -1.0
[86/300] max fitness: -1.0
[87/300] max fitness: -1.0
[88/300] max fitness: -1.0
[89/300] max fitness: -1.0
[90/300] max fitness: -1.0
[91/300] max fitness: -1.0
[92/300] max fitness: -1.0
[93/300] max fitness: -1.0
[94/300] max fitness: -1.0
[95/300] max fitness: -1.0
[96/300] max fitness: -1.0
[97/300] max fitness: -1.0
[98/300] max fitness: -1.0
[99/300] max fitness: -1.0
[100/300] max fitness: -1.0
[101/300] max fitness: -1.0
[102/300] max fitness: -1.0
[103/300] max fitness: -1.0
[104/300] max fitness: -1.0
[105/300] max fitness: -1.0
[106/300] max fitness: -1.0
[107/300] max fitness: -1.0
[108/300] max fitness: -1.0
[109/300] max fitness: -1.0
[110/300] max fitness: -1.0
[111/300] max fitness: -1.0
[112/300] max fitness: -1.0
[113/300] max fitness: -1.0
[114/300] max fitness: -1.0
[115/300] max fitness: -1.0
[116/300] max fitness: -1.0
[117/300] max fitness: -1.0
[118/300] max fitness: -1.0
[119/300] max fitness: -1.0
[120/300] max fitness: -1.0
[121/300] max fitness: -1.0
[122/300] max fitness: -1.0
[123/300] max fitness: -1.0
[124/300] max fitness: -1.0
[125/300] max fitness: -1.0
[126/300] max fitness: -1.0
[127/300] max fitness: -1.0
[128/300] max fitness: -1.0
[129/300] max fitness: -1.0
[130/300] max fitness: -1.0
[131/300] max fitness: -1.0
[132/300] max fitness: -1.0
[133/300] max fitness: -1.0
[134/300] max fitness: -1.0
[135/300] max fitness: -1.0
[136/300] max fitness: -1.0
[137/300] max fitness: -1.0
[138/300] max fitness: -1.0
[139/300] max fitness: -1.0
[140/300] max fitness: -1.0
[141/300] max fitness: -1.0
[142/300] max fitness: -1.0
[143/300] max fitness: -1.0
[144/300] max fitness: -1.0
[145/300] max fitness: -1.0
[146/300] max fitness: -1.0
[147/300] max fitness: -1.0
[148/300] max fitness: -1.0
[149/300] max fitness: -1.0
[150/300] max fitness: -1.0
[151/300] max fitness: -1.0
[152/300] max fitness: -1.0
[153/300] max fitness: -1.0
[154/300] max fitness: -1.0
[155/300] max fitness: -1.0
[156/300] max fitness: -1.0
[157/300] max fitness: -1.0
[158/300] max fitness: -1.0
[159/300] max fitness: -1.0
[160/300] max fitness: -1.0
[161/300] max fitness: -1.0
[162/300] max fitness: -1.0
[163/300] max fitness: -1.0
[164/300] max fitness: -1.0
[165/300] max fitness: -1.0
[166/300] max fitness: -1.0
[167/300] max fitness: -1.0
[168/300] max fitness: -1.0
[169/300] max fitness: -1.0
[170/300] max fitness: -1.0
[171/300] max fitness: -1.0
[172/300] max fitness: 0.0

After finishing the evolution, we plot the evolution of the fittest individual with and without genome reordering

width = 9.0
fig = plt.figure(1, figsize=[width, width / scipy.constants.golden])

plt.plot(history["fitness_champion"], label="Champion")
plt.plot(history_with_reorder["fitness_champion"], label="Champion with reorder")

plt.xlabel("Generation")
plt.ylabel("Fitness")
plt.legend(["Champion", "Champion with reorder"])

plt.yscale("symlog")
plt.ylim(-1.0e2, 0.1)
plt.axhline(0.0, color="0.7")

fig.savefig("example_reorder.pdf", dpi=300)
example reorder

Total running time of the script: ( 0 minutes 3.935 seconds)

Gallery generated by Sphinx-Gallery