Roulette wheel

mattia gervaz at gmail.com
Thu Mar 5 16:48:01 CET 2009


Il Wed, 04 Mar 2009 21:30:54 +0100, Peter Otten ha scritto:

> mattia wrote:
> 
>> Hi everyone, I'm new to python and I want to create some simple code in
>> order to code the classical genetic algorithm example: given a
>> population of chromosomes, encoded using 1 and 0, find the chromosome
>> with the maximum number of 1s. Now, despite all the code used to
>> implement the solution, I'm wondering if there is a better way to use
>> the so-called roulette wheel selection in this problem. Here I paste
>> the code of my solution, any advice will be helpful:
> 
> Your code looks good to me.
> 
>> from random import randint, random
>> 
>> def create_chromosome(min, max, length):
>>     chromosome = []
>>     for i in range(length):
>>         chromosome.append(randint(min, max))
>>     return chromosome
>> 
>> def fitness(chrm, ffunc=sum):
>>     return ffunc(chrm)
> 
> fitness = sum
> 
> has the same effect, without the extra indirection.
>  
>> def create_population(nelem, min, max, length):
>>     return [create_chromosome(min, max, length) for i in range(nelem)]
>> 
>> def get_fitness_and_population(population):
>>     return [(fitness(x), x) for x in population]
>>     
>> def get_roulette_wheel(population):
>>     roulette_wheel = []
>>     index = 0
>>     
>>     for x in get_fitness_and_population(population):
>>         for j in range(x[0]):
>>             roulette_wheel.append(index)
>>         index += 1
> 
> Make that
> 
>       for index, x in enumerate(get_fitness_and_population(population)):
>           ...
> 
> I'd also pass the the fitness function explicitly around instead of
> making it a global.
> 
>>     return roulette_wheel
>> 
>> pop = create_population(5, 0, 1, 10)
>> rw = get_roulette_wheel(pop)
>> print(rw)
>> print(len(rw))
>> ri = randint(0, len(rw) - 1)
>> print("Random index:", rw[ri], ", value:", pop[rw[ri]])
> 
> But these are minor nits :)
> 
> Here's a slightly different approach:
> 
> from random import randint, choice
> 
> def create_chromosome(min, max, length):
>     return [randint(min, max) for i in range(length)]
> 
> def create_population(nelem, min, max, length):
>     return [create_chromosome(min, max, length) for i in range(nelem)]
> 
> def get_fitness_and_population(population, fitness):
>     return [(fitness(x), x) for x in population]
> 
> def get_roulette_wheel(weight_value_pairs):
>     roulette_wheel = []
>     for weight, value in weight_value_pairs:
>         roulette_wheel += [value]*weight
>     return roulette_wheel
> 
> if __name__ == "__main__":
>     pop = create_population(5, 0, 1, 10)
>     fap = get_fitness_and_population(pop, sum) rw =
>     get_roulette_wheel(fap)
>     print("Random value:", choice(rw))
> 
> Note how get_roulette_wheel() is now completeley independent of the
> concrete problem you are using it for.
> 
> Peter

The last question: how can I improve readability in this piece of code?

def crossover(pop, prob=0.6):
    """
    With a crossover probability cross over the parents to form new
    offspring. If no crossover was performed, offspring is the exact copy of parents.
    """
    cpop = []
    for i in range(0, len(pop), 2):
        # crossover
        if prob > random():
            crossover_point = randint(0, len(pop[i])-1)
            nchromosome1 = pop[i][:crossover_point] + pop[i+1][crossover_point:]
            nchromosome2 = pop[i+1][:crossover_point] + pop[i][crossover_point:]
        else:
            nchromosome1 = pop[i][:]
            nchromosome2 = pop[i+1][:]
        cpop += [nchromosome1] + [nchromosome2]
    return cpop

And with this one my example is complete!



More information about the Python-list mailing list