class Population
Stand for a whole population used for an evolution experiment
Constants
- DEFAULT_EVOLVE_ITERATIONS
- DEFAULT_FORCE_FITNESS_RECALCULATION
- DEFAULT_KEEP_ALIVE_RATE
- DEFAULT_MUTATION_RATE
- NO_FITNESS
Attributes
fitness_target[RW]
force_fitness_recalculation[RW]
karyotypes[RW]
keep_alive_rate[R]
mutation_rate[R]
Public Class Methods
new(size, genome, fitness_calculator)
click to toggle source
# File lib/population.rb, line 24 def initialize(size, genome, fitness_calculator) raise 'size must be strictly positive.' if size < 1 @fitness_hash = {} @force_fitness_recalculation = DEFAULT_FORCE_FITNESS_RECALCULATION @mutation_rate = DEFAULT_MUTATION_RATE @keep_alive_rate = DEFAULT_KEEP_ALIVE_RATE @genome = Genome.new(genome) @fitness_calculator = fitness_calculator @karyotypes = Array.new(size) { @genome.create_random_karyotype } evaluate end
Public Instance Methods
evolve(iterations = DEFAULT_EVOLVE_ITERATIONS)
click to toggle source
This function make ou population evolving by:
-
Selecting and breeding the fittest karyotypes
-
Running the fitness evaluation on all the newly created karyotyopes
The selection process include three subprocesses:
-
Selecting the fittest individuals to keep alive
-
Mutating randomly (linear) selected individuals
-
Breeding randomly (fitness weighted) selected individuals
# File lib/population.rb, line 52 def evolve(iterations = DEFAULT_EVOLVE_ITERATIONS) i = 1 while (i <= iterations) && (@fitness_target.nil? || @fitness_target > @karyotypes[0].fitness) evolve_impl i += 1 end self end
keep_alive_rate=(value)
click to toggle source
keep alive rate setter function Accept values in the range [0,1]
# File lib/population.rb, line 20 def keep_alive_rate=(value) @keep_alive_rate = validate!(:keep_alive_rate, value) end
mutation_rate=(value)
click to toggle source
mutation rate setter function Accept values in the range [0,1]
# File lib/population.rb, line 14 def mutation_rate=(value) @mutation_rate = validate!(:mutation_rate, value) end
size()
click to toggle source
# File lib/population.rb, line 41 def size @karyotypes.size end
Private Instance Methods
build_new_karyotypes(keep_alive_count, mutation_count)
click to toggle source
# File lib/population.rb, line 99 def build_new_karyotypes(keep_alive_count, mutation_count) remaining = @karyotypes.size - mutation_count - keep_alive_count @karyotypes[0, keep_alive_count] .concat(Array.new(mutation_count) { create_random_mutation }) .concat(Array.new(remaining) { random_breed }) end
cached_fitness(karyotype)
click to toggle source
# File lib/population.rb, line 87 def cached_fitness(karyotype) @fitness_hash.fetch(karyotype.to_md5) { fitness karyotype } end
create_random_mutation()
click to toggle source
# File lib/population.rb, line 110 def create_random_mutation linear_random_select.copy.mutate end
evaluate()
click to toggle source
Run the fitness function for all karyotypes, and sort it by fitness
# File lib/population.rb, line 67 def evaluate if @force_fitness_recalculation @karyotypes.each { |karyotype| update!(karyotype, fitness(karyotype)) } else @karyotypes.each do |karyotype| update!(karyotype, cached_fitness(karyotype)) if karyotype.fitness.nil? end end @karyotypes.sort_by! { |karyotype| - karyotype.fitness } end
evolve_impl()
click to toggle source
# File lib/population.rb, line 91 def evolve_impl # Keeping alive a specific amount of the best karyotypes keep_alive_count = Integer(@karyotypes.size * @keep_alive_rate) mutation_count = Integer(@karyotypes.size * @mutation_rate) @karyotypes = build_new_karyotypes(keep_alive_count, mutation_count) evaluate end
fitness(karyotype)
click to toggle source
# File lib/population.rb, line 83 def fitness(karyotype) @fitness_calculator.call(karyotype) end
fitness_weighted_random_select()
click to toggle source
# File lib/population.rb, line 114 def fitness_weighted_random_select @karyotypes[ @karyotypes.size - Integer(Math.sqrt(Math.sqrt(1 + rand(@karyotypes.size**4 - 1)))) ] end
linear_random_select()
click to toggle source
# File lib/population.rb, line 106 def linear_random_select @karyotypes[rand @karyotypes.size] end
random_breed()
click to toggle source
# File lib/population.rb, line 121 def random_breed fitness_weighted_random_select + fitness_weighted_random_select end
update!(karyotype, fitness)
click to toggle source
# File lib/population.rb, line 78 def update!(karyotype, fitness) karyotype.fitness = fitness @fitness_hash[karyotype.to_md5] = karyotype.fitness end
validate!(label, value)
click to toggle source
# File lib/population.rb, line 125 def validate!(label, value) raise "#{label} value must be included in [0,1]" unless value.between?(0, 1) value end