class NEAT::Critter

Critters for NEAT

The Critter class comprises a Genotype and a Phenotype.
The Genotype comprises Genes and Neurons.

Critter Reporting

The reporting functionality for critters are represented here,
since this is only tangenial to the actual functionality of
the critters themselves.

Attributes

fitness[RW]

Ratings assigned by Evaluator

genotype[RW]
novelty[RW]

Ratings assigned by Evaluator

phenotype[RW]
population[R]

Public Class Methods

new(pop, mating = false, &block) click to toggle source

Critter construction. We construct the genotype. The phenotype will be constructed by the Expressor operator.

Calls superclass method
# File lib/rubyneat/critter.rb, line 20
def initialize(pop, mating = false, &block)
  super pop.controller
  @population = pop
  @genotype = Genotype.new(self, mating)
  block.(self) unless block.nil?
end

Public Instance Methods

compare(oc) click to toggle source

Compare ourselves against another critter for compability.

The function to be used here is:

distance = c1*E + c2*D + c3*W

Where:

E, D - The number of excess and disjoint genes repesctively.
N - The number of genes in the largest genome.
W - The sum of absolute weight differences.

This is a variation of the formulation suggested by the Stanley paper, which normalizes the E and D terms by N.

# File lib/rubyneat/critter.rb, line 333
def compare(oc)
  c1 = @controller.parms.excess_coefficient
  c2 = @controller.parms.disjoint_coefficient
  c3 = @controller.parms.weight_coefficient
  e = excess(oc)
  d = disjoint(oc)
  w = weight_diff(oc)
  return c1 * e + c2 * d + c3 * w
end
dump_s() click to toggle source

Critter print

# File lib/rubyneat/critter.rb, line 344
def dump_s
  to_s + @genotype.dump_s + "\n" + @phenotype.to_s + "\n"
end
evaluate!() click to toggle source

A single evaluation step. Evaluate and generate fitness, novelty, etc. Returns the result.

# File lib/rubyneat/critter.rb, line 50
def evaluate!
  @controller.evaluator.evaluate! self
end
express!() click to toggle source

Exoress this critter using the Expressor plugin.

# File lib/rubyneat/critter.rb, line 36
def express!
  @controller.expressor.express! self
end
initialize_neurons!() click to toggle source

This initializes neurons in preparation for recurrence. Note that the Critter should already have expressed its genotype before this is called.

# File lib/rubyneat/critter.rb, line 43
def initialize_neurons!
  @phenotype.initialize_neurons
end
ready_for_expression!() click to toggle source

Get the Critter ready for the Expressor to express the geneotype.

# File lib/rubyneat/critter.rb, line 29
def ready_for_expression!
  @genotype.wire!
  @phenotype = NEAT::Critter::Phenotype[self]
  @phenotype
end
report() click to toggle source
# File lib/rubyneat/reporting.rb, line 105
def report
  {
      genotype: report_genotype,
      phenotype: report_phenotype,
      neuron_types: report_neuron_types
  }
end
report_genotype() click to toggle source
# File lib/rubyneat/reporting.rb, line 97
def report_genotype
  genotype.genes.map{|innov, gene| {in: gene.in_neuron, out: gene.out_neuron, innov: innov}}
end
report_neuron_types() click to toggle source
# File lib/rubyneat/reporting.rb, line 89
def report_neuron_types
  {
      input:  population.input_neurons.map {|n| n.name},
      output: population.output_neurons.map{|n| n.name},
      hidden: population.hidden_neurons.map{|n| n.name}
  }
end
report_phenotype() click to toggle source
# File lib/rubyneat/reporting.rb, line 101
def report_phenotype
  phenotype.code
end

Private Instance Methods

disjoint(oc) click to toggle source

Return the count of disjoint genes

# File lib/rubyneat/critter.rb, line 355
def disjoint(oc)
  a = @genotype.genes.keys
  b = oc.genotype.genes.keys
  (a - b).size + (b - a).size - excess(oc)
end
excess(oc) click to toggle source

Return a count of excesses.

# File lib/rubyneat/critter.rb, line 350
def excess(oc)
  (@genotype.genes.size - oc.genotype.genes.size).abs
end
weight_diff(oc) click to toggle source
# File lib/rubyneat/critter.rb, line 362
def weight_diff(oc)
  ag = @genotype.genes
  bg = oc.genotype.genes
  matches = ag.keys & bg.keys
  unless matches.empty?
    matches.map{|i| (ag[i].weight - bg[i].weight).abs}.reduce{|w, ws| w + ws} / matches.size
  else
    0
  end
end