DEAP / deap

Distributed Evolutionary Algorithms in Python
http://deap.readthedocs.org/
GNU Lesser General Public License v3.0
5.79k stars 1.12k forks source link

cxSimulatedBinaryBounded raises Exception with various eta #740

Open eirirlar opened 7 months ago

eirirlar commented 7 months ago

The following code fails with the Exception: TypeError: '<=' not supported between instances of 'float' and 'complex'

The Exception occurs in the mate function cxSimulatedBinaryBounded where on some occasions beta becomes negative causing alpha to become complex and fail division.

I would have expected either proper documentation of the acceptable eta range (maybe in relation to low and up), or a repair of this bug.

import random
from deap import base, creator, tools, algorithms

# Define the problem as a maximization problem
creator.create("FitnessMax", base.Fitness, weights=(1., 1.))
creator.create("Individual", list, fitness=creator.FitnessMax)

# Define the problem-specific functions
def eval_individual(individual):
    a, b, c, d, e, f = individual
    return (a + b) ** 2, (c + d) ** 2

# Define genetic operators
toolbox = base.Toolbox()
toolbox.register("attr_float", random.uniform, 0., 1.)
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_float, n=6)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

toolbox.register("evaluate", eval_individual)
toolbox.register("mate", tools.cxSimulatedBinaryBounded, eta=0.9, low=0., up=1.)
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.2)
toolbox.register("select", tools.selTournament, tournsize=3)

def main():
    population_size = 50
    generations = 20

    population = toolbox.population(n=population_size)
    CXPB, MUTPB = 0.7, 0.2

    print("Start of Evolution")

    # Evaluate the entire population
    fitnesses = list(map(toolbox.evaluate, population))
    for ind, fit in zip(population, fitnesses):
        ind.fitness.values = fit

    print("  Evaluated %i individuals" % len(population))

    for gen in range(generations):
        print("-- Generation %i --" % gen)

        # Select the next generation individuals
        offspring = toolbox.select(population, len(population))

        # Clone the selected individuals
        offspring = list(map(toolbox.clone, offspring))

        # Apply crossover and mutation on the offspring
        for child1, child2 in zip(offspring[::2], offspring[1::2]):
            if random.random() < CXPB:
                toolbox.mate(child1, child2)
                del child1.fitness.values
                del child2.fitness.values

        for mutant in offspring:
            if random.random() < MUTPB:
                # TODO mutate takes data out of range 0-1
                toolbox.mutate(mutant, sigma=0.1)
                del mutant.fitness.values

        # Evaluate offspring individuals
        fitnesses = list(map(toolbox.evaluate, offspring))
        for ind, fit in zip(offspring, fitnesses):
            ind.fitness.values = fit

        # Replace the old population by the offspring
        population[:] = offspring

        # Gather all the fitnesses in one list and print the stats
        fits = [ind.fitness.values[0] for ind in population]

        length = len(population)
        mean = sum(fits) / length
        sum2 = sum(x * x for x in fits)
        std = abs(sum2 / length - mean ** 2) ** 0.5

        print("  Min %s" % min(fits))
        print("  Max %s" % max(fits))
        print("  Avg %s" % mean)
        print("  Std %s" % std)

    print("-- End of (successful) evolution --")

    best_ind = tools.selBest(population, 1)[0]
    print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))

if __name__ == "__main__":
    main()
MySweetEden commented 1 month ago

I noticed that this issue has already been discussed in Issue #566 and a Pull Request (PR) #567 was created to address it. However, it seems this problem persists because the PR has not been merged yet.

Could we look into merging PR #567 or providing an alternative solution to fix this issue? The community would greatly benefit from having this bug resolved.

Thank you!