Python中的健身比例选择(轮盘赌选择)

时间:2012-04-25 21:23:50

标签: python random genetic-algorithm

我有一个对象列表(染色体),它具有属性适应性(染色体。适应性在0和1之间)

鉴于此类对象的列表,我如何实现一个返回单个染色体的函数,该染色体的被选择机会与其适应度成正比?也就是说,健康度为0.8的染色体被选为健康度为0.4的染色体的两倍。

我发现了一些Python和伪代码实现,但它们对于这个要求太复杂了:该函数只需要一个染色体列表。染色体将自己的适应性存储为内部变量。

我已经写过的实现是在我决定允许染色体存储它们自己的适应性之前,因此更复杂并涉及压缩列表和事物。

---------------------------- EDIT --------------- -------------

谢谢Lattyware。以下功能似乎有效。

def selectOne(self, population):
        max     = sum([c.fitness for c in population])
        pick    = random.uniform(0, max)
        current = 0
        for chromosome in population:
            current += chromosome.fitness
            if current > pick:
                return chromosome

6 个答案:

答案 0 :(得分:10)

从字典中选择加权随机选择有一种非常简单的方法:

def weighted_random_choice(choices):
    max = sum(choices.values())
    pick = random.uniform(0, max)
    current = 0
    for key, value in choices.items():
        current += value
        if current > pick:
            return key

如果您手头没有字典,可以修改它以适合您的课程(因为您没有提供更多详细信息,或生成字典:

choices = {chromosome: chromosome.fitness for chromosome in chromosomes}

假设健身是属性。

这是一个被修改为采用可迭代染色体的函数的例子,再次做出相同的假设。

def weighted_random_choice(chromosomes):
    max = sum(chromosome.fitness for chromosome in chromosomes)
    pick = random.uniform(0, max)
    current = 0
    for chromosome in chromosomes:
        current += chromosome.fitness
        if current > pick:
            return chromosome

答案 1 :(得分:2)

使用numpy.random.choice。

import numpy.random as npr
def selectOne(self, population):
    max = sum([c.fitness for c in population])
    selection_probs = [c.fitness/max for c in population]
    return population[npr.choice(len(population), p=selection_probs)]

答案 2 :(得分:1)

我更喜欢线路:

import itertools

def choose(population):
    bounds = list(itertools.accumulate(chromosome.fitness for chromosome in population))
    pick = random.random() * bounds[-1]
    return next(chromosome for chromosome, bound in zip(population, bounds) if pick < bound)

答案 3 :(得分:1)

from __future__ import division
import numpy as np
import random,pdb
import operator

def roulette_selection(weights):
        '''performs weighted selection or roulette wheel selection on a list
        and returns the index selected from the list'''

        # sort the weights in ascending order
        sorted_indexed_weights = sorted(enumerate(weights), key=operator.itemgetter(1));
        indices, sorted_weights = zip(*sorted_indexed_weights);
        # calculate the cumulative probability
        tot_sum=sum(sorted_weights)
        prob = [x/tot_sum for x in sorted_weights]
        cum_prob=np.cumsum(prob)
        # select a random a number in the range [0,1]
        random_num=random.random()

        for index_value, cum_prob_value in zip(indices,cum_prob):
            if random_num < cum_prob_value:
                return index_value


if __name__ == "__main__":
    weights=[1,2,6,4,3,7,20]
    print (roulette_selection(weights))
    weights=[1,2,2,2,2,2,2]
    print (roulette_selection(weights))

答案 4 :(得分:1)

def Indvs_wieght(Indvs): # to comput probality of selecting each Indvs by its fitness
    s=1
    s=sum(i.fitness for i in Indvs)
    wieghts = list()
    for i in range(len(Indvs)) :
        wieghts.append(Indvs[i].fitness/s)
    return wieghts  

def select_parents(indvs,indvs_wieghts,number_of_parents=40): # Roulette Wheel Selection method  #number of selected  parent 
    return np.random.choice(indvs,size=number_of_parents,p=indvs_wieghts)

答案 5 :(得分:-1)

import random

def weighted_choice(items):
    total_weight = sum(item.weight for item in items)
    weight_to_target = random.uniform(0, total_weight)
    for item in items:
        weight_to_target -= item.weight
        if weight_to_target <= 0:
            return item
相关问题