DEAP / deap

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

Individual as a list of floats - error in the eaSimple algorithm #622

Closed blancalarraga closed 2 years ago

blancalarraga commented 2 years ago

Hi, I am creating an individual as a list of floats as follows for a minimization problem:

IND_SIZE=8

creator.create("FitnessMin", base.Fitness, weights=(-1,)) creator.create("Individual", list, fitness=creator.FitnessMin) toolbox=base.Toolbox() toolbox.register("attr_float",random.random) toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_float,n=IND_SIZE) toolbox.register("population", tools.initRepeat, list, toolbox.individual)

then I define the evalError(individual) function and then, I define the main function as follows: def main(): random.seed(169) #semilla fija para poder tener una reproducción de los escenarios

pop=toolbox.population(n=100)

hof=tools.HallOfFame(1)
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)

algorithms.eaSimple(pop,toolbox,0.7,0.2,50,stats=stats,halloffame=hof)

return pop,stats,hof

if name == "main": pop,stats,hof=main() print(hof) print(evalError(hof[0]))

I get an error in line pop,stats,hof=main() as it states that "list indices must be integers or slices, not float". How could I solve it? Thank you very much!!

blancalarraga commented 2 years ago

It seems that the error comes from the 'i' index within the cxPartialyMatched function within the varAnd function used within the eaSimple algorithm. I am completely lost on how this index could be changed and why it is gathering a float number and if this is related with my definition of an individual. Thanks again!

cactusWhiskey commented 2 years ago

You might want to just post the entire code, I couldn't reproduce your error from the code snippets given, ran fine.

blancalarraga commented 2 years ago

That is the complete code I am running.... and still getting an error... It is strange that running the same code in two computers I have and I get a different error. The error I posted I got it on my mac, and on my Linux I am getting the following error; I do not understand why.... specially if it runs for you...:


TypeError Traceback (most recent call last)

in 48 49 if __name__ == "__main__": ---> 50 pop,stats,hof=main() 51 print(hof) 52 print(evalError(hof[0])) in main() 34 random.seed(169) #semilla fija para poder tener una reproducción de los escenarios 35 ---> 36 pop=toolbox.population(n=100) 37 38 hof=tools.HallOfFame(1) /usr/lib/python3/dist-packages/deap/tools/init.py in initRepeat(container, func, n) 23 See the :ref:`list-of-floats` and :ref:`population` tutorials for more examples. 24 """ ---> 25 return container(func() for _ in range(n)) 26 27 def initIterate(container, generator): /usr/lib/python3/dist-packages/deap/tools/init.py in (.0) 23 See the :ref:`list-of-floats` and :ref:`population` tutorials for more examples. 24 """ ---> 25 return container(func() for _ in range(n)) 26 27 def initIterate(container, generator): /usr/lib/python3/dist-packages/deap/tools/init.py in initRepeat(container, func, n) 23 See the :ref:`list-of-floats` and :ref:`population` tutorials for more examples. 24 """ ---> 25 return container(func() for _ in range(n)) 26 27 def initIterate(container, generator): /usr/lib/python3/dist-packages/deap/creator.py in __new__(cls, seq) 77 @staticmethod 78 def __new__(cls, seq=()): ---> 79 return super(_array, cls).__new__(cls, cls.typecode, seq) 80 81 def __deepcopy__(self, memo): TypeError: integer argument expected, got float
cactusWhiskey commented 2 years ago

Yeah, that's why I was asking to post the entire text of the python script, including all imports and function definitions.

Here is what I was able to run:

import random import numpy as np from deap import algorithms from deap import base from deap import creator from deap import tools

IND_SIZE = 8

creator.create("FitnessMin", base.Fitness, weights=(-1.0,)) creator.create("Individual", list, fitness=creator.FitnessMin) toolbox = base.Toolbox() toolbox.register("attr_float", random.random) toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_float, n=IND_SIZE) toolbox.register("population", tools.initRepeat, list, toolbox.individual)

def evalOneMax(individual): return sum(individual),

toolbox.register("evaluate", evalOneMax) toolbox.register("mate", tools.cxTwoPoint) toolbox.register("mutate", tools.mutFlipBit, indpb=0.05) toolbox.register("select", tools.selTournament, tournsize=3)

def main(): random.seed(64)

pop = toolbox.population(n=100)

hof = tools.HallOfFame(1)
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)

algorithms.eaSimple(pop, toolbox, 0.7, 0.2, 50, stats=stats, halloffame=hof)

return pop, stats, hof

if name == "main": pop, stats, hof = main() print(hof)

blancalarraga commented 2 years ago

Thanks for your answer, this works for me too!

Sorry for my mistake; I forgot to include part of the code: toolbox.register("mate",tools.cxPartialyMatched) toolbox.register("mutate",tools.mutShuffleIndexes, indpb=0.05) toolbox.register("select",tools.selTournament, tournsize=3) toolbox.register("evaluate",evalError)

This is different from yours and changing it made it work even though I do not know why having a different mate and mutate function made it not to work. Any explanation?

Thanks again!

cactusWhiskey commented 2 years ago

Looks like this function is specifically intended for individuals that are sequences of indices, not floats. Not exactly sure why, but that's what it says:

def cxPartialyMatched(ind1, ind2): """Executes a partially matched crossover (PMX) on the input individuals. The two individuals are modified in place. This crossover expects :term:sequence individuals of indices, the result for any other type of individuals is unpredictable.

you can see where it's trying to index an array using a value obtained from the individual:

for i in xrange(size):
    p1[ind1[i]] = i
    p2[ind2[i]] = i

Not certain what the use case of this crossover operator is, but you would need to re-write it to work with your individuals.

blancalarraga commented 2 years ago

Thanks for all the info. I am just a beginner and did not know all the functions available for the different parameters for the evolution of the generation.

Thanks a lot!