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())



More information about the Python-list mailing list