# Is there a better way of doing this?

mattia gervaz at gmail.com
Sat Mar 7 00:31:01 CET 2009

```Il Fri, 06 Mar 2009 14:13:47 -0800, Scott David Daniels ha scritto:

> mattia wrote:
>> Here is my last shot, where I get rid of all the old intermediate
>> functions:
>>
>> def selection(fitness, population):
>>     lp = len(population)
>>     roulette_wheel = []
>>     for x in population:
>>         roulette_wheel += [x]*fitness(x)
>>     selected_population = [[]]*lp
>>     selected_population[:2] = sorted(population, key=fitness,
>> reverse=True)[:2]
>>     selected_population[2:] = [choice(roulette_wheel) for _ in range
>> (lp-2)]
> Try something like this to choose likely couples:
>
>      import random
>      import bisect
>
>      def choose_pairs(fitness_population, decider=random):
>          '''Pick and yield pairs weighted by fitness for crossing.
>
>          We assume weighted_population has fitness already calculated.
>          decide is a parameter to allow testing. '''
>          total = 0
>          cumulative = []
>          candidates = []
>          for fitness, individual in set(fitness_population):
>              # calculate total weights, extract real candidates if
>              fitness > 0:
>                  total += fitness
>                  cumulative.append(total)
>                  candidates.append(individual)
>          assert len(candidates) > 1
>          while True:
>              # pick a candidate by weight
>              c0 = decider.random() * total
>              first = bisect.bisect_left(cumulative, c0) if first:
>                  weighting = cumulative[first] - cumulative[first - 1]
>              else:
>                  weighting = cumulative[0]
>              # pick another distinct candidate by fitness c1 = choice =
>              decider.random() * (total - weighting) if choice >=
>              cumulative[first] - weighting:
>                  choice += weight # adjust to avoid selecting first
>              second = bisect.bisect_left(cumulative, choice) yield
>              candidates[first], candidates[second]
>
> --Scott David Daniels
> Scott.Daniels at Acm.Org

Thanks, I've found another solution here: http://www.obitko.com/tutorials/
genetic-algorithms/selection.php
so here is my implementation:

def create_chromosome(min, max, length):
return [randint(min, max) for i in range(length)]

def create_population(nelem, min, max, length):
# preconditions: nelem > 1 and nelem is even
if not nelem > 1:
nelem = 2
if not nelem%2 == 0:
print("The population must have an even number of elements.
Correcting...")
nelem += 1
return [create_chromosome(min, max, length) for i in range(nelem)]

def get_fap(fitness, population):
fap = []
total = 0
for x in population:
f = fitness(x)
fap += [(f, x)]
total += f
return sorted(fap, reverse=True), total

def my_rw():
list, tot = get_fap(sum, pop)
r = randint(0, tot-1)
i = 0
print(r)
for f, e in list:
i += f
print(i)
if i > r:
return e
return [] # never reached

if __name__ == "__main__":
pop = create_population(5, 0, 1, 10)
# selection_mat(sum, pop)
#print(rw(sum, pop))
list, tot = get_fap(sum, pop)
print(list)
print(tot)
for i in range(6):
print(my_rw())

```