Module: NEAT::DSL

Includes:
Math, NEAT, BasicNeuronTypes
Defined in:
lib/rubyneat/dsl.rb

Constant Summary

Constants included from NEAT

STIMULUS

Instance Method Summary collapse

Methods included from NEAT

controller, controller=, create_controller, dpp, gaussian, new_innovation, random_name_generator

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &block) ⇒ Object

This is used to handle the details of our DSL.



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/rubyneat/dsl.rb', line 115

def method_missing(m, *args, &block)
  # we want to catch parameters settings here.
  if NEAT::controller.parms.respond_to? (assignment = (m.to_s + '=').to_sym)
    raise NeatException.new("Missing value(s) to %s" % m) if args.empty?
    val = (args.size == 1) ? args[0] : args
    $log.debug { "Caught method %s with parameter of %s" % [assignment, val] }
    NEAT::controller.parms.send(assignment, val)
  else
    super
  end
end

Instance Method Details

#compare(&block) ⇒ Object

Fitness ordering – given 2 fitness numbers, use the <=> to compare them (or the equivalent, following the +1, 0, -1 that is in the sense of <=>)



63
64
65
# File 'lib/rubyneat/dsl.rb', line 63

def compare(&block)
  NEAT::controller.compare_func_set &block
end

#condition_boolean_vector(vec, sig = :tanh) ⇒ Object

Helper function to Condition boolean vectors to be +1 if true, -1 if false (0 if sigmoid)



82
83
84
# File 'lib/rubyneat/dsl.rb', line 82

def condition_boolean_vector(vec, sig = :tanh)
  vec.map{|b| b ? 1 : ((sig == :sigmoid) ? 0 : -1)}
end

#cost(&block) ⇒ Object

Calculation to add the cost to the fitness, resulting in a fitness that incorporates the cost for sorting purposes.



69
70
71
# File 'lib/rubyneat/dsl.rb', line 69

def cost(&block)
  NEAT::controller.cost_func_set &block
end

#define(name = NEAT.random_name_generator, &block) ⇒ Object

DSL – Define defines the parameters to the controller.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/rubyneat/dsl.rb', line 15

def define(name = NEAT.random_name_generator, &block)
  [
   :inputs,
   :outputs,
   :hidden  # we really don't care about mapping hidden neurons, but we'll ignore them later.
  ].each do |iometh|
    instance_eval %Q[
   def #{iometh}(nodes = nil, &block)
 neui = unless nodes.nil?
          nodes
        else
          block.()
        end
 NEAT::controller.neural_#{iometh} = if neui.kind_of? Hash
                                       neui
                                     else
                                       Hash[neui.map{|n| [NEAT::random_name_generator, n]}]
                                     end
   end]
  end
  block.(NEAT::controller)
end

#evolve(&block) ⇒ Object

DSL – Run evolution



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rubyneat/dsl.rb', line 39

def evolve(&block)
  # Query function is called with the sequence (time evolution) number,
  # and returns an array or hash of parameters that will be given
  # to the input nodes. In the case of hash, the keys in the hash
  # shall correspond to the names given to the input neurons.
  def query(&block)
    NEAT::controller.query_func_add  &block
  end

  def recurrence(&block)
    NEAT::controller.recurrence_func_set &block
  end

  # fitness function calls the block with 2 vectors or two hashes, input and output
  # vectors of the critter being evaluated for fitness, as well as a sequence
  # number that can be used to index what the actual output should be.
  # |vin, vout, seq|
  def fitness(&block)
    NEAT::controller.fitness_func_set &block
  end

  # Fitness ordering -- given 2 fitness numbers,
  # use the <=> to compare them (or the equivalent, following
  # the +1, 0, -1 that is in the sense of <=>)
  def compare(&block)
    NEAT::controller.compare_func_set &block
  end

  # Calculation to add the cost to the fitness, resulting in a fitness
  # that incorporates the cost for sorting purposes.
  def cost(&block)
    NEAT::controller.cost_func_set &block
  end

  # Stop the progression once the fitness criteria is reached
  # for the most fit critter. We allow more than one stop
  # function here.
  def stop_on_fitness(&block)
    NEAT::controller.stop_on_fit_func_add &block
  end

  # Helper function to
  # Condition boolean vectors to be +1 if true, -1 if false (0 if sigmoid)
  def condition_boolean_vector(vec, sig = :tanh)
    vec.map{|b| b ? 1 : ((sig == :sigmoid) ? 0 : -1)}
  end

  # Helper function to
  # Uncondition boolean vectors to be +1 if true, -1 if false
  # FIXME we need a better discrimination function
  def uncondition_boolean_vector(vec, sig = :tanh)
    vec.map{|o| o > ((sig == :sigmoid) ? 0.5 : 0) ? true : false}
  end

  # Helper function to do a simple fitness calculation
  # on the basis of the sum of the square of the diffences
  # of the element in the two vectors.
  def simple_fitness_error(v1, v2)
    sqrt v1.zip(v2).map{|a, b| (a - b) ** 2.0}.reduce{|m, c| m + c}
  end

  block.(NEAT::controller)
end

#fitness(&block) ⇒ Object

fitness function calls the block with 2 vectors or two hashes, input and output vectors of the critter being evaluated for fitness, as well as a sequence number that can be used to index what the actual output should be. |vin, vout, seq|



56
57
58
# File 'lib/rubyneat/dsl.rb', line 56

def fitness(&block)
  NEAT::controller.fitness_func_set &block
end

#query(&block) ⇒ Object

Query function is called with the sequence (time evolution) number, and returns an array or hash of parameters that will be given to the input nodes. In the case of hash, the keys in the hash shall correspond to the names given to the input neurons.



44
45
46
# File 'lib/rubyneat/dsl.rb', line 44

def query(&block)
  NEAT::controller.query_func_add  &block
end

#recurrence(&block) ⇒ Object



48
49
50
# File 'lib/rubyneat/dsl.rb', line 48

def recurrence(&block)
  NEAT::controller.recurrence_func_set &block
end

#report(&block) ⇒ Object

Report on evaluations



104
105
106
# File 'lib/rubyneat/dsl.rb', line 104

def report(&block)
  NEAT::controller.report_add &block
end

#run_engine(&block) ⇒ Object

Run the engine. The block is called on each generation.



109
110
111
112
# File 'lib/rubyneat/dsl.rb', line 109

def run_engine(&block)
  NEAT::controller.end_run_add &block
  NEAT::controller.run
end

#simple_fitness_error(v1, v2) ⇒ Object

Helper function to do a simple fitness calculation on the basis of the sum of the square of the diffences of the element in the two vectors.



96
97
98
# File 'lib/rubyneat/dsl.rb', line 96

def simple_fitness_error(v1, v2)
  sqrt v1.zip(v2).map{|a, b| (a - b) ** 2.0}.reduce{|m, c| m + c}
end

#stop_on_fitness(&block) ⇒ Object

Stop the progression once the fitness criteria is reached for the most fit critter. We allow more than one stop function here.



76
77
78
# File 'lib/rubyneat/dsl.rb', line 76

def stop_on_fitness(&block)
  NEAT::controller.stop_on_fit_func_add &block
end

#uncondition_boolean_vector(vec, sig = :tanh) ⇒ Object

Helper function to Uncondition boolean vectors to be +1 if true, -1 if false FIXME we need a better discrimination function



89
90
91
# File 'lib/rubyneat/dsl.rb', line 89

def uncondition_boolean_vector(vec, sig = :tanh)
  vec.map{|o| o > ((sig == :sigmoid) ? 0.5 : 0) ? true : false}
end