Skip to content

Inconsistent Results in Genetic Programming with Global Random Seed #765

@billyoftea

Description

@billyoftea

Issue Description

Hi DEAP team,

I'm a beginner using DEAP for genetic programming and have encountered an issue where setting a global random seed (random.seed(1)) does not produce consistent results across multiple runs. Specifically, the results for generation 0 are identical, but starting from generation 1, metrics like average fitness, standard deviation, and number of evaluations differ. I suspect the issue may be related to the selection or crossover processes, as modifying the selRandom function to use a local seed fixed the issue in my tests.

Thank you in advance for your help and for maintaining this amazing library!

Steps to Reproduce

  1. Set up a genetic programming experiment with the following configuration:
    • Random seed: random.seed(1), np.random.seed(1), torch.manual_seed(1)
    • Population size: 1000
    • Generations: 3
    • Selection: tools.selTournament with tournsize=20
    • Crossover: gp.cxOnePoint with probability 0.8
    • Mutation: gp.mutUniform with probability 0.3
  2. Run the experiment multiple times and compare the output metrics (e.g., average fitness, standard deviation, number of evaluations).
  3. Observe that generation 0 metrics are consistent, but subsequent generations differ.

Code Example

Here is the relevant code snippet:

import random
import numpy as np
import torch
from deap import base, creator, tools, gp

# Set random seed
random_state = 1
random.seed(random_state)
np.random.seed(random_state)
torch.manual_seed(random_state)

# Define problem-specific primitives (omitted for brevity)
# Assume pset is a gp.PrimitiveSetTyped object

# Set up DEAP
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", gp.PrimitiveTree, fitness=creator.FitnessMax)

toolbox = base.Toolbox()
toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=4)
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.expr)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("evaluate", calculate_fitness)  # Custom fitness function (deterministic)
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.register("select", tools.selTournament, tournsize=20)

# Parameters
population_size = 1000
generations = 3
cxpb = 0.8
mutpb = 0.3
hall_of_fame_size = 10

# Run evolution (e.g., using eaSimple)
pop = toolbox.population(n=population_size)
hof = tools.HallOfFame(hall_of_fame_size)
stats = tools.Statistics(lambda ind: ind.fitness.values)
stats.register("avg", np.mean)
stats.register("std", np.std)
stats.register("min", np.min)
stats.register("max", np.max)
pop, logbook = algorithms.eaSimple(pop, toolbox, cxpb=cxpb, mutpb=mutpb, ngen=generations, stats=stats, halloffame=hof, verbose=True)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions