Roulette Selection in Genetic Algorithms

后端 未结 14 847
庸人自扰
庸人自扰 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 12:46
    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;
            }
    
    0 讨论(0)
  • 2020-11-27 12:49

    From the above answer, I got the following, which was clearer to me than the answer itself.

    To give an example:

    Random(sum) :: Random(12) Iterating through the population, we check the following: random < sum

    Let us chose 7 as the random number.

    Index   |   Fitness |   Sum |   7 < Sum
    0       |   2   |   2       |   false
    1       |   3   |   5       |   false
    2       |   1   |   6       |   false
    3       |   4   |   10      |   true
    4       |   2   |   12      |   ...
    

    Through this example, the most fit (Index 3) has the highest percentage of being chosen (33%); as the random number only has to land within 6->10, and it will be chosen.

        for (unsigned int i=0;i<sets.size();i++) {
            sum += sets[i].eval();
        }       
        double rand = (((double)rand() / (double)RAND_MAX) * sum);
        sum = 0;
        for (unsigned int i=0;i<sets.size();i++) {
            sum += sets[i].eval();
            if (rand < sum) {
                //breed i
                break;
            }
        }
    
    0 讨论(0)
  • 2020-11-27 12:57

    Roulette Wheel Selection in MatLab:

    TotalFitness=sum(Fitness);
        ProbSelection=zeros(PopLength,1);
        CumProb=zeros(PopLength,1);
    
        for i=1:PopLength
            ProbSelection(i)=Fitness(i)/TotalFitness;
            if i==1
                CumProb(i)=ProbSelection(i);
            else
                CumProb(i)=CumProb(i-1)+ProbSelection(i);
            end
        end
    
        SelectInd=rand(PopLength,1);
    
        for i=1:PopLength
            flag=0;
            for j=1:PopLength
                if(CumProb(j)<SelectInd(i) && CumProb(j+1)>=SelectInd(i))
                    SelectedPop(i,1:IndLength)=CurrentPop(j+1,1:IndLength);
                    flag=1;
                    break;
                end
            end
            if(flag==0)
                SelectedPop(i,1:IndLength)=CurrentPop(1,1:IndLength);
            end
        end
    
    0 讨论(0)
  • 2020-11-27 12:57

    This Swift 4 array extension implements weighted random selection, a.k.a Roulette selection from its elements:

    public extension Array where Element == Double {
    
        /// Consider the elements as weight values and return a weighted random selection by index.
        /// a.k.a Roulette wheel selection.
        func weightedRandomIndex() -> Int {
            var selected: Int = 0
            var total: Double = self[0]
    
            for i in 1..<self.count { // start at 1
                total += self[i]
                if( Double.random(in: 0...1) <= (self[i] / total)) { selected = i }
            }
    
            return selected
        }
    }
    

    For example given the two element array:

    [0.9, 0.1]
    

    weightedRandomIndex() will return zero 90% of the time and one 10% of the time.

    Here is a more complete test:

    let weights = [0.1, 0.7, 0.1, 0.1]
    var results = [Int:Int]()
    let n = 100000
    for _ in 0..<n {
        let index = weights.weightedRandomIndex()
        results[index] = results[index, default:0] + 1
    }
    for (key,val) in results.sorted(by: { a,b in weights[a.key] < weights[b.key] }) {
        print(weights[key], Double(val)/Double(n))
    }
    

    output:

    0.1 0.09906
    0.1 0.10126
    0.1 0.09876
    0.7 0.70092
    

    This answer is basically the same as Andrew Mao's answer here: https://stackoverflow.com/a/15582983/74975

    0 讨论(0)
  • 2020-11-27 12:57

    Here is the code in python. This code can also handle the negative value of fitness.

    from numpy import min, sum, ptp, array 
    from numpy.random import uniform 
    
    list_fitness1 = array([-12, -45, 0, 72.1, -32.3])
    list_fitness2 = array([0.5, 6.32, 988.2, 1.23])
    
    def get_index_roulette_wheel_selection(list_fitness=None):
        """ It can handle negative also. Make sure your list fitness is 1D-numpy array"""
        scaled_fitness = (list_fitness - min(list_fitness)) / ptp(list_fitness)
        minimized_fitness = 1.0 - scaled_fitness
        total_sum = sum(minimized_fitness)
        r = uniform(low=0, high=total_sum)
        for idx, f in enumerate(minimized_fitness):
            r = r + f
            if r > total_sum:
                return idx
    
    get_index_roulette_wheel_selection(list_fitness1)
    get_index_roulette_wheel_selection(list_fitness2)
    
    1. Make sure your fitness list is 1D-numpy array
    2. Scaled the fitness list to the range [0, 1]
    3. Transform maximum problem to minimum problem by 1.0 - scaled_fitness_list
    4. Random a number between 0 and sum(minimizzed_fitness_list)
    5. Keep adding element in minimized fitness list until we get the value greater than the total sum
    6. You can see if the fitness is small --> it has bigger value in minimized_fitness --> It has a bigger chance to add and make the value greater than the total sum.
    0 讨论(0)
  • 2020-11-27 12:58

    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)
    0 讨论(0)
提交回复
热议问题