2012-04-25 18 views
7

में (रौलेट व्हील चयन) मैं वस्तुओं (गुणसूत्र) जो एक विशेषता फिटनेस है की एक सूची है (chromosome.fitness 0 और के बीच है 1)स्वास्थ्य आनुपातिक चयन अजगर

इस तरह की वस्तुओं की एक सूची को देखते हुए, कैसे कर सकते हैं मैं एक ऐसा कार्य लागू करता हूं जो एक एकल गुणसूत्र लौटाता है जिसका चयन करने का मौका इसकी फिटनेस के समान है? यही है, फिटनेस 0.8 के साथ गुणसूत्र फिटनेस 0.4 के साथ एक के रूप में चुना जाने की संभावना है।

मुझे कुछ पायथन और छद्म कोड कार्यान्वयन मिले हैं, लेकिन वे इस आवश्यकता के लिए बहुत जटिल हैं: फ़ंक्शन को केवल गुणसूत्रों की एक सूची की आवश्यकता होती है। क्रोमोसोम एक आंतरिक चर के रूप में अपनी फिटनेस स्टोर करते हैं।

मैंने पहले ही लिखा था कि कार्यान्वयन से पहले मैंने क्रोमोसोम को अपनी फिटनेस स्टोर करने की अनुमति देने का फैसला किया था, इसलिए बहुत अधिक जटिल और जुड़ी सूचियां और चीजें शामिल थीं।

---------------------------- संपादित करें ---------------- ------------

धन्यवाद लैटवेयर। निम्नलिखित कार्य काम करता प्रतीत होता है।

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

एक शब्दकोश से एक भारित यादृच्छिक विकल्प का चयन करने के लिए एक बहुत ही सरल तरीका है:

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 
+2

आप कई विकल्प है, या आप वजन का एक ही सेट के साथ कई मूल्यों लेने के लिए है, तो आप भी बदल सकती है यह ओ (एन) समाधान एक ओ (लॉग (एन)) समाधान में बाइनरी खोज, या यहां तक ​​कि एक ओ (1) समाधान का उपयोग करके किसी प्रकार की लुक-अप तालिका का उपयोग करके समाधान। –

+0

@SvenMarnach यह सच है, मैं यहां सबसे सरल समाधान दे रहा हूं, जरूरी नहीं कि सबसे तेज़ - यह वास्तव में ध्यान देने योग्य है। –

+0

[यह आलेख] (http://www.keithschwarz.com/darts-dice-coins/) इस नमूने के लिए ओ (1) एल्गोरिदम विकसित करने का एक अच्छा प्रदर्शन प्रदान करता है। – Dougal

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