rubyneat 0.3.5.alpha.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (261) hide show
  1. checksums.yaml +7 -0
  2. data/.directory +4 -0
  3. data/.gitignore.orig +20 -0
  4. data/.idea/.name +1 -0
  5. data/.idea/.rakeTasks +7 -0
  6. data/.idea/dictionaries/trader.xml +3 -0
  7. data/.idea/encodings.xml +5 -0
  8. data/.idea/misc.xml +5 -0
  9. data/.idea/modules.xml +9 -0
  10. data/.idea/rubyneat.iml +197 -0
  11. data/.idea/runConfigurations/invpend_neat.xml +26 -0
  12. data/.idea/runConfigurations/sigdebug_neat.xml +24 -0
  13. data/.idea/runConfigurations/xor_neat.xml +26 -0
  14. data/.idea/runConfigurations/xordebug_neat.xml +24 -0
  15. data/.idea/runConfigurations/xorsin_neat.xml +24 -0
  16. data/.idea/scopes/scope_settings.xml +5 -0
  17. data/.idea/vcs.xml +7 -0
  18. data/.idea/workspace.xml +1124 -0
  19. data/.semver +5 -0
  20. data/.yardoc/checksums +11 -0
  21. data/.yardoc/object_types +0 -0
  22. data/.yardoc/objects/root.dat +0 -0
  23. data/.yardoc/proxy_types +0 -0
  24. data/Gemfile +32 -0
  25. data/Gemfile.lock +135 -0
  26. data/Gemfile.lock.orig +147 -0
  27. data/Guardfile +8 -0
  28. data/Rakefile +61 -0
  29. data/bin/neat +83 -0
  30. data/config/application.rb +5 -0
  31. data/doc/ControllerPoint.html +125 -0
  32. data/doc/CuteA.html +286 -0
  33. data/doc/CuteB.html +297 -0
  34. data/doc/DSL.html +883 -0
  35. data/doc/NEAT/BasicNeuronTypes/BiasNeuron.html +518 -0
  36. data/doc/NEAT/BasicNeuronTypes/CosineNeuron.html +274 -0
  37. data/doc/NEAT/BasicNeuronTypes/InputNeuron.html +366 -0
  38. data/doc/NEAT/BasicNeuronTypes/SigmoidNeuron.html +275 -0
  39. data/doc/NEAT/BasicNeuronTypes/SineNeuron.html +274 -0
  40. data/doc/NEAT/BasicNeuronTypes/TanhNeuron.html +274 -0
  41. data/doc/NEAT/BasicNeuronTypes.html +136 -0
  42. data/doc/NEAT/Controller/NeatSettings.html +3985 -0
  43. data/doc/NEAT/Controller.html +2490 -0
  44. data/doc/NEAT/Critter/Genotype/Gene.html +979 -0
  45. data/doc/NEAT/Critter/Genotype.html +1601 -0
  46. data/doc/NEAT/Critter/Phenotype.html +603 -0
  47. data/doc/NEAT/Critter.html +1037 -0
  48. data/doc/NEAT/DSL.html +1255 -0
  49. data/doc/NEAT/Evaluator.html +420 -0
  50. data/doc/NEAT/Evolver/CritterOp.html +551 -0
  51. data/doc/NEAT/Evolver.html +602 -0
  52. data/doc/NEAT/Expressor.html +327 -0
  53. data/doc/NEAT/Graph/DependencyResolver.html +478 -0
  54. data/doc/NEAT/Graph/GraphException.html +123 -0
  55. data/doc/NEAT/Graph.html +402 -0
  56. data/doc/NEAT/NeatException.html +123 -0
  57. data/doc/NEAT/NeatOb.html +567 -0
  58. data/doc/NEAT/Neuron.html +1067 -0
  59. data/doc/NEAT/Operator.html +162 -0
  60. data/doc/NEAT/Population.html +1961 -0
  61. data/doc/NEAT/Trait.html +169 -0
  62. data/doc/NEAT.html +588 -0
  63. data/doc/_index.html +373 -0
  64. data/doc/class_list.html +54 -0
  65. data/doc/css/common.css +1 -0
  66. data/doc/css/full_list.css +57 -0
  67. data/doc/css/style.css +339 -0
  68. data/doc/file_list.html +53 -0
  69. data/doc/frames.html +26 -0
  70. data/doc/index.html +373 -0
  71. data/doc/js/app.js +219 -0
  72. data/doc/js/full_list.js +178 -0
  73. data/doc/js/jquery.js +4 -0
  74. data/doc/method_list.html +1415 -0
  75. data/doc/top-level-namespace.html +164 -0
  76. data/foo/foo_aquarium_example.rb +38 -0
  77. data/foo/foo_gosu.rb +99 -0
  78. data/foo/foo_rubygoo.rb +104 -0
  79. data/foo/foo_sdl.rb +34 -0
  80. data/foo/icon.png +0 -0
  81. data/lib/rubyneat/critter.rb +374 -0
  82. data/lib/rubyneat/default_neat.rb +10 -0
  83. data/lib/rubyneat/dsl.rb +130 -0
  84. data/lib/rubyneat/evaluator.rb +51 -0
  85. data/lib/rubyneat/evolver.rb +315 -0
  86. data/lib/rubyneat/expressor.rb +110 -0
  87. data/lib/rubyneat/graph.rb +95 -0
  88. data/lib/rubyneat/neuron.rb +152 -0
  89. data/lib/rubyneat/population.rb +227 -0
  90. data/lib/rubyneat/rubyneat.rb +429 -0
  91. data/lib/rubyneat.rb +8 -0
  92. data/neater/invpend_neat.rb +150 -0
  93. data/neater/rnlib/inverted_pendulum.rb +380 -0
  94. data/neater/rnlib/xor.rb +10 -0
  95. data/neater/sigdebug_neat.rb +136 -0
  96. data/neater/xor_neat.rb +137 -0
  97. data/neater/xoranalog_neat.rb +138 -0
  98. data/neater/xorsin_neat.rb +143 -0
  99. data/projectFilesBackup/.idea/rubyneat.iml +180 -0
  100. data/public/.directory +4 -0
  101. data/public/background.png +0 -0
  102. data/public/background.xcf +0 -0
  103. data/public/cart.png +0 -0
  104. data/public/cart.xcf +0 -0
  105. data/public/metalpoles_molton_ball_l.jpg +0 -0
  106. data/public/old_background.png +0 -0
  107. data/public/pointer.png +0 -0
  108. data/public/pointer.xcf +0 -0
  109. data/public/pole.kra +0 -0
  110. data/public/pole.png +0 -0
  111. data/public/pole.xcf +0 -0
  112. data/public/wheel-of-year-stone-DD-131-WOYS.jpg +0 -0
  113. data/public/wheel.png +0 -0
  114. data/public/wheel.xcf +0 -0
  115. data/public/wood-planks-texture.jpg +0 -0
  116. data/rdoc/ControllerPoint.html +116 -0
  117. data/rdoc/CuteA.html +177 -0
  118. data/rdoc/CuteB.html +178 -0
  119. data/rdoc/DSLSetup.html +177 -0
  120. data/rdoc/GameTestWindow.html +242 -0
  121. data/rdoc/GameWindow.html +292 -0
  122. data/rdoc/Gemfile.html +215 -0
  123. data/rdoc/Gemfile_lock.html +327 -0
  124. data/rdoc/GraphTest.html +210 -0
  125. data/rdoc/Guardfile.html +198 -0
  126. data/rdoc/InvertedPendulum/Cart.html +668 -0
  127. data/rdoc/InvertedPendulum/DSL.html +259 -0
  128. data/rdoc/InvertedPendulum/InvPendWindow.html +402 -0
  129. data/rdoc/InvertedPendulum.html +198 -0
  130. data/rdoc/Logger.html +98 -0
  131. data/rdoc/NEAT/BasicNeuronTypes/BiasNeuron.html +265 -0
  132. data/rdoc/NEAT/BasicNeuronTypes/CosineNeuron.html +162 -0
  133. data/rdoc/NEAT/BasicNeuronTypes/InputNeuron.html +206 -0
  134. data/rdoc/NEAT/BasicNeuronTypes/SigmoidNeuron.html +162 -0
  135. data/rdoc/NEAT/BasicNeuronTypes/SineNeuron.html +162 -0
  136. data/rdoc/NEAT/BasicNeuronTypes/TanhNeuron.html +161 -0
  137. data/rdoc/NEAT/BasicNeuronTypes.html +107 -0
  138. data/rdoc/NEAT/Controller/NeatSettings.html +880 -0
  139. data/rdoc/NEAT/Controller.html +729 -0
  140. data/rdoc/NEAT/Critter/Genotype/Gene.html +457 -0
  141. data/rdoc/NEAT/Critter/Genotype.html +735 -0
  142. data/rdoc/NEAT/Critter/Phenotype.html +330 -0
  143. data/rdoc/NEAT/Critter.html +489 -0
  144. data/rdoc/NEAT/DSL.html +729 -0
  145. data/rdoc/NEAT/Evaluator.html +256 -0
  146. data/rdoc/NEAT/Evolver/CritterOp.html +349 -0
  147. data/rdoc/NEAT/Evolver.html +891 -0
  148. data/rdoc/NEAT/Expressor.html +402 -0
  149. data/rdoc/NEAT/Graph/DependencyResolver.html +291 -0
  150. data/rdoc/NEAT/Graph/GraphException.html +105 -0
  151. data/rdoc/NEAT/Graph.html +263 -0
  152. data/rdoc/NEAT/NeatException.html +105 -0
  153. data/rdoc/NEAT/NeatOb.html +325 -0
  154. data/rdoc/NEAT/Neuron.html +481 -0
  155. data/rdoc/NEAT/Operator.html +109 -0
  156. data/rdoc/NEAT/Population.html +935 -0
  157. data/rdoc/NEAT/Trait.html +117 -0
  158. data/rdoc/NEAT.html +422 -0
  159. data/rdoc/Object.html +384 -0
  160. data/rdoc/Phi.html +98 -0
  161. data/rdoc/Player.html +383 -0
  162. data/rdoc/Rakefile.html +254 -0
  163. data/rdoc/RubyNEAT/Application.html +105 -0
  164. data/rdoc/RubyNEAT.html +98 -0
  165. data/rdoc/SDL/Event2.html +98 -0
  166. data/rdoc/SDL.html +98 -0
  167. data/rdoc/Vector.html +195 -0
  168. data/rdoc/created.rid +125 -0
  169. data/rdoc/doc/ControllerPoint_html.html +299 -0
  170. data/rdoc/doc/CuteA_html.html +438 -0
  171. data/rdoc/doc/CuteB_html.html +436 -0
  172. data/rdoc/doc/DSL_html.html +992 -0
  173. data/rdoc/doc/NEAT/BasicNeuronTypes/BiasNeuron_html.html +617 -0
  174. data/rdoc/doc/NEAT/BasicNeuronTypes/CosineNeuron_html.html +413 -0
  175. data/rdoc/doc/NEAT/BasicNeuronTypes/InputNeuron_html.html +498 -0
  176. data/rdoc/doc/NEAT/BasicNeuronTypes/SigmoidNeuron_html.html +413 -0
  177. data/rdoc/doc/NEAT/BasicNeuronTypes/SineNeuron_html.html +413 -0
  178. data/rdoc/doc/NEAT/BasicNeuronTypes/TanhNeuron_html.html +412 -0
  179. data/rdoc/doc/NEAT/BasicNeuronTypes_html.html +310 -0
  180. data/rdoc/doc/NEAT/Controller/NeatSettings_html.html +3324 -0
  181. data/rdoc/doc/NEAT/Controller_html.html +2212 -0
  182. data/rdoc/doc/NEAT/Critter/Genotype/Gene_html.html +997 -0
  183. data/rdoc/doc/NEAT/Critter/Genotype_html.html +1556 -0
  184. data/rdoc/doc/NEAT/Critter/Phenotype_html.html +687 -0
  185. data/rdoc/doc/NEAT/Critter_html.html +1037 -0
  186. data/rdoc/doc/NEAT/DSL_html.html +1349 -0
  187. data/rdoc/doc/NEAT/Evaluator_html.html +556 -0
  188. data/rdoc/doc/NEAT/Evolver/CritterOp_html.html +690 -0
  189. data/rdoc/doc/NEAT/Evolver_html.html +677 -0
  190. data/rdoc/doc/NEAT/Expressor_html.html +468 -0
  191. data/rdoc/doc/NEAT/Graph/DependencyResolver_html.html +598 -0
  192. data/rdoc/doc/NEAT/Graph/GraphException_html.html +299 -0
  193. data/rdoc/doc/NEAT/Graph_html.html +527 -0
  194. data/rdoc/doc/NEAT/NeatException_html.html +299 -0
  195. data/rdoc/doc/NEAT/NeatOb_html.html +671 -0
  196. data/rdoc/doc/NEAT/Neuron_html.html +1095 -0
  197. data/rdoc/doc/NEAT/Operator_html.html +337 -0
  198. data/rdoc/doc/NEAT/Population_html.html +1795 -0
  199. data/rdoc/doc/NEAT/Trait_html.html +344 -0
  200. data/rdoc/doc/NEAT_html.html +736 -0
  201. data/rdoc/doc/_index_html.html +559 -0
  202. data/rdoc/doc/class_list_html.html +369 -0
  203. data/rdoc/doc/css/common_css.html +188 -0
  204. data/rdoc/doc/css/full_list_css.html +243 -0
  205. data/rdoc/doc/css/style_css.html +530 -0
  206. data/rdoc/doc/file_list_html.html +240 -0
  207. data/rdoc/doc/frames_html.html +217 -0
  208. data/rdoc/doc/index_html.html +559 -0
  209. data/rdoc/doc/js/app_js.html +423 -0
  210. data/rdoc/doc/js/full_list_js.html +372 -0
  211. data/rdoc/doc/js/jquery_js.html +1536 -0
  212. data/rdoc/doc/method_list_html.html +1375 -0
  213. data/rdoc/doc/top-level-namespace_html.html +317 -0
  214. data/rdoc/fonts/Lato-Light.ttf +0 -0
  215. data/rdoc/fonts/Lato-LightItalic.ttf +0 -0
  216. data/rdoc/fonts/Lato-Regular.ttf +0 -0
  217. data/rdoc/fonts/Lato-RegularItalic.ttf +0 -0
  218. data/rdoc/fonts/SourceCodePro-Bold.ttf +0 -0
  219. data/rdoc/fonts/SourceCodePro-Regular.ttf +0 -0
  220. data/rdoc/fonts.css +167 -0
  221. data/rdoc/images/add.png +0 -0
  222. data/rdoc/images/arrow_up.png +0 -0
  223. data/rdoc/images/brick.png +0 -0
  224. data/rdoc/images/brick_link.png +0 -0
  225. data/rdoc/images/bug.png +0 -0
  226. data/rdoc/images/bullet_black.png +0 -0
  227. data/rdoc/images/bullet_toggle_minus.png +0 -0
  228. data/rdoc/images/bullet_toggle_plus.png +0 -0
  229. data/rdoc/images/date.png +0 -0
  230. data/rdoc/images/delete.png +0 -0
  231. data/rdoc/images/find.png +0 -0
  232. data/rdoc/images/loadingAnimation.gif +0 -0
  233. data/rdoc/images/macFFBgHack.png +0 -0
  234. data/rdoc/images/package.png +0 -0
  235. data/rdoc/images/page_green.png +0 -0
  236. data/rdoc/images/page_white_text.png +0 -0
  237. data/rdoc/images/page_white_width.png +0 -0
  238. data/rdoc/images/plugin.png +0 -0
  239. data/rdoc/images/ruby.png +0 -0
  240. data/rdoc/images/tag_blue.png +0 -0
  241. data/rdoc/images/tag_green.png +0 -0
  242. data/rdoc/images/transparent.png +0 -0
  243. data/rdoc/images/wrench.png +0 -0
  244. data/rdoc/images/wrench_orange.png +0 -0
  245. data/rdoc/images/zoom.png +0 -0
  246. data/rdoc/index.html +282 -0
  247. data/rdoc/js/darkfish.js +140 -0
  248. data/rdoc/js/jquery.js +18 -0
  249. data/rdoc/js/navigation.js +142 -0
  250. data/rdoc/js/search.js +109 -0
  251. data/rdoc/js/search_index.js +1 -0
  252. data/rdoc/js/searcher.js +228 -0
  253. data/rdoc/rdoc.css +580 -0
  254. data/rdoc/rubyneat_gemspec.html +387 -0
  255. data/rdoc/table_of_contents.html +2502 -0
  256. data/rdoc/xordebug_log.html +170598 -0
  257. data/rdoc/xorsin_log.html +22569 -0
  258. data/rubyneat.gemspec +347 -0
  259. data/rubyneat.gemspec.orig +375 -0
  260. data/spec/lib/rubyneat/rubyneat_spec.rb +132 -0
  261. metadata +555 -0
@@ -0,0 +1,227 @@
1
+ require 'rubyneat/rubyneat'
2
+
3
+ module NEAT
4
+ #= Population of NEAT Critters.
5
+ # The Population
6
+ # In ourselves we have the pool of neurons the critters all use.
7
+ # the pool of neurons are indirects, of course, as during phenotype
8
+ # expression, all the phenotypes shall be created individually.
9
+ #
10
+ class Population < NeatOb
11
+ # Ordered list or hash of input neuron classes
12
+ # (all critters generated here shall have this)
13
+ attr_accessor :input_neurons
14
+
15
+ # List of possible neuron classes for hidden neurons.
16
+ attr_accessor :hidden_neurons
17
+
18
+ # Ordered list or hash of output neuron classes
19
+ # (all critters generated here shall have this)
20
+ attr_accessor :output_neurons
21
+
22
+ attr_accessor :traits
23
+
24
+ # list of critter in this population
25
+ attr_accessor :critters
26
+
27
+ # Overall population fitness and novelty
28
+ attr_reader :fitness, :novelty
29
+
30
+ # Hash list of species lists
31
+ attr_reader :species
32
+
33
+ # in a deep dive, exclude the following from replication.
34
+ exclude :input_neurons, :output_neurons
35
+
36
+ # Create initial (ramdom) population of critters
37
+ def initialize(c, &block)
38
+ super
39
+ @input_neurons = c.neural_inputs.clone
40
+ @output_neurons = c.neural_outputs.clone
41
+ @hidden_neurons = unless c.neural_hidden.nil?
42
+ c.neural_hidden
43
+ else
44
+ c.neuron_catalog.keep_if {|n| not n.input?}
45
+ end
46
+ @critters = (0 ... c.parms.start_population_size || c.parms.population_size).map do
47
+ Critter.new(self)
48
+ end
49
+ block.(self) unless block.nil?
50
+ end
51
+
52
+ # Make sure all critters are reset and prepared for
53
+ # recurrent network evaluation.
54
+ def initialize_for_recurrence!
55
+ @critters.each {|crit| crit.initialize_neurons!}
56
+ end
57
+
58
+ # Mutate the genes and neurons.
59
+ def mutate!
60
+ @controller.evolver.mutate! self
61
+ end
62
+
63
+ # Express the entire population.
64
+ def express!
65
+ @critters.each { |critter| critter.express! }
66
+ end
67
+
68
+ # Called for each sequence.
69
+ def evaluate!
70
+ @critters.each { |critter| critter.evaluate! }
71
+ end
72
+
73
+ # Alalyze evaluation results.
74
+ def analyze!
75
+ @critters.each { |critter| @controller.evaluator.analyze_for_fitness! critter }
76
+ end
77
+
78
+ # Call this after evaluation.
79
+ # Returns a newly-evolved population.
80
+ def evolve
81
+ @controller.evolver.evolve self
82
+ end
83
+
84
+ # Group critters into species
85
+ # Note that the @species objects
86
+ # have useful singleton methods:
87
+ #* @species.member? -- checks all of the lists for membership, not just the hash
88
+ #* @species[crit].fitness -- fitness of the entire species
89
+ def speciate!
90
+ # We blow away existing species and create our own member? function
91
+ @species = {} # lists keyed by representative critter
92
+ def @species.member?(crit)
93
+ super.member?(crit) or self.map{|k, li| li.member? crit}.reduce{|t1, t2| t1 or t2 }
94
+ end
95
+
96
+ def @species.evaluate!
97
+ self.each do |k, sp|
98
+ sp.fitness = sp.map{|crit| crit.fitness}.reduce{|a,b| a+b} / sp.size
99
+ end
100
+ end
101
+
102
+ def @species.compactify!(parm)
103
+ mutt = self[:mutt] = self.map { |k, splist| [k, splist]}.reject {|k, splist|
104
+ splist.size >= parm.smallest_species
105
+ }.map { |k, splist|
106
+ self.delete k
107
+ splist
108
+ }.flatten
109
+
110
+ # FIXME this code is not dry!!!!
111
+ def mutt.fitness=(fit)
112
+ @fitness = fit
113
+ end
114
+
115
+ def mutt.fitness
116
+ @fitness
117
+ end
118
+
119
+ self.delete :mutt if self[:mutt].empty?
120
+ end
121
+
122
+ # Some convience parms
123
+ parm = @controller.parms
124
+
125
+ # And so now we iterate...
126
+ @critters.each do |crit|
127
+ wearein = false
128
+ @species.each do |ck, list|
129
+ delta = crit.compare(ck)
130
+ #log.debug { "delta for #{crit} and #{ck} is #{delta}" }
131
+ if delta < parm.compatibility_threshold
132
+ list << crit
133
+ wearein = true
134
+ break
135
+ end
136
+ end
137
+
138
+ # New species?
139
+ unless wearein
140
+ @species[crit] = species = [crit]
141
+ def species.fitness=(fit)
142
+ @fitness = fit
143
+ end
144
+ def species.fitness
145
+ @fitness
146
+ end
147
+ end
148
+ end
149
+
150
+ # Compactify the species if less than smallest_species
151
+ @species.compactify! parm
152
+
153
+ # And now we evaluate all species for fitness...
154
+ @species.evaluate!
155
+
156
+ # Dump for debugging reasons
157
+ @species.each do |k, sp|
158
+ log.debug ">> Species #{k} has #{sp.size} members with a #{sp.fitness} fitness"
159
+ end
160
+
161
+ end
162
+
163
+ #== Generate a report on the state of this population.
164
+ #
165
+ def report
166
+ {
167
+ fitness: report_fitness,
168
+ fitness_species: report_fitness_species,
169
+ best_critter: report_best_fit,
170
+ worst_critter: report_worst_fit,
171
+ }
172
+ end
173
+
174
+ # The "best critter" is the critter with the lowest (closet to zero)
175
+ # fitness rating.
176
+ def best_critter
177
+ unless @controller.compare_func.nil?
178
+ @critters.min {|a, b| @controller.compare_func.(a.fitness, b.fitness) }
179
+ else
180
+ @critters.min {|a, b| a.fitness <=> b.fitness}
181
+ end
182
+ end
183
+
184
+ # The "worst critter" is the critter with the highest (away from zero)
185
+ # fitness rating.
186
+ def worst_critter
187
+ unless @controller.compare_func.nil?
188
+ @critters.max {|a, b| @controller.compare_func.(a.fitness, b.fitness) }
189
+ else
190
+ @critters.max {|a, b| a.fitness <=> b.fitness}
191
+ end
192
+ end
193
+
194
+ def dump_s
195
+ to_s + "\npopulation:\n" + @critters.map{|crit| crit.dump_s }.join("\n")
196
+ end
197
+
198
+ protected
199
+ # report on many fitness metrics
200
+ def report_fitness
201
+ {
202
+ overall: @critters.map{|critter| critter.fitness}.reduce{|m, f| m + f} / @critters.size,
203
+ best: best_critter.fitness,
204
+ worst: worst_critter.fitness,
205
+ }
206
+ end
207
+
208
+ # report on the best and worst species
209
+ def report_fitness_species
210
+ {
211
+ best: nil,
212
+ worst: nil,
213
+ }
214
+ end
215
+
216
+ # Find the best fit critter
217
+ def report_best_fit
218
+ best_critter.phenotype.code
219
+ end
220
+
221
+ # Find the worst fit critter
222
+ def report_worst_fit
223
+ worst_critter.phenotype.code
224
+ end
225
+
226
+ end
227
+ end
@@ -0,0 +1,429 @@
1
+ require 'distribution'
2
+ require 'yaml'
3
+ require 'logger'
4
+ require 'awesome_print'
5
+ require 'deep_dive'
6
+
7
+ =begin rdoc
8
+ = RubyNEAT -- a Ruby Implementation of the NeuroEvolution by Augmented Topologies.
9
+
10
+ The RubyNEAT system incorporates the basis of the NEAT alorithm. Flexibility
11
+ is the key here, allowing RubyNEAT to be leverage in a varitety of applications.
12
+
13
+ === Requirements
14
+ We make no effort to support Ruby versions less than 1.9.2. I know this will
15
+ be a problem to some, but you are strongly urgerd to upgrade.
16
+
17
+ =end
18
+
19
+ $log = Logger.new(STDOUT)
20
+ $log.level = Logger::INFO
21
+ AwesomePrint.defaults = { plain: true }
22
+
23
+ =begin rdoc
24
+ = NEAT -- Module for RubyNEAT.
25
+
26
+ == Synopsis
27
+ We have a Population of Critters, and each Critter
28
+ represents a network of Neurons and a connection list specifying
29
+ how those Neurons are connected.
30
+
31
+ Each Neuron has an inplicit genotype and phenotype component. Neurons,
32
+ from the Ruby persoective, contain their own code to produce their own
33
+ phenotypes.
34
+
35
+ There are input Neurons and output Neurons. The input Neurons are special, as
36
+ they do not contain any input from other nodes, but serve as interfaces
37
+ from the "real world". Thier range of inputs are open, and it shall be up to
38
+ the input Neuron's phenotype generators to condition those inputs, if need be,
39
+ to someething more suiable for the neural network.
40
+
41
+ == Issues
42
+ === Multicore / Cloud Computing
43
+ Some thought needs to be given to how to make this anenable to multiple
44
+ processes so that we can leverage the power of multicore systems as well
45
+ as multiple computers in the Cloud, etc.
46
+
47
+ Our initial inclination is to put all of that functionality in the Conroller.
48
+ =end
49
+ module NEAT
50
+ @rng_count = 0
51
+ @rng_names = %w{aaa bee cex dee flo kis lee mor cie lou gir sex quo sam lac hin pee
52
+ cur set sew flat nac zac pae por lie lox pox nez fez wib poo sho
53
+ nuz tux que bsh shi her him can muk fuk kit kat uno dos ant mic
54
+ aa be nz oo py tt my of ze mu pi zz qu fl tr as sd fg gh hj bc
55
+ lion tame monk busy honk tape slap zonk funk tear flip shop soap
56
+ quay mony stir moot shoo slim fate trat beep kook love hate
57
+ mire hair lips funk open shut case lace joop lute doze fuzz
58
+ mean nice soil vote kick apes snak huge sine pine gray nook fool
59
+ woot hail smel tell jell suut gage phat pinoy spain rey bloke zit}
60
+ def self.random_name_generator
61
+ (1..3).map {
62
+ @rng_names[rand @rng_names.size]
63
+ }.push(@rng_count += 1).join('_').to_sym
64
+ end
65
+
66
+ # Name of the stimulus method in NEAT::Critter::Phenotype to use
67
+ # for the singleton method expression of the critter.
68
+ STIMULUS = :stimulate
69
+
70
+ # Mixin for new innovation numbers.
71
+ def self.new_innovation; @controller.new_innovation; end
72
+
73
+ # Mixin for the gaussian object.
74
+ def self.gaussian ; @controller.gaussian; end
75
+
76
+ # PrettyPrint to log.debug
77
+ def self.dpp ob
78
+ #$log.ap ob
79
+ end
80
+
81
+ # Basis of all NEAT objects
82
+ class NeatOb
83
+ include DeepDive
84
+ exclude :controller, :name
85
+
86
+ # Designation of this particular object instance
87
+ attr_reader :name
88
+
89
+ # Who's your daddy?
90
+ attr_reader :controller
91
+
92
+ def log ; $log ; end
93
+ def self.log ; $log; end
94
+
95
+ # Initializer for all NEAT objects. Requires that
96
+ # the controller object is specified for all classes
97
+ # with the exception of the Controller itself or the
98
+ # Controller's NeatSettings.
99
+ def initialize(controller = nil, name = nil)
100
+ @name = unless name.nil?
101
+ name.to_sym
102
+ else
103
+ NEAT::random_name_generator
104
+ end
105
+ unless controller.nil?
106
+ @controller = controller
107
+ else
108
+ raise NeatException.new "Controller Needed!" unless self.is_a?(Controller) or self.is_a?(Controller::NeatSettings)
109
+ @controller = self unless self.is_a? Controller::NeatSettings
110
+ end
111
+ end
112
+
113
+ def to_s
114
+ "%s<%s>" % [self.class, self.name]
115
+ end
116
+ end
117
+
118
+ class NeatException < Exception
119
+ end
120
+
121
+ #= Base class of operators in RubyNEAT,
122
+ # Such as Evolver, etc.
123
+ class Operator < NeatOb
124
+ end
125
+
126
+ #= Traits
127
+ # A Trait is a group of parameters that can be expressed
128
+ # as a group more than one time. Traits save a genetic
129
+ # algorithm from having to search vast parameter landscapes
130
+ # on every node. Instead, each node can simply point to a trait
131
+ # and those traits can evolve on their own. (Taken from the C version of NEAT)
132
+ #
133
+ # Since we wish to allow for different classes of Neurons, this trait idea is
134
+ # super, since all we need to do is have a different trait species for the
135
+ # different node types.
136
+ class Trait < NeatOb
137
+ end
138
+
139
+ require 'rubyneat/critter'
140
+ require 'rubyneat/neuron'
141
+ require 'rubyneat/population'
142
+ require 'rubyneat/evolver'
143
+ require 'rubyneat/expressor'
144
+ require 'rubyneat/evaluator'
145
+
146
+ #= Controller for all operations of RubyNEAT
147
+ # This object contains all the specifications and details for
148
+ # evolving and evaluation of the RubyNEAT system. It is
149
+ # a type of "World", if you will, for the entire enterprise.
150
+ #
151
+ # Your application shall only have one Controller.
152
+ class Controller < NeatOb
153
+ # global innovation number
154
+ attr_reader :glob_innov_num
155
+
156
+ # current sequence number being evaluated
157
+ attr_reader :seq_num
158
+
159
+ # Current generation count
160
+ attr_reader :generation_num
161
+
162
+ # catalog of neurons classes to use { weight => nclass, ... }
163
+ attr_accessor :neuron_catalog
164
+
165
+ # Class map of named input and output neurons (each critter will have
166
+ # instantiations of these) name: InputNeuralClass (usually InputNeuron)
167
+ attr_accessor :neural_inputs, :neural_outputs, :neural_hidden
168
+
169
+ # Parameters for evolution (NeatParameters)
170
+ attr_accessor :parms
171
+
172
+ # population object and class specification
173
+ attr_reader :population, :population_history, :population_class
174
+
175
+ attr_accessor :expressor, :expressor_class
176
+ attr_accessor :evaluator, :evaluator_class
177
+ attr_accessor :evolver, :evolver_class
178
+
179
+ # Global verbosity level:
180
+ ## 1 - normal (the default)
181
+ ## 2 - really verbose
182
+ ## 3 - maximally verbose
183
+ # Use in conjunction with log.debug
184
+ attr_accessor :verbosity
185
+
186
+ # Query function that Critters shall call.
187
+ attr_accessor :query_func
188
+
189
+ # Fitness function that Critters shall be rated on.
190
+ attr_accessor :fitness_func
191
+
192
+ # Recurrence function that Critters will yield to.
193
+ attr_accessor :recurrence_func
194
+
195
+ # Compare function for fitness
196
+ # Cost function for integrating in the cost to the fitness scalar.
197
+ attr_accessor :compare_func, :cost_func, :stop_on_fit_func
198
+
199
+ # End run function to call at the end of each generational run
200
+ # Also report_hook to dump reports for the user, etc.
201
+ attr_accessor :end_run_func, :report_hook
202
+
203
+ # Logger object for all of RubyNEAT
204
+ attr_reader :log
205
+
206
+ # Various parameters affecting evolution.
207
+ # Based somewhat on the C version of NEAT.
208
+ # TODO not all of these parameters are implemented yet!!!
209
+ class NeatSettings < NeatOb
210
+ ## RubyNEAT specific
211
+
212
+ # Set to true to returned named parameters as hashes to the fitness function
213
+ # (the default is to do ordered arrays)
214
+ attr_accessor :hash_on_fitness
215
+
216
+ ## based on the C version of NEAT
217
+ attr_accessor :age_significance
218
+ attr_accessor :babies_stolen
219
+
220
+ # Species compatability threshold
221
+ attr_accessor :compatibility_threshold
222
+
223
+ # Speciation coffficient
224
+ attr_accessor :disjoint_coefficient, :excess_coefficient, :weight_coefficient
225
+
226
+ # Max target number of species (will result in the compatability_coeifficient
227
+ # being adjusted automatically
228
+ attr_accessor :max_species
229
+
230
+ # Species Peality age for not making progress
231
+ attr_accessor :dropoff_age
232
+
233
+ # Species smallest population allowed (coalse smaller species into one)
234
+ attr_accessor :smallest_species
235
+
236
+ # Ratio of mating are actually interspecies
237
+ attr_accessor :interspecies_mate_rate
238
+
239
+ attr_accessor :linktrait_mutation_sig
240
+ attr_accessor :mate_multipoint_avg_prob
241
+ attr_accessor :mate_multipoint_prob
242
+ attr_accessor :mate_only_prob
243
+ attr_accessor :mate_singlepoint_prob
244
+
245
+ # Maximum number of generations to run, if given.
246
+ attr_accessor :max_generations
247
+
248
+ # Maximun number of populations to maintain in the history buffer.
249
+ attr_accessor :max_population_history
250
+
251
+ attr_accessor :mutate_add_gene_prob
252
+ attr_accessor :mutate_add_neuron_prob
253
+
254
+ attr_accessor :mutate_gene_disable_prob
255
+ attr_accessor :mutate_gene_reenable_prob
256
+
257
+ attr_accessor :mutate_gene_trait_prob
258
+
259
+ # For gene weights perturbations and changes (complete overwrites)
260
+ attr_accessor :mutate_perturb_gene_weights_prob,
261
+ :mutate_perturb_gene_weights_sd,
262
+ :mutate_change_gene_weights_prob,
263
+ :mutate_change_gene_weights_sd
264
+
265
+ attr_accessor :mutate_neuron_trait_prob
266
+ attr_accessor :mutate_only_prob
267
+ attr_accessor :mutate_random_trait_prob
268
+ attr_accessor :mutate_toggle_enable_prob
269
+ attr_accessor :mutdiff_coefficient
270
+ attr_accessor :newlink_tries
271
+ attr_accessor :neuron_trait_mut_sig
272
+
273
+ # fitness costs, if given, use in the computation of fitness
274
+ # AFTER the overall fitness for the applied stimuli have been
275
+ # caclulated.
276
+ attr_accessor :fitness_cost_per_neuron
277
+ attr_accessor :fitness_cost_per_gene
278
+
279
+ # If set, will start off at the specified size and
280
+ # grow to the bigger population size
281
+ attr_accessor :start_population_size, :population_size
282
+
283
+ attr_accessor :start_sequence_at, :end_sequence_at
284
+
285
+ attr_accessor :print_every
286
+ attr_accessor :recur_only_prob
287
+ attr_accessor :recur_prob
288
+
289
+ # factor (0 to 1) of the top percentage of the species that's
290
+ # allowed to mate.
291
+ attr_accessor :survival_threshold
292
+ attr_accessor :survival_mininum_per_species
293
+
294
+ attr_accessor :trait_mutation_power
295
+ attr_accessor :trait_param_mut_prob
296
+ attr_accessor :weigh_mut_power
297
+
298
+ # Enable FS-NEAT
299
+ attr_accessor :feature_selection_switch
300
+
301
+ # Enable HyperNEAT. This will result in the critters
302
+ # being interpreted as CPPNs for substrate weights. Additional
303
+ # setup will be necessary.
304
+ attr_accessor :hyper_switch
305
+
306
+ # Enable Evolved Substrate HyperNEAT. Meaningless unless
307
+ # hyper_switch is also enabled.
308
+ attr_accessor :evolved_substrate_switch
309
+
310
+ # Enable RT-NEAT, for gradual evolution suitable for
311
+ # games and other human-interactive systems.
312
+ attr_accessor :real_time_switch
313
+
314
+ # If true, allow for recurrent networks.
315
+ attr_accessor :recurrency_switch
316
+
317
+ # Set up defaults for mandatory entries.
318
+ def initialize
319
+ super
320
+ @start_sequence_at = 0
321
+ @end_sequence_at = 100
322
+ @max_generations = 1000
323
+
324
+ # Default operators
325
+ @evaluator = Evaluator.new self
326
+ @expressor = Expressor.new self
327
+ @evolver = Evolver.new self
328
+ end
329
+ end
330
+
331
+ #- neural_inputs -- array of input classes
332
+ #- neural_outputs -- array of output classes
333
+ #- parameters -- NeatParameters object, or a path to a YAML file to create this.
334
+ def initialize(neural_inputs: nil,
335
+ neural_outputs: nil,
336
+ neural_hidden: nil,
337
+ parameters: NeatSettings.new,
338
+ &block)
339
+ super(self)
340
+ @verbosity = 1
341
+ @glob_innov_num = 0
342
+ @gaussian = Distribution::Normal.rng
343
+ @population_history = []
344
+ @evolver = Evolver.new self
345
+ @expressor = Expressor.new self
346
+
347
+ @neuron_catalog = Neuron::neuron_types.clone
348
+ @neural_inputs = neural_inputs
349
+ @neural_outputs = neural_outputs
350
+ @neural_hidden = neural_hidden
351
+
352
+ # Default classes for population and operators, etc.
353
+ @population_class = NEAT::Population
354
+ @evaluator_class = NEAT::Evaluator
355
+ @expressor_class = NEAT::Expressor
356
+ @evolver_class = NEAT::Evolver
357
+
358
+ # Handle the parameters parameter. :-)
359
+ @parms = unless parameters.kind_of? String
360
+ parameters
361
+ else # load it from a file
362
+ open(parameters, 'r') { |fd| YAML::load fd.read }
363
+ end
364
+ block.(self) unless block.nil?
365
+ end
366
+
367
+ def new_innovation ; @glob_innov_num += 1; end
368
+ def gaussian ; @gaussian.() ; end
369
+
370
+ # Run this evolution.
371
+ def run
372
+ pre_run_initialize
373
+ (1..@parms.max_generations).each do |gen_number|
374
+ @generation_num = gen_number
375
+ @population_history << unless @population.nil?
376
+ @population
377
+ else
378
+ @population = @population_class.new(self)
379
+ end
380
+ @population_history.shift unless @population_history.size <= @parms.max_population_history
381
+ @population.mutate!
382
+ @population.express!
383
+
384
+ ## Evaluate population
385
+ @evaluator.ready_for_evaluation @population
386
+ (@parms.start_sequence_at .. @parms.end_sequence_at).each do |snum|
387
+ @seq_num = snum
388
+ @population.evaluate!
389
+ end
390
+
391
+ @population.analyze!
392
+ @population.speciate!
393
+
394
+ $log.debug @population.dump_s unless @verbosity < 3
395
+
396
+ new_pop = @population.evolve
397
+
398
+ ## Report hook for evaluation
399
+ @report_hook.(@population.report) unless @report_hook.nil?
400
+
401
+ ## Exit if fitness criteria is reached
402
+ #FIXME handle this exit condition better!!!!!
403
+ exit if @stop_on_fit_func.(@population.report[:fitness], self) unless @stop_on_fit_func.nil?
404
+
405
+ ## Evolve population
406
+ @population = new_pop
407
+
408
+ ## Finish up this run
409
+ @end_run_func.(self) unless @end_run_func.nil?
410
+ end
411
+ end
412
+
413
+ private
414
+ # We must set up the objects we need prior to the run, if not set.
415
+ def pre_run_initialize
416
+ @evaluator = @evaluator_class.new(self) if @evaluator.nil?
417
+ @evolver = @evolver_class.new(self) if @evolver.nil?
418
+ end
419
+ end
420
+
421
+ @controller = Controller.new
422
+ def self.controller ; @controller ; end
423
+ def self.controller=(controller) ; @controller = controller ; end
424
+ def self.create_controller(*parms); @controller = Controller.new(*parms); end
425
+ end
426
+
427
+ # We put all the internal requires at the end to avoid conflicts.
428
+ require 'rubyneat/neuron'
429
+ require 'rubyneat/population'
data/lib/rubyneat.rb ADDED
@@ -0,0 +1,8 @@
1
+ =begin rdoc
2
+ =RubyNEAT ()Neural Evolution via Augmented Topologies)
3
+ =end
4
+
5
+ require 'rubyneat/rubyneat'
6
+ require 'rubyneat/graph'
7
+ require 'rubyneat/dsl'
8
+ require 'set'