Skip to content

varAnd question #761

@karma-riuk

Description

@karma-riuk

Hello,

I'm currently trying to do some mutations over a list of str. The way I set up deap is with the following code:

creator.create("Fitness", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.Fitness)
toolbox = base.Toolbox()
toolbox.register("attr_str", fuzzer.random_individual)
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_str, n=len(types)) # len(types) can be any int from 1 to 3
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("evaluate", fitness.get_fitness_of_f(globals()[func]))
toolbox.register("mate", deap_crossover)
toolbox.register("mutate", deap_mutate)
toolbox.register("select", tools.selTournament, tournsize=TOURNSIZE)

for i in range(REPS):
    population = toolbox.population(n=NPOP)
    algorithms.eaSimple(population, toolbox, CXPROB, MUPROB, NGEN, verbose=False)

As you can notice, my Individual is a list, that can contain any number (from 1 to 3) of strings.
Additionally, let me give you the deap_mutate function, as it will be useful for later:

def deap_mutate(ind):
    return creator.Individual(fuzzer.mutate(ind))

fuzzer.mutate takes in a list of strings and returns a copy of that list, with a one element mutated.

For some reason, my code kept crashing after a mutation was triggered. I was really confused why so I started digging in the code of the library, and found this: inside the varAnd function, with this piece of code that handles the mutations:

    for i in range(len(offspring)):
        if random.random() < mutpb:
            offspring[i], = toolbox.mutate(offspring[i])
            del offspring[i].fitness.values

My question is related to that little , in the third line, namely the offspring[i],. Why is it there? I am very confused by it's existence and am probably missing something.

The issue it gave me was the following, given that my individuals are a lists, when the list has one element, that element would get unpacked (because of that ,) and cause an error saying

    del offspring[i].fitness.values
        ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'fitness'

If however my list contains more than one element, then the error would come from the line where the mutation happen, saying

    offspring[i], = toolbox.mutate(offspring[i])
    ^^^^^^^^^^^^^
ValueError: too many values to unpack (expected 1)

Now, there are two fixes I found for this issue. One on my side and one on the side of the library. The one on my side is simply to wrap the individual returned in a list, in order for the mutated individual to be unpacked correctly inside the library:

def deap_mutate(ind):
    return [creator.Individual(fuzzer.mutate(ind))]

The one on the side of the library is to remove that , in the varAnd function:

    for i in range(len(offspring)):
        if random.random() < mutpb:
            offspring[i] = toolbox.mutate(offspring[i])
            del offspring[i].fitness.values

Hence my question, why are you unpacking the result of the mutation?

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