Class: Darwinning::Population
- Inherits:
-
Object
- Object
- Darwinning::Population
- Defined in:
- lib/darwinning/population.rb
Instance Attribute Summary collapse
-
#fitness_goal ⇒ Object
Returns the value of attribute fitness_goal.
-
#generation ⇒ Object
Returns the value of attribute generation.
-
#generations_limit ⇒ Object
Returns the value of attribute generations_limit.
-
#members ⇒ Object
Returns the value of attribute members.
-
#mutation_rate ⇒ Object
Returns the value of attribute mutation_rate.
-
#organism ⇒ Object
Returns the value of attribute organism.
Instance Method Summary collapse
- #best_member ⇒ Object
- #build_population(population_size) ⇒ Object
- #crossover(m1, m2) ⇒ Object
- #evolution_over? ⇒ Boolean
- #evolve! ⇒ Object
-
#initialize(organism, population_size, fitness_goal, mutation_rate = 0.0, generations_limit = 0, manual_fitness = false) ⇒ Population
constructor
A new instance of Population.
- #make_next_generation! ⇒ Object
- #mutate! ⇒ Object
- #set_members_fitness!(fitness_values) ⇒ Object
- #sexytimes(m1, m2) ⇒ Object
- #size ⇒ Object
- #weighted_select(members) ⇒ Object
Constructor Details
#initialize(organism, population_size, fitness_goal, mutation_rate = 0.0, generations_limit = 0, manual_fitness = false) ⇒ Population
Returns a new instance of Population.
6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/darwinning/population.rb', line 6 def initialize(organism, population_size, fitness_goal, mutation_rate = 0.0, generations_limit = 0, manual_fitness = false) @organism = organism @fitness_goal = fitness_goal @mutation_rate = mutation_rate @generations_limit = generations_limit @manual_fitness = manual_fitness @members = [] @generation = 0 # initial population is generation 0 build_population(population_size) end |
Instance Attribute Details
#fitness_goal ⇒ Object
Returns the value of attribute fitness_goal.
4 5 6 |
# File 'lib/darwinning/population.rb', line 4 def fitness_goal @fitness_goal end |
#generation ⇒ Object
Returns the value of attribute generation.
4 5 6 |
# File 'lib/darwinning/population.rb', line 4 def generation @generation end |
#generations_limit ⇒ Object
Returns the value of attribute generations_limit.
4 5 6 |
# File 'lib/darwinning/population.rb', line 4 def generations_limit @generations_limit end |
#members ⇒ Object
Returns the value of attribute members.
4 5 6 |
# File 'lib/darwinning/population.rb', line 4 def members @members end |
#mutation_rate ⇒ Object
Returns the value of attribute mutation_rate.
4 5 6 |
# File 'lib/darwinning/population.rb', line 4 def mutation_rate @mutation_rate end |
#organism ⇒ Object
Returns the value of attribute organism.
4 5 6 |
# File 'lib/darwinning/population.rb', line 4 def organism @organism end |
Instance Method Details
#best_member ⇒ Object
112 113 114 |
# File 'lib/darwinning/population.rb', line 112 def best_member @members.sort_by { |m| m.fitness }[0] end |
#build_population(population_size) ⇒ Object
18 19 20 21 22 |
# File 'lib/darwinning/population.rb', line 18 def build_population(population_size) population_size.times do |i| @members << @organism.new end end |
#crossover(m1, m2) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/darwinning/population.rb', line 30 def crossover(m1, m2) genotypes1 = [] genotypes2 = [] m1.genotypes.zip(m2.genotypes).each do |g| if m1.genotypes.index(g[0]) % 2 == 0 genotypes1 << g[0] genotypes2 << g[1] else genotypes1 << g[1] genotypes2 << g[0] end end [@organism.new(genotypes1), @organism.new(genotypes2)] end |
#evolution_over? ⇒ Boolean
107 108 109 110 |
# File 'lib/darwinning/population.rb', line 107 def evolution_over? # check if the fiteness goal or generation limit has been met @generation == @generations_limit or best_member.fitness == @fitness_goal end |
#evolve! ⇒ Object
24 25 26 27 28 |
# File 'lib/darwinning/population.rb', line 24 def evolve! until evolution_over? make_next_generation! end end |
#make_next_generation! ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/darwinning/population.rb', line 85 def make_next_generation! temp_members = @members used_members = [] new_members = [] until new_members.length == @members.length/2 m1 = weighted_select(@members - used_members) used_members << m1 m2 = weighted_select(@members - used_members) used_members << m2 new_members << crossover(m1,m2) end new_members.flatten! @members = new_members mutate! @generation += 1 end |
#mutate! ⇒ Object
71 72 73 74 75 76 77 78 79 |
# File 'lib/darwinning/population.rb', line 71 def mutate! @members.map! { |m| if (0..100).to_a.sample < @mutation_rate*100 m.mutate! else m end } end |
#set_members_fitness!(fitness_values) ⇒ Object
81 82 83 |
# File 'lib/darwinning/population.rb', line 81 def set_members_fitness!(fitness_values) @members.to_enum.each_with_index { |m, i| m.fitness = fitness_values[i] } end |
#sexytimes(m1, m2) ⇒ Object
47 48 49 |
# File 'lib/darwinning/population.rb', line 47 def sexytimes(m1, m2) crossover(m1, m2) end |
#size ⇒ Object
116 117 118 |
# File 'lib/darwinning/population.rb', line 116 def size @members.length end |
#weighted_select(members) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/darwinning/population.rb', line 51 def weighted_select(members) e = 0.01 fitness_sum = members.inject(0) { |sum, m| sum + m.fitness } weighted_members = members.sort_by { |m| (m.fitness - @fitness_goal).abs }.map { |m| [m, fitness_sum / ((m.fitness - @fitness_goal).abs + e)] } weight_sum = weighted_members.inject(0) { |sum, m| sum + m[1] } pick = (0..weight_sum).to_a.sample weighted_members.reverse! # In order to pop from the end we need the lowest ranked first pick_sum = 0 until pick_sum > pick do selected_member = weighted_members.pop pick_sum += selected_member[1] end selected_member[0] end |