I'm learning python and trying to implement a genetic algorithm with simulated annealing. I've created a class describing my population, which contains a list of individuals as well as as some other attributes and methods. When I try to create the next generation of a population, I want to remove the parent's genotypes from my population, then perform simulated annealing to see whether I shall reinclude the parents or the children individually to the population. The problem occurs when trying to remove the parents from the population.
I've checked that the genotypes of the parents are indeed in the population. I've created a minimal working example by building upon a very minimal example and expanding it until the error is occuring.
import random
from math import factorial
class Genotype(object):
def __init__(self, data_list):
self.__genotype = data_list
# fitness is a complicated long function depending on modules,
# replaced by random for simplicity
self.fitness = random.random()
def __eq__(self, other):
"""
Comparing if two genotypes are equal
:param other: Other Genotype object
:type other: Genotype
:return: True if they are equal, False otherwise
:rtype: Boolean
"""
if self.get_genotype() == other.get_genotype():
return True
else:
return False
def get_genotype(self):
"""
Return the genotype.
"""
return self.__genotype
class Population(object):
def __init__(self, genotype_list):
self.individuals = genotype_list
self.fitness = self.get_fitness()
def __getitem__(self, key):
return self.individuals[key]
def get_fitness(self):
return [x.fitness for x in self.individuals]
def next_generation(self):
parent_indices = list()
childs = list()
# define the number of parents
number_of_parents = 12
# Roulette-wheel selection
eff_fit = self.fitness
s = sum(eff_fit)
eff_fit_with_indices = list(enumerate(eff_fit))
eff_fit_sorted = sorted(eff_fit_with_indices, key=lambda i: i[1])
for rep in range(number_of_parents):
r = random.uniform(0, s)
partial_sum = 0
for idx, val in enumerate(eff_fit_sorted):
partial_sum += val[1]
if partial_sum >= r:
parent_indices.append(val)
break
parent_genotypes = [self[x[0]] for x in parent_indices]
for parent in parent_genotypes:
self.individuals.remove(parent)
return self
individuals = 120
rectangle_number = 79
max_permutations = factorial(rectangle_number)
master_genotype = range(0, rectangle_number)
# creating initial genotypes
initial_genotypes = list()
for idx in range(0, individuals):
unique = False
temp_seed = random.randint(1, max_permutations)
random.seed(temp_seed)
while not unique:
temp_genotype_data_list = list(master_genotype)
random.shuffle(temp_genotype_data_list)
temp_genotype = Genotype(temp_genotype_data_list)
if temp_genotype not in initial_genotypes:
initial_genotypes.append(temp_genotype)
unique = True
population = Population(initial_genotypes)
population.next_generation()
I expected self to have less members as the parents are removed, however, I get the following error:
Exception has occured: ValueError
list.remove(x): x not in list