Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cxSimulatedBinaryBounded raises Exception with various eta #740

Open
eirirlar opened this issue Feb 16, 2024 · 1 comment
Open

cxSimulatedBinaryBounded raises Exception with various eta #740

eirirlar opened this issue Feb 16, 2024 · 1 comment

Comments

@eirirlar
Copy link

eirirlar commented Feb 16, 2024

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
Copy link

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants