require 'lib/roulette' module Selection # Stochastic Universal Sampling selection method. The probability of the individual selection is # proportional to some (usually fitness) non-negative value (as in Roulette selection). # However, more individuals can be selected at once by the single run of a wheel, which brings # a better spread of the results (in comparision with Roulette method). # # See http://en.wikipedia.org/wiki/Stochastic_universal_sampling # class Sampling < Roulette # Set the proportional_by or the block for obtaining invividual's proportion. # See Roulette#proportional_by def initialize( proportional_by=nil, &block ) super end # Select individuals from the population. # It can be specified how_much individuals will be selected. def select( how_much, population=self.population ) raise "Sampling: cannot select from an empty population" if population.empty? raise "Sampling: cannot select more than population.size" if how_much > population.size return [] if how_much == 0 @sum,@wheel = wheel_core population @population = population step = @sum.to_f/how_much ballot = step * @random.rand width = 0.0 winners = [] @wheel.each_with_index do |slot,index| width += slot.width next if ballot > width winners.push slot.original ballot += step end winners end # Select one individual from the population (same as Roulette#select_one, but a bit less effective). def select_one population=self.population select( 1, population ).first end end end # Selection