0

I am developing a simple genetic algorithm using Python and the Deap library . At the end of all I am launching the eaSimple function to have the population evolved, but I keep having the following error : "object 'int' has no len()'. The algorithm is very basic and its mostly cut and pasted from a model algorithm taken from a course, which is allegedly working fine. Here is the involved section of code :

def safediv (dividend, divisor):
    if divisor != 0:
        return dividend / divisor
    else:
        return dividend
        
        
#select the primitives 
pset = gp.PrimitiveSet("main", 6)    #arity is 6 because as we'll see, the primitiveset 's function is calculated over 6 param (f12,d12, f1, etc..)'
pset.addPrimitive(operator.add, 2)
pset.addPrimitive(operator.mul, 2)
pset.addPrimitive(operator.sub, 2)
pset.addPrimitive(safediv,2)
            
creator.create ("MyFitness", base.Fitness, weights=(-1.0,))    
creator.create ("Individual", gp.PrimitiveTree, fitness = creator.MyFitness)

toolbox = base.Toolbox()
toolbox.register("expr",
               gp.genGrow, 
               pset=pset, 
               min_ = 1,  # minimum depth of primitivetree 
               max_ = 4)  # maximum depth of primitivetree (max of nested primitive calls)

toolbox.register("individual",      #function for creating the single individual
               tools.initIterate,    #initIterate takes the first arg (creator.Individual) and builds it with the structur coming from the second
               creator.Individual, # (tools.expr)
               toolbox.expr)

toolbox.register ("compile", gp.compile, pset = pset)

toolbox.register("population", 
                tools.initRepeat,
                list,
                toolbox.individual)

#parameters to pass to the eaSimple algorithm
toolbox.register("evaluate", MyError,y_train = y_train_set, x_train_ambo = x_train_set_ambo, x_train_extract =x_train_set_extract )
toolbox.register("mate",tools.cxUniform , indpb = 0.3)  #Uniform swaps individual bits between the two parents, rather than segments
                                                     #(see book)
toolbox.register("expr_mut", gp.genFull, min_=0,max_=2)    
toolbox.register("mutate",gp.mutUniform, expr=toolbox.expr_mut,pset= pset)
toolbox.register("select", tools.selTournament, tournSize = 3) #tournaments allow to distribute the selection between multiple processors
                                                            #as picking individuals by 3 at a time can have each #tournament performed
                                                            #on a different cpu and then the selection parallelized
#decorators to limit the growth of the PrimitiveTree       
toolbox.decorate("mate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17))
toolbox.decorate("mutate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17))        

pop = toolbox.population(n=300)
hof = tools.HallOfFame(1)
stat_fit = tools.Statistics (key=lambda ind: ind.fitness.values)
stat_size = tools.Statistics ( key=len)


mstats = tools.MultiStatistics(fitness = stat_fit, size = stat_size)

mstats.register ("min", np.min)
mstats.register ("max", np.max)
mstats.register ("avg", np.mean)
mstats.register ("std", np.std)

pop, log = algorithms.eaSimple(population = pop,  
                               toolbox = toolbox, 
                               cxpb = 0.5,    
                               mutpb = 0.1,    
                               ngen = num_gen,     
                               stats= mstats,
                               halloffame=hof
                               , 
                               verbose=True
                              )
    

The MyError function returns an int, I am confident its working fine since I debugged it accurately, thats why I didn't include the code.

Any idea ?

1
  • Ok found . The MyError function was returning an int instead of a tuple , that's the reason . Commented May 29, 2023 at 3:45

1 Answer 1

0

The evaluation function needs to return a tuple for DEAP to work, the function "MyError" is returning an int, you only need to change the return value of the function to a tuple, like this:

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

Notice that I'm returning a tuple that contains two elements, the first one is the fitness of my individual and the second one is empty.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.