Class: NEAT::Population

Inherits:
NeatOb
  • Object
show all
Defined in:
lib/rubyneat/population.rb

Overview

Population of NEAT Critters.

The Population In ourselves we have the pool of neurons the critters all use. the pool of neurons are indirects, of course, as during phenotype expression, all the phenotypes shall be created individually.

Instance Attribute Summary (collapse)

Attributes inherited from NeatOb

#controller, #name

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods inherited from NeatOb

#log, log, #to_s

Constructor Details

- (Population) initialize(c, &block)

Create initial (ramdom) population of critters



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/rubyneat/population.rb', line 37

def initialize(c, &block)
  super
  @input_neurons = c.neural_inputs.clone
  @output_neurons = c.neural_outputs.clone
  @hidden_neurons = unless c.neural_hidden.nil?
                      c.neural_hidden
                    else
                      c.neuron_catalog.keep_if {|n| not n.input?}
                    end
  @critters = (0 ... c.parms.start_population_size || c.parms.population_size).map do
    Critter.new(self)
  end
  block.(self) unless block.nil?
end

Instance Attribute Details

- (Object) critters

list of critter in this population



25
26
27
# File 'lib/rubyneat/population.rb', line 25

def critters
  @critters
end

- (Object) fitness (readonly)

Overall population fitness and novelty



28
29
30
# File 'lib/rubyneat/population.rb', line 28

def fitness
  @fitness
end

- (Object) hidden_neurons

List of possible neuron classes for hidden neurons.



16
17
18
# File 'lib/rubyneat/population.rb', line 16

def hidden_neurons
  @hidden_neurons
end

- (Object) input_neurons

Ordered list or hash of input neuron classes (all critters generated here shall have this)



13
14
15
# File 'lib/rubyneat/population.rb', line 13

def input_neurons
  @input_neurons
end

- (Object) novelty (readonly)

Overall population fitness and novelty



28
29
30
# File 'lib/rubyneat/population.rb', line 28

def novelty
  @novelty
end

- (Object) output_neurons

Ordered list or hash of output neuron classes (all critters generated here shall have this)



20
21
22
# File 'lib/rubyneat/population.rb', line 20

def output_neurons
  @output_neurons
end

- (Object) species (readonly)

Hash list of species lists



31
32
33
# File 'lib/rubyneat/population.rb', line 31

def species
  @species
end

- (Object) traits

Returns the value of attribute traits



22
23
24
# File 'lib/rubyneat/population.rb', line 22

def traits
  @traits
end

Class Method Details

+ (Object) compactify!(parm)



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/rubyneat/population.rb', line 102

def @species.compactify!(parm)
  mutt = self[:mutt] = self.map { |k, splist| [k, splist]}.reject {|k, splist|
    splist.size >= parm.smallest_species
  }.map { |k, splist|
    self.delete k
    splist
  }.flatten

  # FIXME this code is not dry!!!!
  def mutt.fitness=(fit)
    @fitness = fit
  end

  def mutt.fitness
    @fitness
  end

  self.delete :mutt if self[:mutt].empty?
end

+ (Object) evaluate!



96
97
98
99
100
# File 'lib/rubyneat/population.rb', line 96

def @species.evaluate!
  self.each do |k, sp|
    sp.fitness = sp.map{|crit| crit.fitness}.reduce{|a,b| a+b} / sp.size
  end
end

+ (Boolean) member?(crit)

lists keyed by representative critter

Returns:

  • (Boolean)


92
93
94
# File 'lib/rubyneat/population.rb', line 92

def @species.member?(crit)
  super.member?(crit) or self.map{|k, li| li.member? crit}.reduce{|t1, t2| t1 or t2 }
end

Instance Method Details

- (Object) analyze!

Alalyze evaluation results.



74
75
76
# File 'lib/rubyneat/population.rb', line 74

def analyze!
   @critters.each { |critter| @controller.evaluator.analyze_for_fitness! critter }
end

- (Object) best_critter

The “best critter” is the critter with the lowest (closet to zero) fitness rating.



176
177
178
179
180
181
182
# File 'lib/rubyneat/population.rb', line 176

def best_critter
  unless @controller.compare_func.nil?
    @critters.min {|a, b| @controller.compare_func.(a.fitness, b.fitness) }
  else
    @critters.min {|a, b| a.fitness <=> b.fitness}
  end
end

- (Object) dump_s



194
195
196
# File 'lib/rubyneat/population.rb', line 194

def dump_s
  to_s + "\npopulation:\n" + @critters.map{|crit| crit.dump_s }.join("\n")
end

- (Object) evaluate!

Called for each sequence.



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

def evaluate!
   @critters.each { |critter| critter.evaluate! }
end

- (Object) evolve

Call this after evaluation. Returns a newly-evolved population.



80
81
82
# File 'lib/rubyneat/population.rb', line 80

def evolve
  @controller.evolver.evolve self
end

- (Object) express!

Express the entire population.



64
65
66
# File 'lib/rubyneat/population.rb', line 64

def express!
   @critters.each { |critter| critter.express! }
end

- (Object) initialize_for_recurrence!

Make sure all critters are reset and prepared for recurrent network evaluation.



54
55
56
# File 'lib/rubyneat/population.rb', line 54

def initialize_for_recurrence!
  @critters.each {|crit| crit.initialize_neurons!}
end

- (Object) mutate!

Mutate the genes and neurons.



59
60
61
# File 'lib/rubyneat/population.rb', line 59

def mutate!
  @controller.evolver.mutate! self
end

- (Object) report

Generate a report on the state of this population.



165
166
167
168
169
170
171
172
# File 'lib/rubyneat/population.rb', line 165

def report
  {
      fitness:         report_fitness,
      fitness_species: report_fitness_species,
      best_critter:    report_best_fit,
      worst_critter:   report_worst_fit,
  }
end

- (Object) speciate!

Group critters into species Note that the @species objects have useful singleton methods:

  • @species.member? – checks all of the lists for membership, not just the hash

  • @species.fitness – fitness of the entire species



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/rubyneat/population.rb', line 89

def speciate!
  # We blow away existing species and create our own member? function
  @species = {} # lists keyed by representative critter
  def @species.member?(crit)
    super.member?(crit) or self.map{|k, li| li.member? crit}.reduce{|t1, t2| t1 or t2 }
  end

  def @species.evaluate!
    self.each do |k, sp|
      sp.fitness = sp.map{|crit| crit.fitness}.reduce{|a,b| a+b} / sp.size
    end
  end

  def @species.compactify!(parm)
    mutt = self[:mutt] = self.map { |k, splist| [k, splist]}.reject {|k, splist|
      splist.size >= parm.smallest_species
    }.map { |k, splist|
      self.delete k
      splist
    }.flatten

    # FIXME this code is not dry!!!!
    def mutt.fitness=(fit)
      @fitness = fit
    end

    def mutt.fitness
      @fitness
    end

    self.delete :mutt if self[:mutt].empty?
  end

  # Some convience parms
  parm = @controller.parms

  # And so now we iterate...
  @critters.each do |crit|
    wearein = false
    @species.each do |ck, list|
      delta = crit.compare(ck)
      #log.debug { "delta for #{crit} and #{ck} is #{delta}" }
      if delta < parm.compatibility_threshold
        list << crit
        wearein = true
        break
      end
    end

    # New species?
    unless wearein
      @species[crit] = species = [crit]
      def species.fitness=(fit)
        @fitness = fit
      end
      def species.fitness
        @fitness
      end
    end
  end

  # Compactify the species if less than smallest_species
  @species.compactify! parm

  # And now we evaluate all species for fitness...
  @species.evaluate!

  # Dump for debugging reasons
  @species.each do |k, sp|
    log.debug ">> Species #{k} has #{sp.size} members with a #{sp.fitness} fitness"
  end

end

- (Object) worst_critter

The “worst critter” is the critter with the highest (away from zero) fitness rating.



186
187
188
189
190
191
192
# File 'lib/rubyneat/population.rb', line 186

def worst_critter
  unless @controller.compare_func.nil?
    @critters.max {|a, b| @controller.compare_func.(a.fitness, b.fitness) }
  else
    @critters.max {|a, b| a.fitness <=> b.fitness}
  end
end