I have a population (
Pop) which has an attribute which is a list of individuals (
Ind) where each individual has an attribute which is a list of chromosomes (
Chromo). Each chromosome is a list of numbers which tells about the fitness (=reproductive success, the fitness is obtain by multiplying all numbers of a all chromosomes) of the individuals. Within one position on the chromosome, there are different values for the different individuals. I'd like to set the greatest value to 1 and the others to keep their relative value in comparison to the biggest value.
For example, if on one position on the n-th chromosome, the individuals in the population have the values [3,4,0.4,12,5,6] (that would be a case of a population of 6 individuals).
I'd like to set these value to:
a = [3,4,0.4,12,5,6] [i/float(max(a)) for i in a]
I tried to create this function but I got lost and can hardly find out a solution in all these lists!
You can reach the 14th of the 4th chromosome in the 25th individual by writing:
To make sure my aim is understood. I'd like to create a function which take an instance of
Pop as argument and return the same or another
Pop where all positions on the chromosomes are replaced by numbers in the range [0,1] respecting the relative values of all numbers at the same position on the same chromosome in the population.
Below is my code (it is long but reading the constructor of the classes
Pop (which are all impressively basic) should, I hope, be enough. The class
WalkerRandomSampling serve only the purpose of performing a random weighted sampling).
One might have a look to what I tried, the method is called
set_best_fitness_to_one and is within the
from random import uniform, gauss, choice, expovariate, shuffle from numpy import arange, array, bincount, ndarray, ones, where from numpy.random import seed, random, randint, binomial from operator import mul, methodcaller class WalkerRandomSampling(object): """Walker's alias method for random objects with different probablities. Based on the implementation of Denis Bzowy at the following URL: http://code.activestate.com/recipes/576564-walkers-alias-method-for-random-objects-with-diffe/ """ def __init__(self, weights, keys=None): """Builds the Walker tables ``prob`` and ``inx`` for calls to `random()`. The weights (a list or tuple or iterable) can be in any order and they do not even have to sum to 1.""" n = self.n = len(weights) if keys is None: self.keys = keys else: self.keys = array(keys) if isinstance(weights, (list, tuple)): weights = array(weights, dtype=float) elif isinstance(weights, ndarray): if weights.dtype != float: weights = weights.astype(float) else: weights = array(list(weights), dtype=float) if weights.ndim != 1: raise ValueError("weights must be a vector") weights = weights * n / weights.sum() inx = -ones(n, dtype=int) short = where(weights < 1).tolist() long = where(weights > 1).tolist() while short and long: j = short.pop() k = long[-1] inx[j] = k weights[k] -= (1 - weights[j]) if weights[k] < 1: short.append( k ) long.pop() self.prob = weights self.inx = inx def random(self, count=None): """Returns a given number of random integers or keys, with probabilities being proportional to the weights supplied in the constructor. When `count` is ``None``, returns a single integer or key, otherwise returns a NumPy array with a length given in `count`. """ if count is None: u = random() j = randint(self.n) k = j if u <= self.prob[j] else self.inx[j] return self.keys[k] if self.keys is not None else k u = random(count) j = randint(self.n, size=count) k = where(u <= self.prob[j], j, self.inx[j]) return self.keys[k] if self.keys is not None else k def test(self): weights = [12,3,2,0,5] test = WalkerRandomSampling(weights=weights) a =  for i in xrange(10000): a.append(test.random()) b =  for value in range(4): b.append(len([i for i in a if i == value])/float(len(a))) print b print weights class Chromo(object): def __init__(self, alleles): self.alleles=alleles def mutations(self): nb_mut = binomial(chromo_size, mut_rate) for one_mut in xrange(nb_mut): self.alleles[choice(range(chromo_size))] *= pdf_mutation(pdf_mut_scale) return self class Ind(object): def __init__(self, chromosomes): self.chromosomes = chromosomes def fitness(self): if nb_chromosomes == 1: return reduce(mul, self.chromosomes.alleles) fit = 1 for gene_pos in xrange(chromo_size): alleles =  for chromo_pos in range(len(self.chromosomes)): alleles.append(self.chromosomes[chromo.pos].alleles[gene_pos]) fit *= sum(alleles)/len(alleles) # + dominance effect. Epistasis?! return fit def reprod(self,other): off = Ind(chromosomes = ) for one_chromo in xrange(nb_chromosomes): # recombination. Because the population has been shuffled, it is not necessary to create two recombined chromosomes and that select one (segragation). I construct only one recombined chromosome where self construct the first part of the chromosome. nb_cross = binomial(chromo_size, recombination) cross_pos = WalkerRandomSampling(*(chromo_size-1)).random(count=nb_cross).sort() recombined_chromo = Chromo() previous_cross = 0 for sex, one_cross in enumerate(cross_pos): if sex%2 == 0: recombined_cromo.alleles.append(self.chromosomes.alleles[previous_cross:(one_cross+1)]) else: recombined_cromo.alleles.append(other.chromosomes.alleles[previous_cross:(one_cross+1)]) previous_cross = one_cross off.chromosomes.append(recombined_chromo) return off class Pop(object): def __init__(self, inds): self.inds = inds def reproduction(self): "First chose those that reproduce and then simulate mutations in offsprings" # chosing those who reproduce - Creating the offspring population new_pop = Pop(inds=) fitness =  for one_ind in self.inds: fitness.append(one_ind.fitness()) min_fitness = min(fitness) if min_fitness < 0: fitness = [one_ind - min_fitness for one_ind in fitness] pick = WalkerRandomSampling(weights = fitness) if nb_chromosomes == 1 and recombination == 0: for i in xrange(pop_size): new_pop.inds.append(self.inds[pick.random()]) else: for i in xrange(pop_size): father = self.inds[pick.random()] mother = self.inds[pick.random()] off = father.reprod(mother) new_pop.inds.append(off) nb_off += 1 # Mutations for one_ind in new_pop.inds: for chromo_number in xrange(nb_chromosomes): one_ind.chromosomes[chromo_number].mutations() return new_pop def create_population(self): one_chromo = Chromo(alleles = *chromo_size) one_ind = Ind(chromosomes = [one_chromo for i in range(nb_chromosomes)]) return Pop(inds=[one_ind for i in xrange(pop_size)]) def stats(self, generation): line_to_write = str(generation) + '\t' + str(replicat) + '\t' + str(mut_rate) + '\t' + str(pdf_mut_scale) + '\t' + str(pdf_mutation.__name__)\ + '\t' + str(pop_size) + '\t' + str(nb_chromosomes) + '\t' + str(chromo_size) + '\t' + str(recombination) + '\t' + str(dominance) + '\t' if output_type == 'mean fitness': add = sum([ind.fitness() for ind in self.inds])/pop_size output_file.write(line_to_write + str(add) + '\n') def set_best_fitness_to_one(self): list_chromo = zip(*[map(fun_for_set_fitness,[ind.chromosomes[chromo_number] for ind in self.inds]) for chromo_number in xrange(nb_chromosomes)]) new_pop = Pop() for one_ind in xrange(0,pop_size,nb_chromosomes): new_pop.inds.append(list_chromo[one_ind:(ond_ind+nb_chromosomes)]) return new_pop def fun_for_set_fitness(list_one_chromo_number): l = zip(*list_one_chromo_number) for locus_pos, one_locus in enumerate(l): max_one_locus = max(one_locus) one_locus = [i/float(max_one_locus) for i in one_locus] l[locus_pos] = one_locus return zip(*l) ######### Main ############# def main_run(): population = Pop().create_population() for generation in xrange(Nb_generations): population.stats(generation) population = population.reproduction() shuffle(population.inds) population = population.set_best_fitness_to_one() ####### PARAMETERS ########## # Parameters Nb_generations = 120 # output_type = 'all individuals fitness' output_type = 'mean fitness' max_pop_size = 100 # this is only used to create the first (title, header) line! # Output file file_name = 'stats3.txt' path = '/Users/remimatthey-doret/Documents/Biologie/programmation/Python/Fitness distribution in the population/' + file_name output_file = open(path,'w') first_line = 'Generation\treplicat\tmut_rate\tpdf_mut_scale\tpdf_mutation\tpop_size\tnb_chromosomes\tchromo_size\trecombination\tdominance\t' if output_type == 'mean fitness': first_line += 'mean_fitness' if output_type == 'all individuals fitness': for ind in xrange(max_pop_size): first_line += 'fit_ind_' + str(ind) + '\t' output_file.write(first_line + '\n') # Parameters that iterate total_nb_runs = 3 * 10 # just enter the total number of iteration of the main_run function nb_runs_performed = 0 for mut_rate in [0.0001]: for pdf_mut_scale in [0.01,0.1,0.3]: # Note: with an negative exponential distribution (expovariate) the expected value is 1/lambda for pdf_mutation in [expovariate]: for pop_size in : for nb_chromosomes in : for chromo_size in : for recombination in : for dominance in : for replicat in xrange(10): main_run() nb_runs_performed += 1 print str(float(nb_runs_performed)/total_nb_runs * 100) + '%'