Class: NEAT::Critter::Genotype
Overview
Genotype part of the Critter
List of connections, basically.
Also, basic phentypic expression (which may be overriden by the expressor)
Notes
Currently, all lists of neurons and genes are Hashes. The neurons are indexed by their own names, and the genes are indexed by their innovation numbers.
Defined Under Namespace
Classes: Gene
Instance Attribute Summary (collapse)
-
- (Object) critter
Critter to which we belong.
-
- (Object) dangling_neurons
(also: #dangling_neurons?)
This will be set to true if there are dangling neurons.
-
- (Object) genes
Genes keyed by innovation numbers.
-
- (Object) neural_gene_map
readonly
Map neurons to the genes that marks them as output { oneu_name => [ gene_1, gene_2,… gene_n], …} Just take the in_neuron name and the weight to do the call to that neuron function with the appropriate weights.
-
- (Object) neural_inputs
readonly
Instantiations of neural inputs and outputs.
-
- (Object) neural_outputs
readonly
Instantiations of neural inputs and outputs.
-
- (Object) neurons
List of neurons hashed by name.
Attributes inherited from NeatOb
Instance Method Summary (collapse)
-
- (Object) add_genes(*genes)
Genes added here MUST correspond to pre-existing neurons.
-
- (Object) add_neurons(*neus)
Add new neurons to the fold.
- - (Object) dump_s
-
- (Object) fitness_cost
Calculate the cost of this genotype.
-
- (Object) forget!
Make the neurons forget their wiring.
-
- (Genotype) initialize(critter, mating = false, &block)
constructor
A new instance of Genotype.
-
- (Object) innervate!(*hneus)
We take the neural hashes (presumably from other neurons), and innervate them.
-
- (Object) neucleate(clean: true, &block)
We add genes given here to the genome.
-
- (Object) nuke_redundancies!
Remove any redundancies in the genome, any genes refering to the same two neurons.
-
- (Object) prune!
Go through the list of neurons and drop any neurons not referenced by the genes.
-
- (Object) wire!
Wire up the neurons based on the genes.
Methods inherited from NeatOb
Constructor Details
- (Genotype) initialize(critter, mating = false, &block)
Returns a new instance of Genotype
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rubyneat/critter.rb', line 88 def initialize(critter, mating = false, &block) super critter.controller @critter = critter # Initialize basic structures @genes = nil @neural_inputs = Hash[@critter.population.input_neurons.map { |sym, ineu| [sym, ineu.new(@controller, sym)] }] @neural_outputs = Hash[@critter.population.output_neurons.map { |sym, ineu| [sym, ineu.new(@controller, sym)] }] @neurons = @neural_inputs.clone # this must be a shallow clone! @neurons.merge! @neural_outputs @controller.evolver.gen_initial_genes!(self) unless mating block.(self) unless block.nil? end |
Instance Attribute Details
- (Object) critter
Critter to which we belong
67 68 69 |
# File 'lib/rubyneat/critter.rb', line 67 def critter @critter end |
- (Object) dangling_neurons Also known as: dangling_neurons?
This will be set to true if there are dangling neurons.
79 80 81 |
# File 'lib/rubyneat/critter.rb', line 79 def dangling_neurons @dangling_neurons end |
- (Object) genes
Genes keyed by innovation numbers
70 71 72 |
# File 'lib/rubyneat/critter.rb', line 70 def genes @genes end |
- (Object) neural_gene_map (readonly)
Map neurons to the genes that marks them as output { oneu_name => [ gene_1, gene_2,… gene_n], …} Just take the in_neuron name and the weight to do the call to that neuron function with the appropriate weights
86 87 88 |
# File 'lib/rubyneat/critter.rb', line 86 def neural_gene_map @neural_gene_map end |
- (Object) neural_inputs (readonly)
Instantiations of neural inputs and outputs
76 77 78 |
# File 'lib/rubyneat/critter.rb', line 76 def neural_inputs @neural_inputs end |
- (Object) neural_outputs (readonly)
Instantiations of neural inputs and outputs
76 77 78 |
# File 'lib/rubyneat/critter.rb', line 76 def neural_outputs @neural_outputs end |
- (Object) neurons
List of neurons hashed by name
73 74 75 |
# File 'lib/rubyneat/critter.rb', line 73 def neurons @neurons end |
Instance Method Details
- (Object) add_genes(*genes)
Genes added here MUST correspond to pre-existing neurons. Be sure to do add_neurons first!!!!
163 164 165 166 167 168 169 |
# File 'lib/rubyneat/critter.rb', line 163 def add_genes(*genes) genes.each do |gene| raise NeatException.new "Neuron #{gene.in_neuron} missing" unless @neurons.member? gene.in_neuron raise NeatException.new "Neuron #{gene.out_neuron} missing" unless @neurons.member? gene.out_neuron @genes[gene.innovation] = gene end end |
- (Object) add_neurons(*neus)
Add new neurons to the fold
155 156 157 158 159 |
# File 'lib/rubyneat/critter.rb', line 155 def add_neurons(*neus) neus.each do |neu| @neurons[neu.name] = neu end end |
- (Object) dump_s
218 219 220 221 222 |
# File 'lib/rubyneat/critter.rb', line 218 def dump_s to_s + "\ngenes:\n" + @genes.map{|k, gene| gene.to_s}.join("\n") + "\nneurons:\n" + @neurons.map{|k, neu| neu.to_s}.join("\n") end |
- (Object) fitness_cost
Calculate the cost of this genotype.
213 214 215 216 |
# File 'lib/rubyneat/critter.rb', line 213 def fitness_cost p = @controller.parms p.fitness_cost_per_neuron * @neurons.size + p.fitness_cost_per_gene * @genes.size end |
- (Object) forget!
Make the neurons forget their wiring.
134 135 136 137 |
# File 'lib/rubyneat/critter.rb', line 134 def forget! @neurons.each { |name, neu| neu.clear_graph } @neural_gene_map = Hash.new {|h, k| h[k] = [] } end |
- (Object) innervate!(*hneus)
We take the neural hashes (presumably from other neurons), and innervate them. We do this in distinctions based on the neuron's names. FIXME We need to randomly select a neuron in the case of clashes.
175 176 177 178 179 |
# File 'lib/rubyneat/critter.rb', line 175 def innervate!(*hneus) hneus.each do |neus| @neurons.merge! neus.dclone end end |
- (Object) neucleate(clean: true, &block)
We add genes given here to the genome. An array of genes is returned from the block and we simply add them in.
113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/rubyneat/critter.rb', line 113 def neucleate(clean: true, &block) genes = Hash[block.(self).map { |g| g.genotype = self [g.innovation, g] }] if clean @genes = genes else @genes.merge! genes end nuke_redundancies! end |
- (Object) nuke_redundancies!
Remove any redundancies in the genome, any genes refering to the same two neurons. Simply choose one and delete the rest. TODO: implement nuke_redundancies!
129 130 131 |
# File 'lib/rubyneat/critter.rb', line 129 def nuke_redundancies! log.warn 'nuke_redundancies! NIY' end |
- (Object) prune!
Go through the list of neurons and drop any neurons not referenced by the genes.
Then go through the genes and drop any that are dangling (i.e. no matching neurons)
Then make sure that @neural_inputs and @neural_outputs reference the actual instance neurons in @neurons
TODO add this circularity check to prune!
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/rubyneat/critter.rb', line 191 def prune! # Take care of dangling neurons neunames = @genes.values.map{|g| [g.in_neuron, g.out_neuron]}.flatten.to_set @neurons = Hash[@neurons.values.reject do |n| not neunames.member? n.name end.map do |n| [n.name, n] end] # Take care of dangling genes @genes = Hash[@genes.values.reject do |gene| not (@neurons.member?(gene.in_neuron) and @neurons.member?(gene.out_neuron)) end.map do |gene| [gene.name, gene] end] # Make sure @neural_inputs and @neural_outputs are consistent @neural_inputs = Hash[@neural_inputs.values.map{|n| [n.name, @neurons[n.name]]}] @neural_outputs = Hash[@neural_outputs.values.map{|n| [n.name, @neurons[n.name]]}] end |
- (Object) wire!
Wire up the neurons based on the genes.
140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/rubyneat/critter.rb', line 140 def wire! forget! @genes.each do |innov, gene| if gene.enabled? raise NeatException.new "Can't find #{gene.out_neuron}" if @neurons[gene.out_neuron].nil? @neurons[gene.out_neuron] << @neurons[gene.in_neuron] @neural_gene_map[gene.out_neuron] << gene unless gene.in_neuron.nil? end end unless @genes.nil? if @genes.nil? $log.error 'Genes Not Present' end end |