Skip to content

Commit

Permalink
Fixed bug in automatic epsilon lexicase, and added example.
Browse files Browse the repository at this point in the history
  • Loading branch information
Eddie Pantridge authored and Eddie Pantridge committed Sep 3, 2016
1 parent 0edf058 commit c7f99fa
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 2 deletions.
4 changes: 2 additions & 2 deletions deap/tools/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,9 @@ def selAutomaticEpsilonLexicase(individuals, k):
random.shuffle(cases)

while len(cases) > 0 and len(candidates) > 1:
errors_for_this_case = [x.fitness.values[cases[0] for x in candidates]
errors_for_this_case = [x.fitness.values[cases[0]] for x in candidates]
median_val = np.median(errors_for_this_case)
median_absolute_deviation = np.median([abs(x - median_val) for x in candidates])
median_absolute_deviation = np.median([abs(x - median_val) for x in errors_for_this_case])
if fit_weights[cases[0]] > 0:
best_val_for_case = max(errors_for_this_case)
min_val_to_survive = best_val_for_case - median_absolute_deviation
Expand Down
92 changes: 92 additions & 0 deletions examples/gp/symbreg_epsilon_lexicase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# This file is part of EAP.
#
# EAP is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# EAP is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with EAP. If not, see <http://www.gnu.org/licenses/>.

import operator
import math
import random

import numpy

from deap import algorithms
from deap import base
from deap import creator
from deap import tools
from deap import gp

# Define new functions
def protectedDiv(left, right):
try:
return left / right
except ZeroDivisionError:
return 1

pset = gp.PrimitiveSet("MAIN", 1)
pset.addPrimitive(operator.add, 2)
pset.addPrimitive(operator.sub, 2)
pset.addPrimitive(operator.mul, 2)
pset.addPrimitive(protectedDiv, 2)
pset.addPrimitive(operator.neg, 1)
pset.addPrimitive(math.cos, 1)
pset.addPrimitive(math.sin, 1)
pset.addEphemeralConstant("rand101", lambda: random.randint(-1,1))
pset.renameArguments(ARG0='x')

creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", gp.PrimitiveTree, fitness=creator.FitnessMin)

toolbox = base.Toolbox()
toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=2)
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.expr)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("compile", gp.compile, pset=pset)

def evalSymbReg(individual, points):
# Transform the tree expression in a callable function
func = toolbox.compile(expr=individual)
# Evaluate the mean squared error between the expression
# and the real function : x**4 + x**3 + x**2 + x
sqerrors = ((func(x) - x**4 - x**3 - x**2 - x)**2 for x in points)
return math.fsum(sqerrors) / len(points),

toolbox.register("evaluate", evalSymbReg, points=[x/10. for x in range(-10,10)])
toolbox.register("select", tools.selAutomaticEpsilonLexicase)
toolbox.register("mate", gp.cxOnePoint)
toolbox.register("expr_mut", gp.genFull, min_=0, max_=2)
toolbox.register("mutate", gp.mutUniform, expr=toolbox.expr_mut, pset=pset)

toolbox.decorate("mate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17))
toolbox.decorate("mutate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17))

def main():
#random.seed(318)

pop = toolbox.population(n=300)
hof = tools.HallOfFame(1)

stats_fit = tools.Statistics(lambda ind: ind.fitness.values)
stats_size = tools.Statistics(len)
mstats = tools.MultiStatistics(fitness=stats_fit, size=stats_size)
mstats.register("avg", numpy.mean)
mstats.register("std", numpy.std)
mstats.register("min", numpy.min)
mstats.register("max", numpy.max)

pop, log = algorithms.eaSimple(pop, toolbox, 0.5, 0.1, 40, stats=mstats,
halloffame=hof, verbose=True)
# print log
return pop, log, hof

if __name__ == "__main__":
main()

0 comments on commit c7f99fa

Please sign in to comment.