Distributed Evolutionary Algorithms in Python (DEAP)
DEAP is a novel evolutionary computation framework designed for rapid prototyping and testing of ideas. It provides explicit algorithms and transparent data structures for various evolutionary computation techniques, including genetic algorithms, genetic programming, evolution strategies, and multi-objective optimization. It works seamlessly with parallelization mechanisms like multiprocessing. The current stable version is 1.4.3.
Warnings
- gotcha The evaluation function for an individual MUST return a tuple of fitness values, even for a single objective. For example, `return sum(individual),` (note the comma) or `return (sum(individual),)`.
- gotcha When defining `creator.create("Fitness...", base.Fitness, weights=...)`, the `weights` tuple determines if the objective is maximization (positive weight, e.g., `(1.0,)`) or minimization (negative weight, e.g., `(-1.0,)`). Ensure the sign matches your optimization goal.
- breaking For Genetic Programming (GP), the `gp.stringify()` function was replaced by `PrimitiveTree.__str__()`. Also, `gp.evaluate()` and `gp.lambdify()` were merged and replaced by a single `gp.compile()` function. The `tools.Checkpoint` class was removed in favor of simpler manual checkpointing.
- deprecated Older versions of DEAP (pre-1.x, particularly around 0.8) for Python 3 installations might have required `setuptools<=58` due to the use of `2to3` for source translation. This is unlikely to affect modern installations (Python 3.6+ and DEAP 1.x+).
Install
-
pip install deap
Imports
- creator
from deap import creator
- base
from deap import base
- tools
from deap import tools
- algorithms
from deap import algorithms
Quickstart
import random
from deap import creator, base, tools, algorithms
# 1. Define problem: Maximize sum of bits in a binary string (OneMax problem)
# Create a FitnessMax class, higher values are better
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
# Create an Individual class, which is a list and has a fitness attribute
creator.create("Individual", list, fitness=creator.FitnessMax)
# 2. Initialize Toolbox
toolbox = base.Toolbox()
# Register function to generate random boolean attributes (0 or 1)
toolbox.register("attr_bool", random.randint, 0, 1)
# Register function to create an individual: 100 random booleans
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, 100)
# Register function to create a population: a list of individuals
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
# 3. Define Evaluation Function
def evalOneMax(individual):
return sum(individual), # The comma is crucial: returns a tuple
toolbox.register("evaluate", evalOneMax)
# 4. Define Genetic Operators
toolbox.register("mate", tools.cxTwoPoint) # Two-point crossover
toolbox.register("mutate", tools.mutFlipBit, indpb=0.05) # Flip bit mutation with 5% probability
toolbox.register("select", tools.selTournament, tournsize=3) # Tournament selection with size 3
# 5. Run the Evolutionary Algorithm
def main():
random.seed(42) # For reproducibility
population = toolbox.population(n=300)
# Number of generations, crossover probability, mutation probability
NGEN, CXPB, MUTPB = 40, 0.7, 0.2
# The main evolutionary loop
print(f"Start of evolution: Population size {len(population)}")
population, logbook = algorithms.eaSimple(population, toolbox, cxpb=CXPB, mutpb=MUTPB, ngen=NGEN, verbose=False)
# Get the best individual(s) from the final population
best_ind = tools.selBest(population, 1)[0]
print(f"Best individual: {best_ind}, Fitness: {best_ind.fitness.values[0]}")
if __name__ == "__main__":
main()