Categories
Mastering Development

‘list’ object has no attribute ‘fitness’ ERROR

import random 
  
class Individual(object): 
    ''' 
    Class representing individual in population 
    '''
    def __init__(self, chromosome): 
        self.chromosome = chromosome  
        self.fitness = self.fitness() 
  
    @classmethod
    def mutate(chromosome): 
        ''' 
        random change value of a random col
        '''
        # randomly choose mutation position 
        col = random.randint(0, len(chromosome)-1)
        row = random.randint(0, len(chromosome)-1)
        chromosome[col] = row
        return chromosome 
  
    @classmethod
    def create_chromosome(self,size): 
        ''' 
        create a random initial state of n queen, where no
        column has horizontal conflicts with each other.
        '''
        initial_chromosome = [_ for _ in range(size)]
        random.shuffle(initial_chromosome)
        return initial_chromosome
    
    def reproduction_rate(chromosome,population):
        # defin reproduction_rate according to the textbook
        return fitness(chromosome)/sum(fitness(n) for n in population)
       
    def mate(self, obj): 
        ''' 
        Perform mating and produce new offspring 
        '''
  
        # random cross point  
        cross_point = random.randint(0, len(self.chromosome)-1)
        # return the child chromosome
        return self.chromosome[0:cross_point] + obj.chromosome[cross_point:len(self.chromosome)]
            
  
    def fitness(self): 
        ''' 
        Calculate fittness score, it is the number of 
        pairs of non-conflicting queens,with maximum 
        fitness = size*(size-1)/2
        '''
        #since each column can have at most one queen, no vertical collision
        #define horizontal collision, each two occurance is considered half
        horizontal_collisions = sum([self.chromosome.count(queen)-1 for queen in self.chromosome])/2
        # define diagnal collision count innitally 0
        diagnal_collisions = 0
        n = len(self.chromosome)
        # maxFitness is defined as the best possible fitness value
        maxFitness = n*(n-1)/2
        # store a table of sum values in 2n cells, which identifies diagnal collision
        left_diagonal = [0]*2*n # left_diagnal value record
        right_diagonal =[0]*2*n # righ _diagnal value record
        
        for i in range(n): # for each col in chromosome:
            left_diagonal[i + self.chromosome[i]] += 1 # increment the record at this value by 1
            right_diagonal[n -i +self.chromosome[i]-1] += 1 # opposite side
            
        for i in range (2*n-1): # evaluate the record values in each diagnal cell
            counter =0
            if left_diagonal[i] >1: #more than one value, conflict
                counter += left_diagonal[i] -1 # increment this value to count as conflicts
            if right_diagonal[i] >1:
                counter += right_diagonal[i]-1
            diagnal_collisions += counter/(n-abs(i-n+1))
        # return int value of fitness
        return int(maxFitness - horizontal_collisions - diagnal_collisions)
  
# Driver code 
def main(): 
    size = int(input("Enter NUmber of Queens:"))
    global POPULATION_SIZE 
    POPULATION_SIZE = 100
    maxFitness = size*(size-1)/2
    #current generation 
    generation = 1
  
    found = False
    population = [] 
  
    # create initial population of size 100
    for _ in range(POPULATION_SIZE): 
        chromosome = Individual.create_chromosome(size) # returns a list of chromosome
        population.append(Individual(chromosome)) 
  
    while not found: 
        
        print (population[0].fitness)
        print (population[0].chromosome)
        # sort the population in increasing order of fitness score 
        population = sorted(population, key =lambda x: x.fitness) 
  
        # if the individual having lowest fitness score ie.  
        # 0 then we know that we have reached to the target 
        # and break the loop 
        if population[0].fitness <= 0: 
            found = True
            break
            
        # Otherwise generate new offsprings for new generation 
        new_generation = [] 
        
        # Perform Elitism, that mean 10% of fittest population 
        # goes to the next generation 
        s = int((10*POPULATION_SIZE)/100) 
        new_generation.extend(population[:s]) 
        
        # From 50% of fittest population, Individuals  
        # will mate to produce offspring 
        s = int((90*POPULATION_SIZE)/100) 
        for _ in range(s): 
            parent1 = random.choice(population[:50]) 
            parent2 = random.choice(population[:50]) 
            child = parent1.mate(parent2) 
            new_generation.append(child) 
            
        population = new_generation 
        
        print("Generation: {}\tString: {}\tFitness: {}".
              format(generation, 
              "".join(map(str,population[0].chromosome)), 
              population[0].fitness)) 
        
        generation += 1
        
    print("Generation: {}\tString: {}\tFitness: {}".
          format(generation, 
          "".join(map(str, population[0].chromosome)), 
          population[0].fitness)) 
  
if __name__ == '__main__': 
    main() 

The interpreter is giving me this error on the lambda function, I want to sort the list of population where each element is an object, which has a fitness value defined by the class. I’m not sure what I did wrong here, I checked similar questions it seems like the lambda function doesn’t have access to this fitness() function, why is that happening? This code is a modification from: https://www.geeksforgeeks.org/genetic-algorithms/ to solve the n-queen prolem

traceback:
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~\aima-python\genetic_algorithm.py in <module>
    154 
    155 if __name__ == '__main__':
--> 156     main()

~\aima-python\genetic_algorithm.py in main()
    113         print (population[0].chromosome)
    114         # sort the population in increasing order of fitness score
--> 115         population = sorted(population, key =lambda x: x.fitness, reverse = True)
    116 
    117         # if the individual having lowest fitness score ie.

~\aima-python\genetic_algorithm.py in <lambda>(x)
    113         print (population[0].chromosome)
    114         # sort the population in increasing order of fitness score
--> 115         population = sorted(population, key =lambda x: x.fitness, reverse = True)
    116 
    117         # if the individual having lowest fitness score ie.

AttributeError: 'list' object has no attribute 'fitness'

Leave a Reply

Your email address will not be published. Required fields are marked *