-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
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.valuesMy 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.valuesHence my question, why are you unpacking the result of the mutation?