Roulette Selection in Genetic Algorithms

2020-01-24 11:15发布

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

alt text

I don't really understand how to read this math notation. I never took any probability or statistics.

13条回答
放荡不羁爱自由
2楼-- · 2020-01-24 11:47
Based on my research ,Here is another implementation in C# if there is a need for it:


//those with higher fitness get selected wit a large probability 
//return-->individuals with highest fitness
        private int RouletteSelection()
        {
            double randomFitness = m_random.NextDouble() * m_totalFitness;
            int idx = -1;
            int mid;
            int first = 0;
            int last = m_populationSize -1;
            mid = (last - first)/2;

            //  ArrayList's BinarySearch is for exact values only
            //  so do this by hand.
            while (idx == -1 && first <= last)
            {
                if (randomFitness < (double)m_fitnessTable[mid])
                {
                    last = mid;
                }
                else if (randomFitness > (double)m_fitnessTable[mid])
                {
                    first = mid;
                }
                mid = (first + last)/2;
                //  lies between i and i+1
                if ((last - first) == 1)
                    idx = last;
            }
            return idx;
        }
查看更多
霸刀☆藐视天下
3楼-- · 2020-01-24 11:49

Prof. Thrun of Stanford AI lab also presented a fast(er?) re-sampling code in python during his CS373 of Udacity. Google search result led to the following link:

http://www.udacity-forums.com/cs373/questions/20194/fast-resampling-algorithm

Hope this helps

查看更多
姐就是有狂的资本
4楼-- · 2020-01-24 11:51

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.

查看更多
beautiful°
5楼-- · 2020-01-24 11:54

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;

    }
查看更多
贪生不怕死
6楼-- · 2020-01-24 11:55

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.

查看更多
爷、活的狠高调
7楼-- · 2020-01-24 11:56

This is called roulette-wheel selection via stochastic acceptance:

/// \param[in] f_max maximum fitness of the population
///
/// \return index of the selected individual
///
/// \note Assuming positive fitness. Greater is better.

unsigned rw_selection(double f_max)
{
  for (;;)
  {
    // Select randomly one of the individuals
    unsigned i(random_individual());

    // The selection is accepted with probability fitness(i) / f_max
    if (uniform_random_01() < fitness(i) / f_max)
      return i;
  }   
}

The average number of attempts needed for a single selection is:

τ = fmax / avg(f)

  • fmax is the maximum fitness of the population
  • avg(f) is the average fitness

τ doesn't depend explicitly on the number of individual in the population (N), but the ratio can change with N.

However in many application (where the fitness remains bounded and the average fitness doesn't diminish to 0 for increasing N) τ doesn't increase unboundedly with N and thus a typical complexity of this algorithm is O(1) (roulette wheel selection using search algorithms has O(N) or O(log N) complexity).

The probability distribution of this procedure is indeed the same as in the classical roulette-wheel selection.

For further details see:

  • Roulette-wheel selection via stochastic acceptance (Adam Liposki, Dorota Lipowska - 2011)
查看更多
登录 后发表回答