Roulette wheel

Peter Otten __peter__ at web.de
Wed Mar 4 15:30:54 EST 2009


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



More information about the Python-list mailing list