Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 21st, 2012  |  syntax: None  |  size: 3.83 KB  |  hits: 13  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1.   1 class Population
  2.   2   def initialize(population_size, target)
  3.   3     @target = target
  4.   4
  5.   5     @population = []
  6.   6     population_size.times do
  7.   7       @population.push Individual.create_random(target, target.length)
  8.   8     end
  9.   9   end
  10.  10
  11.  11   def next_generation
  12.  12     target_length = @population.length
  13.  13     cull_population
  14.  14     repopulate(target_length).first.score
  15.  15   end
  16.  16
  17.  17   def cull_population
  18.  18     order_population
  19.  19     @population.each_index do |index|
  20.  20       if should_be_culled?(index)
  21.  21         @population.delete_at(index)
  22.  22       end
  23.  23     end
  24.  24   end
  25.  25  
  26.  26   def repopulate(target_length)
  27.  27     order_population
  28.  28     growth = target_length - @population.length
  29.  29     babies = []
  30.  30     growth.times do
  31.  31       mate_a = find_mate(@population)
  32.  32       mate_b = find_mate_for(mate_a)
  33.  33       babies << mate_a.mate_with(mate_b)
  34.  34     end
  35.  35     @population += babies
  36.  36   end
  37.  37  
  38.  38   def should_be_culled?(index)
  39.  39     rand(@population.length) <= index
  40.  40   end
  41.  41
  42.  42   def should_mate(index)
  43.  43     rand(@population.length) <= index
  44.  44   end
  45.  45  
  46.  46   def find_mate(population)
  47.  47     while true do
  48.  48       population.each_index do |index|
  49.  49         if should_mate(index)
  50.  50             return population[index]
  51.  51         end
  52.  52       end
  53.  53     end
  54.  54   end
  55.  55  
  56.  56   def find_mate_for(individual)
  57.  57     rest_of_pop = []
  58.  58     @population.each do |ind|
  59.  59       if ind != individual
  60.  60         rest_of_pop << ind
  61.  61       end
  62.  62     end
  63.  63     find_mate(rest_of_pop)
  64.  64   end
  65.  65
  66.  66   def order_population
  67.  67     @population.sort! do |a,b,|
  68.  68       a.score <=> b.score
  69.  69     end
  70.  70   end
  71.  71
  72.  72   def log
  73.  73     puts "-----"
  74.  74     @population.each do |individual|
  75.  75       puts individual.to_s
  76.  76     end
  77.  77   end
  78.  78
  79.  79   def log_best
  80.  80     puts @population.first.to_s
  81.  81   end
  82.  82 end
  83.  83
  84.  84 class Individual
  85.  85   def initialize(target, reproduction_system)
  86.  86     @target = target
  87.  87     @reproduction_system = reproduction_system
  88.  88   end
  89.  89
  90.  90   def self.create_random(target, output_length)
  91.  91     Individual.new(target, ReproductionSystem.create_random(output_length))
  92.  92   end
  93.  93
  94.  94   def score
  95.  95     score = 0
  96.  96     @reproduction_system.genes.each_index do |index|
  97.  97       score += (@target[index] - @reproduction_system.genes[index]).abs
  98.  98     end
  99.  99     score
  100. 100   end
  101. 101
  102. 102   def mate_with(mate)
  103. 103     @reproduction_system.mate_with(mate)
  104. 104   end
  105. 105
  106. 106   def be_mated_with(genetic_code)
  107. 107     Individual.new(@target, @reproduction_system.be_mated_with(genetic_code))
  108. 108   end
  109. 109
  110. 110   def to_s
  111. 111     @reproduction_system.to_s + "  :  " + score.to_s
  112. 112   end
  113. 113 end
  114. 114
  115. 115 class ReproductionSystem
  116. 116   attr_reader :genes
  117. 117   def initialize(genes)
  118. 118     @genes = genes
  119. 119   end
  120. 120
  121. 121   def self.random_gene_part
  122. 122     32 + rand(94)
  123. 123   end
  124. 124
  125. 125   def self.create_random(output_length)
  126. 126     genes = []
  127. 127     output_length.times do
  128. 128       genes.push(random_gene_part)
  129. 129     end
  130. 130     ReproductionSystem.new(genes)
  131. 131   end
  132. 132
  133. 133   def to_s
  134. 134     out = ''
  135. 135     @genes.each do |part|
  136. 136       out += part.chr
  137. 137     end
  138. 138     out
  139. 139   end
  140. 140
  141. 141   def mate_with(mate)
  142. 142     mate.be_mated_with(@genes)
  143. 143   end
  144. 144
  145. 145   def be_mated_with(genetic_code)
  146. 146     length = @genes.length
  147. 147     a_half = genetic_code.slice(0, length/2)
  148. 148     b_half = @genes.slice(length/2,length-1)
  149. 149     genes = a_half + b_half
  150. 150     genes[rand(length)] = ReproductionSystem.random_gene_part
  151. 151
  152. 152     ReproductionSystem.new(genes)
  153. 153   end
  154. 154 end
  155. 155
  156. 156 population = Population.new(100, "Hello World")
  157. 157 population.order_population
  158. 158 population.log
  159. 159 i=0
  160. 160 while(population.next_generation>0) do
  161. 161   puts "generation " + (i+=1).to_s
  162. 162   population.log_best
  163. 163 end