Is there a better way of doing this?

mattia gervaz at gmail.com
Fri Mar 6 22:40:31 CET 2009


Il Fri, 06 Mar 2009 22:28:00 +0100, Peter Otten ha scritto:

> mattia wrote:
> 
>> Il Fri, 06 Mar 2009 14:06:14 +0100, Peter Otten ha scritto:
>> 
>>> mattia wrote:
>>> 
>>>> Hi, I'm new to python, and as the title says, can I improve this
>>>> snippet (readability, speed, tricks):
>>>> 
>>>> def get_fitness_and_population(fitness, population):
>>>>     return [(fitness(x), x) for x in population]
>>>> 
>>>> def selection(fitness, population):
>>>>     '''
>>>>     Select the parent chromosomes from a population according to
>>>>     their fitness (the better fitness, the bigger chance to be
>>>>     selected) ''' selected_population = []
>>>>     fap = get_fitness_and_population(fitness, population) pop_len =
>>>>     len(population)
>>>>     # elitism (it prevents a loss of the best found solution) # take
>>>>     the only 2 best solutions
>>>>     elite_population = sorted(fap)
>>>>     selected_population += [elite_population[pop_len-1][1]] +
>>>> [elite_population[pop_len-2][1]]
>>>>     # go on with the rest of the elements for i in range(pop_len-2):
>>>>         # do something
>>> 
>>> def selection1(fitness, population, N=2):
>>>     rest = sorted(population, key=fitness, reverse=True) best =
>>>     rest[:N] del rest[:N]
>>>     # work with best and rest
>>> 
>>> 
>>> def selection2(fitness, population, N=2):
>>>     decorated = [(-fitness(p), p) for p in population]
>>>     heapq.heapify(decorated)
>>>     
>>>     best = [heapq.heappop(decorated)[1] for _ in range(N)] rest = [p
>>>     for f, p in decorated]
>>>     # work with best and rest
>>> 
>>> Both implementations assume that you are no longer interested in the
>>> individuals' fitness once you have partitioned the population in two
>>> groups.
>>> 
>>> In theory the second is more efficient for "small" N and "large"
>>> populations.
>>> 
>>> Peter
>> 
>> Ok, but the fact is that I save the best individuals of the current
>> population, than I'll have to choose the others elements of the new
>> population (than will be N-2) in a random way. The common way is using
>> a roulette wheel selection (based on the fitness of the individuals, if
>> the total fitness is 200, and one individual has a fitness of 10, that
>> this individual will have a 0.05 probability to be selected to form the
>> new population). So in the selection of the best solution I have to use
>> the fitness in order to get the best individual, the last individual
>> use the fitness to have a chance to be selected. Obviously the old
>> population anf the new population must have the same number of
>> individuals.
> 
> You're right, it was a bad idea.
> 
> Peter

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



More information about the Python-list mailing list