Here's a silly example that maybe sheds some light for you:
import copy
import random
import inspyred
def my_bounder(candidate, args):
# The candidate is really 3 different types of things:
# * a discrete value from 21, 42, or 63
# * a continuous value v where 0 <= v <= 100
# * a discrete value between 1 and 10, inclusive
db1 = inspyred.ec.DiscreteBounder([21, 42, 63])
rb = inspyred.ec.Bounder(0, 100)
db2 = inspyred.ec.DiscreteBounder(list(range(1, 11)))
# If there were multiple components that used the same bounder,
# you could just call the relevant function again for that component.
# You don't have to make a new bounding function for each component,
# only for those that have different bounds.
return [db1([candidate[0]], args)[0],
rb([candidate[1]], args)[0],
db2([candidate[2]], args)[0]]
def my_generator(random, args):
return [random.choice([21, 42, 63]),
random.uniform(0, 100),
random.randint(1, 10)]
def my_evaluator(candidates, args):
# This is all just made up. It has no sense or meaning.
# It's just an example.
fitness = []
for cs in candidates:
multiplier = {21: 0.5, 42: 1.5, 63: 2}
discount = [0.9, 0.8, 0.7, 0.65, 0.6, 0.55, 0.5, 0.45, 0.35, 0.25, 0.1]
fit = multiplier[cs[0]] * cs[1] * discount[cs[2] - 1]
fitness.append(fit)
return fitness
def my_mutation(random, candidates, args):
rate = args.setdefault('mutation_rate', 0.1)
mutants = []
for cs in candidates:
mutant = copy.copy(cs)
if random.random() < rate:
dv1 = list(set([21, 42, 63]) - set([cs[0]]))
mutant[0] = random.choice(dv1)
if random.random() < rate:
mutant[1] += random.gauss(0, 5)
if random.random() < rate:
dv2 = list(set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) - set([cs[2]]))
mutant[2] = random.choice(dv2)
mutant = my_bounder(mutant, args)
mutants.append(mutant)
return mutants
prng = random.Random()
prng.seed(12345)
ec = inspyred.ec.EvolutionaryComputation(prng)
ec.terminator = inspyred.ec.terminators.evaluation_termination
ec.variator = [my_mutation]
ec.selector = inspyred.ec.selectors.tournament_selection
ec.replacer = inspyred.ec.replacers.generational_replacement
ec.observer = [inspyred.ec.observers.stats_observer]
final_pop = ec.evolve(generator=my_generator,
evaluator=my_evaluator,
pop_size=10,
maximize=True,
bounder=my_bounder,
num_selected=10,
num_elites=1,
max_evaluations=200,
mutation_rate=0.1)
final_pop.sort(reverse=True)
print(final_pop[0])