Created
September 30, 2011 21:33
-
-
Save hfaulds/1255029 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 1 class Population | |
| 2 def initialize(population_size, target) | |
| 3 @target = target | |
| 4 | |
| 5 @population = [] | |
| 6 population_size.times do | |
| 7 @population.push Individual.create_random(target, target.length) | |
| 8 end | |
| 9 end | |
| 10 | |
| 11 def next_generation | |
| 12 target_length = @population.length | |
| 13 cull_population | |
| 14 repopulate(target_length).first.score | |
| 15 end | |
| 16 | |
| 17 def cull_population | |
| 18 order_population | |
| 19 @population.each_index do |index| | |
| 20 if should_be_culled?(index) | |
| 21 @population.delete_at(index) | |
| 22 end | |
| 23 end | |
| 24 end | |
| 25 | |
| 26 def repopulate(target_length) | |
| 27 order_population | |
| 28 growth = target_length - @population.length | |
| 29 babies = [] | |
| 30 growth.times do | |
| 31 mate_a = find_mate(@population) | |
| 32 mate_b = find_mate_for(mate_a) | |
| 33 babies << mate_a.mate_with(mate_b) | |
| 34 end | |
| 35 @population += babies | |
| 36 end | |
| 37 | |
| 38 def should_be_culled?(index) | |
| 39 rand(@population.length) <= index | |
| 40 end | |
| 41 | |
| 42 def should_mate(index) | |
| 43 rand(@population.length) <= index | |
| 44 end | |
| 45 | |
| 46 def find_mate(population) | |
| 47 while true do | |
| 48 population.each_index do |index| | |
| 49 if should_mate(index) | |
| 50 return population[index] | |
| 51 end | |
| 52 end | |
| 53 end | |
| 54 end | |
| 55 | |
| 56 def find_mate_for(individual) | |
| 57 rest_of_pop = [] | |
| 58 @population.each do |ind| | |
| 59 if ind != individual | |
| 60 rest_of_pop << ind | |
| 61 end | |
| 62 end | |
| 63 find_mate(rest_of_pop) | |
| 64 end | |
| 65 | |
| 66 def order_population | |
| 67 @population.sort! do |a,b,| | |
| 68 a.score <=> b.score | |
| 69 end | |
| 70 end | |
| 71 | |
| 72 def log | |
| 73 puts "-----" | |
| 74 @population.each do |individual| | |
| 75 puts individual.to_s | |
| 76 end | |
| 77 end | |
| 78 | |
| 79 def log_best | |
| 80 puts @population.first.to_s | |
| 81 end | |
| 82 end | |
| 83 | |
| 84 class Individual | |
| 85 def initialize(target, reproduction_system) | |
| 86 @target = target | |
| 87 @reproduction_system = reproduction_system | |
| 88 end | |
| 89 | |
| 90 def self.create_random(target, output_length) | |
| 91 Individual.new(target, ReproductionSystem.create_random(output_length)) | |
| 92 end | |
| 93 | |
| 94 def score | |
| 95 score = 0 | |
| 96 @reproduction_system.genes.each_index do |index| | |
| 97 score += (@target[index] - @reproduction_system.genes[index]).abs | |
| 98 end | |
| 99 score | |
| 100 end | |
| 101 | |
| 102 def mate_with(mate) | |
| 103 @reproduction_system.mate_with(mate) | |
| 104 end | |
| 105 | |
| 106 def be_mated_with(genetic_code) | |
| 107 Individual.new(@target, @reproduction_system.be_mated_with(genetic_code)) | |
| 108 end | |
| 109 | |
| 110 def to_s | |
| 111 @reproduction_system.to_s + " : " + score.to_s | |
| 112 end | |
| 113 end | |
| 114 | |
| 115 class ReproductionSystem | |
| 116 attr_reader :genes | |
| 117 def initialize(genes) | |
| 118 @genes = genes | |
| 119 end | |
| 120 | |
| 121 def self.random_gene_part | |
| 122 32 + rand(94) | |
| 123 end | |
| 124 | |
| 125 def self.create_random(output_length) | |
| 126 genes = [] | |
| 127 output_length.times do | |
| 128 genes.push(random_gene_part) | |
| 129 end | |
| 130 ReproductionSystem.new(genes) | |
| 131 end | |
| 132 | |
| 133 def to_s | |
| 134 out = '' | |
| 135 @genes.each do |part| | |
| 136 out += part.chr | |
| 137 end | |
| 138 out | |
| 139 end | |
| 140 | |
| 141 def mate_with(mate) | |
| 142 mate.be_mated_with(@genes) | |
| 143 end | |
| 144 | |
| 145 def be_mated_with(genetic_code) | |
| 146 length = @genes.length | |
| 147 a_half = genetic_code.slice(0, length/2) | |
| 148 b_half = @genes.slice(length/2,length-1) | |
| 149 genes = a_half + b_half | |
| 150 genes[rand(length)] = ReproductionSystem.random_gene_part | |
| 151 | |
| 152 ReproductionSystem.new(genes) | |
| 153 end | |
| 154 end | |
| 155 | |
| 156 population = Population.new(100, "Hello World") | |
| 157 population.order_population | |
| 158 population.log | |
| 159 i=0 | |
| 160 while(population.next_generation>0) do | |
| 161 puts "generation " + (i+=1).to_s | |
| 162 population.log_best | |
| 163 end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment