Skip to content

One Max Problem

Detailed Version

from deap_er import Fitness, Toolbox, creator, tools

tools.rng.seed(1234)  # disables randomization

NGEN = 1000
CX_PROB = 0.5
MUT_PROB = 0.2


def setup():
    creator.create_type("FitnessMax", Fitness, weights=(1.0,))
    creator.create_type("Individual", list, fitness=creator.FitnessMax)

    toolbox = Toolbox()
    toolbox.register("attr_bool", tools.rng.randint, 0, 1)
    toolbox.register("individual", tools.init_repeat, creator.Individual, toolbox.attr_bool, 100)
    toolbox.register("population", tools.init_repeat, list, toolbox.individual)
    toolbox.register("mate", tools.cx_two_point)
    toolbox.register("mutate", tools.mut_flip_bit, mut_prob=0.05)
    toolbox.register("select", tools.sel_tournament, contestants=3)
    toolbox.register("evaluate", lambda x: sum(x))

    return toolbox


def print_results(best_ind):
    if not all(gene == 1 for gene in best_ind):
        raise RuntimeError("Evolution failed to converge.")
    print("\nEvolution converged correctly.")


def main():
    toolbox = setup()
    population = toolbox.population(size=300)

    fitness = map(toolbox.evaluate, population)
    for ind, fit in zip(population, fitness, strict=False):
        ind.fitness.values = fit
    fits = [ind.fitness.values[0] for ind in population]

    generation = 0
    while max(fits) < 100 and generation < NGEN:
        offspring = toolbox.select(population, len(population))
        offspring = list(map(toolbox.clone, offspring))

        for child1, child2 in zip(offspring[::2], offspring[1::2], strict=False):
            if tools.rng.random() < CX_PROB:
                toolbox.mate(child1, child2)
                del child1.fitness.values
                del child2.fitness.values

        for mutant in offspring:
            if tools.rng.random() < MUT_PROB:
                toolbox.mutate(mutant)
                del mutant.fitness.values

        tools.evaluate_invalid(toolbox, offspring)
        population[:] = offspring
        fits = [ind.fitness.values[0] for ind in population]
        generation += 1

    best_ind = tools.sel_best(population, sel_count=1)[0]
    print_results(best_ind)


if __name__ == "__main__":
    main()

Short Version

import array

import numpy
from deap_er import Fitness, Toolbox, creator, tools

tools.rng.seed(1234)  # disables randomization


def setup():
    creator.create_type("FitnessMax", Fitness, weights=(1.0,))
    creator.create_type("Individual", array.array, typecode="b", fitness=creator.FitnessMax)

    toolbox = Toolbox()
    toolbox.register("attr_bool", tools.rng.randint, 0, 1)
    toolbox.register("individual", tools.init_repeat, creator.Individual, toolbox.attr_bool, 100)
    toolbox.register("population", tools.init_repeat, list, toolbox.individual)
    toolbox.register("mate", tools.cx_two_point)
    toolbox.register("mutate", tools.mut_flip_bit, mut_prob=0.05)
    toolbox.register("select", tools.sel_tournament, contestants=3)
    toolbox.register("evaluate", lambda x: sum(x))

    stats = tools.Statistics(lambda ind: ind.fitness.values)
    stats.register("avg", numpy.mean)
    stats.register("std", numpy.std)
    stats.register("min", numpy.min)
    stats.register("max", numpy.max)

    return toolbox, stats


def print_results(best_ind):
    if not all(gene == 1 for gene in best_ind):
        raise RuntimeError("Evolution failed to converge.")
    print("\nEvolution converged correctly.")


def main():
    toolbox, stats = setup()
    pop = toolbox.population(size=300)
    hof = tools.HallOfFame(maxsize=1)
    args = {
        "toolbox": toolbox,
        "population": pop,
        "generations": 50,
        "cx_prob": 0.5,
        "mut_prob": 0.2,
        "hof": hof,
        "stats": stats,
        "verbose": True,  # prints stats
    }
    tools.ea_simple(**args)
    print_results(hof[0])


if __name__ == "__main__":
    main()

Using Numpy

import numpy
from deap_er import Fitness, Toolbox, creator, tools

tools.rng.seed(1234)  # disables randomization


def setup():
    creator.create_type("FitnessMax", Fitness, weights=(1.0,))
    creator.create_type("Individual", numpy.ndarray, fitness=creator.FitnessMax)

    toolbox = Toolbox()
    toolbox.register("attr_bool", tools.rng.randint, 0, 1)
    toolbox.register("individual", tools.init_repeat, creator.Individual, toolbox.attr_bool, 100)
    toolbox.register("population", tools.init_repeat, list, toolbox.individual)

    toolbox.register("mate", tools.cx_two_point_copy)
    toolbox.register("mutate", tools.mut_flip_bit, mut_prob=0.05)
    toolbox.register("select", tools.sel_tournament, contestants=3)
    toolbox.register("evaluate", lambda x: sum(x))

    stats = tools.Statistics(lambda ind: ind.fitness.values)
    stats.register("avg", numpy.mean)
    stats.register("std", numpy.std)
    stats.register("min", numpy.min)
    stats.register("max", numpy.max)

    return toolbox, stats


def print_results(best_ind):
    if not all(gene == 1 for gene in best_ind):
        raise RuntimeError("Evolution failed to converge.")
    print("\nEvolution converged correctly.")


def main():
    toolbox, stats = setup()
    pop = toolbox.population(size=300)
    hof = tools.HallOfFame(maxsize=1, similar=numpy.array_equal)
    args = {
        "toolbox": toolbox,
        "population": pop,
        "generations": 50,
        "cx_prob": 0.5,
        "mut_prob": 0.2,
        "hof": hof,
        "stats": stats,
        "verbose": True,  # prints stats
    }
    tools.ea_simple(**args)
    print_results(hof[0])


if __name__ == "__main__":
    main()

Using Multiprocessing

import array
import multiprocessing as mp

import numpy
from deap_er import Fitness, Toolbox, creator, tools

tools.rng.seed(1234)  # disables randomization


# Evaluator can't be a lambda, because lambdas can't be pickled.
def evaluate(individual):
    return sum(individual)


# Can't be in setup(), because subprocesses need these objects.
creator.create_type("FitnessMax", Fitness, weights=(1.0,))
creator.create_type("Individual", array.array, typecode="b", fitness=creator.FitnessMax)


def setup():
    toolbox = Toolbox()
    toolbox.register("attr_bool", tools.rng.randint, 0, 1)
    toolbox.register("individual", tools.init_repeat, creator.Individual, toolbox.attr_bool, 100)
    toolbox.register("population", tools.init_repeat, list, toolbox.individual)

    toolbox.register("mate", tools.cx_two_point)
    toolbox.register("mutate", tools.mut_flip_bit, mut_prob=0.05)
    toolbox.register("select", tools.sel_tournament, contestants=3)
    toolbox.register("evaluate", evaluate)

    stats = tools.Statistics(lambda ind: ind.fitness.values)
    stats.register("avg", numpy.mean)
    stats.register("std", numpy.std)
    stats.register("min", numpy.min)
    stats.register("max", numpy.max)

    return toolbox, stats


def print_results(best_ind):
    if not all(gene == 1 for gene in best_ind):
        raise RuntimeError("Evolution failed to converge.")
    print("\nEvolution converged correctly.")


def main():
    toolbox, stats = setup()
    pop = toolbox.population(size=300)
    hof = tools.HallOfFame(maxsize=1)
    with mp.Pool() as pool:
        toolbox.register("map", pool.map)
        args = {
            "toolbox": toolbox,
            "population": pop,
            "generations": 50,
            "cx_prob": 0.5,
            "mut_prob": 0.2,
            "hof": hof,
            "stats": stats,
            "verbose": True,  # prints stats
        }
        tools.ea_simple(**args)
        print_results(hof[0])


if __name__ == "__main__":
    main()