Roulette Selection in Genetic Algorithms

后端 未结 14 849
庸人自扰
庸人自扰 2020-11-27 12:19

Can anyone provide some pseudo code for a roulette selection function? How would I implement this:

相关标签:
14条回答
  • 2020-11-27 13:01

    Here's a compact java implementation I wrote recently for roulette selection, hopefully of use.

    public static gene rouletteSelection()
    {
        float totalScore = 0;
        float runningScore = 0;
        for (gene g : genes)
        {
            totalScore += g.score;
        }
    
        float rnd = (float) (Math.random() * totalScore);
    
        for (gene g : genes)
        {   
            if (    rnd>=runningScore &&
                    rnd<=runningScore+g.score)
            {
                return g;
            }
            runningScore+=g.score;
        }
    
        return null;
    }
    
    0 讨论(0)
  • 2020-11-27 13:02

    Here is some code in C :

    // Find the sum of fitnesses. The function fitness(i) should 
    //return the fitness value   for member i**
    
    float sumFitness = 0.0f;
    for (int i=0; i < nmembers; i++)
        sumFitness += fitness(i);
    
    // Get a floating point number in the interval 0.0 ... sumFitness**
    float randomNumber = (float(rand() % 10000) / 9999.0f) * sumFitness;
    
    // Translate this number to the corresponding member**
    int memberID=0;
    float partialSum=0.0f;
    
    while (randomNumber > partialSum)
    {
       partialSum += fitness(memberID);
       memberID++;
    } 
    
    **// We have just found the member of the population using the roulette algorithm**
    **// It is stored in the "memberID" variable**
    **// Repeat this procedure as many times to find random members of the population**
    
    0 讨论(0)
  • 2020-11-27 13:05

    The pseudocode posted contained some unclear elements, and it adds the complexity of generating offspring in stead of performing pure selection. Here is a simple python implementation of that pseudocode:

    def roulette_select(population, fitnesses, num):
        """ Roulette selection, implemented according to:
            <http://stackoverflow.com/questions/177271/roulette
            -selection-in-genetic-algorithms/177278#177278>
        """
        total_fitness = float(sum(fitnesses))
        rel_fitness = [f/total_fitness for f in fitnesses]
        # Generate probability intervals for each individual
        probs = [sum(rel_fitness[:i+1]) for i in range(len(rel_fitness))]
        # Draw new population
        new_population = []
        for n in xrange(num):
            r = rand()
            for (i, individual) in enumerate(population):
                if r <= probs[i]:
                    new_population.append(individual)
                    break
        return new_population
    
    0 讨论(0)
  • 2020-11-27 13:07

    Lots of correct solutions already, but I think this code is clearer.

    def select(fs):
        p = random.uniform(0, sum(fs))
        for i, f in enumerate(fs):
            if p <= 0:
                break
            p -= f
        return i
    

    In addition, if you accumulate the fs, you can produce a more efficient solution.

    cfs = [sum(fs[:i+1]) for i in xrange(len(fs))]
    
    def select(cfs):
        return bisect.bisect_left(cfs, random.uniform(0, cfs[-1]))
    

    This is both faster and it's extremely concise code. STL in C++ has a similar bisection algorithm available if that's the language you're using.

    0 讨论(0)
  • 2020-11-27 13:07

    Okay, so there are 2 methods for roulette wheel selection implementation: Usual and Stochastic Acceptance one.

    Usual algorithm:

    # there will be some amount of repeating organisms here.
    mating_pool = []
    
    all_organisms_in_population.each do |organism|
      organism.fitness.times { mating_pool.push(organism) }
    end
    
    # [very_fit_organism, very_fit_organism, very_fit_organism, not_so_fit_organism]
    return mating_pool.sample #=> random, likely fit, parent!
    

    Stochastic Acceptance algorithm:

    max_fitness_in_population = all_organisms_in_population.sort_by(:fitness)[0]
    loop do
      random_parent = all_organisms_in_population.sample
      probability = random_parent.fitness/max_fitness_in_population * 100
      # if random_parent's fitness is 90%,
      # it's very likely that rand(100) is smaller than it.
      if rand(100) < probability
        return random_parent #=> random, likely fit, parent!
      else
        next #=> or let's keep on searching for one.
      end
    end
    

    You can choose either, they will be returning identical results.


    Useful resources:

    http://natureofcode.com/book/chapter-9-the-evolution-of-code - a beginner-friendly and clear chapter on genetic algorithms. explains roulette wheel selection as a bucket of wooden letters (the more As you put in - the great is the chance of picking an A, Usual algorithm).

    https://en.wikipedia.org/wiki/Fitness_proportionate_selection - describes Stochastic Acceptance algorithm.

    0 讨论(0)
  • 2020-11-27 13:10

    I wrote a version in C# and am really looking for confirmation that it is indeed correct:

    (roulette_selector is a random number which will be in the range 0.0 to 1.0)

    private Individual Select_Roulette(double sum_fitness)
        {
            Individual ret = new Individual();
            bool loop = true;
    
            while (loop)
            {
                //this will give us a double within the range 0.0 to total fitness
                double slice = roulette_selector.NextDouble() * sum_fitness;
    
                double curFitness = 0.0;
    
                foreach (Individual ind in _generation)
                {
                    curFitness += ind.Fitness;
                    if (curFitness >= slice)
                    {
                        loop = false;
                        ret = ind;
                        break;
                    }
                }
            }
            return ret;
    
        }
    
    0 讨论(0)
提交回复
热议问题