Is there a better way of doing this?
mattia
gervaz at gmail.com
Fri Mar 6 16:40:31 EST 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