alice/code/evolve.py

77 lines
3.0 KiB
Python

import random
from deap import creator, base, tools, algorithms
import numpy as np
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", np.ndarray, fitness=creator.FitnessMax)
toolbox = base.Toolbox()
#toolbox.register("attr_bool", random.randint, 0, 1) # non-numpy non-float version
toolbox.register("attr_float", random.random)
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_float, n=100)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
def linearFitness(individual):
'''selection pressure for genome values to be numpy.arange(start=0.0, stop=1.0, step=1/len(genome))'''
import numpy as np
a = np.arange(0, 1, 1.0/len(individual))
b = np.array(individual)
return 1.0-np.sum(np.abs(a-b))/(len(individual)*0.5),
def cxTwoPointCopy(ind1, ind2):
"""Execute a two points crossover with copy on the input individuals. The
copy is required because the slicing in numpy returns a view of the data,
which leads to a self overwriting in the swap operation. It prevents
::
>>> import numpy as np
>>> a = np.array((1,2,3,4))
>>> b = np.array((5,6,7,8))
>>> a[1:3], b[1:3] = b[1:3], a[1:3]
>>> print(a)
[1 6 7 4]
>>> print(b)
[5 6 7 8]
"""
size = len(ind1)
cxpoint1 = random.randint(1, size)
cxpoint2 = random.randint(1, size - 1)
if cxpoint2 >= cxpoint1:
cxpoint2 += 1
else: # Swap the two cx points
cxpoint1, cxpoint2 = cxpoint2, cxpoint1
ind1[cxpoint1:cxpoint2], ind2[cxpoint1:cxpoint2] = ind2[cxpoint1:cxpoint2].copy(), ind1[cxpoint1:cxpoint2].copy()
return ind1, ind2
toolbox.register("evaluate", linearFitness)
#toolbox.register("mate", tools.cxTwoPoint) # non-numpy non-float version
toolbox.register("mate", cxTwoPointCopy)
#toolbox.register("mutate", tools.mutFlipBit, indpb=0.05) # non-numpy non-float version
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=0.2, indpb=0.05)
toolbox.register("select", tools.selTournament, tournsize=3)
# evolution loop
population = toolbox.population(n=100)
NGEN=500
for gen in range(NGEN):
offspring = algorithms.varAnd(population, toolbox, cxpb=0.5, mutpb=0.1)
# constrain genome values to [0,1]
for offspring_i,individual in enumerate(offspring):
np.clip(np.array(offspring[offspring_i]), 0.0, 1.0)
# Evaluate the individuals with an invalid fitness (not yet evaluated)
invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses):
ind.fitness.values = fit
population = toolbox.select(offspring, k=len(population))
# post-evolution analysis
fitnesses = toolbox.map(toolbox.evaluate, population)
sortedFitnesses = sorted(fitnesses)
bestFitness, worstFitness = sortedFitnesses[0], sortedFitnesses[-1]
print(bestFitness, worstFitness)
bestGenome = tools.selBest(population, k=1)
print(bestGenome)