wallace 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +14 -0
- data/README.md +12 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/bin/.gitkeep +0 -0
- data/lib/analysers/fitness_distribution_analyser.rb +28 -0
- data/lib/analysers/init.rb +1 -0
- data/lib/core/analyser.rb +63 -0
- data/lib/core/breeder.rb +68 -0
- data/lib/core/breeding_graph.rb +59 -0
- data/lib/core/breeding_graph/init.rb +3 -0
- data/lib/core/breeding_graph/input_node.rb +55 -0
- data/lib/core/breeding_graph/node.rb +68 -0
- data/lib/core/breeding_graph/node_input.rb +6 -0
- data/lib/core/evaluator.rb +52 -0
- data/lib/core/evolver.rb +47 -0
- data/lib/core/exceptions.rb +6 -0
- data/lib/core/experiment.rb +22 -0
- data/lib/core/fitness.rb +8 -0
- data/lib/core/fraction.rb +7 -0
- data/lib/core/individual.rb +65 -0
- data/lib/core/logger.rb +5 -0
- data/lib/core/migrator.rb +6 -0
- data/lib/core/operator.rb +54 -0
- data/lib/core/population.rb +56 -0
- data/lib/core/selector.rb +43 -0
- data/lib/core/species.rb +52 -0
- data/lib/core/state.rb +29 -0
- data/lib/core/subpopulation.rb +53 -0
- data/lib/core/termination.rb +39 -0
- data/lib/distributions/gaussian_distribution.rb +60 -0
- data/lib/distributions/init.rb +3 -0
- data/lib/fitness/init.rb +1 -0
- data/lib/fitness/raw_fitness.rb +30 -0
- data/lib/loggers/csv_logger.rb +20 -0
- data/lib/loggers/init.rb +1 -0
- data/lib/loggers/mongo_logger.rb +5 -0
- data/lib/loggers/sqlite_logger.rb +5 -0
- data/lib/modules/ge/backus_naur_form.rb +125 -0
- data/lib/modules/ge/grammar_derivation.rb +30 -0
- data/lib/modules/ge/grammar_species.rb +29 -0
- data/lib/modules/ge/init.rb +5 -0
- data/lib/modules/init.rb +2 -0
- data/lib/modules/koza/builder.rb +48 -0
- data/lib/modules/koza/builder/full_builder.rb +92 -0
- data/lib/modules/koza/builder/grow_builder.rb +103 -0
- data/lib/modules/koza/builder/half_builder.rb +70 -0
- data/lib/modules/koza/builder/init.rb +3 -0
- data/lib/modules/koza/ephemeral.rb +33 -0
- data/lib/modules/koza/init.rb +12 -0
- data/lib/modules/koza/koza_node.rb +108 -0
- data/lib/modules/koza/koza_node_value.rb +72 -0
- data/lib/modules/koza/koza_node_value_set.rb +51 -0
- data/lib/modules/koza/koza_species.rb +48 -0
- data/lib/modules/koza/koza_tree.rb +159 -0
- data/lib/modules/koza/operators/init.rb +4 -0
- data/lib/modules/koza/operators/subtree_crossover_operation.rb +43 -0
- data/lib/modules/koza/operators/subtree_mutation_operation.rb +32 -0
- data/lib/operators/bit_flip_mutation_operation.rb +29 -0
- data/lib/operators/boundary_mutation_operation.rb +28 -0
- data/lib/operators/cycle_crossover_operation.rb +77 -0
- data/lib/operators/gaussian_mutation_operation.rb +39 -0
- data/lib/operators/half_uniform_crossover_operation.rb +24 -0
- data/lib/operators/init.rb +26 -0
- data/lib/operators/merging_crossover_operation.rb +27 -0
- data/lib/operators/one_point_crossover_operation.rb +29 -0
- data/lib/operators/order_crossover_operation.rb +38 -0
- data/lib/operators/partially_mapped_crossover_operation.rb +44 -0
- data/lib/operators/point_mutation_operation.rb +31 -0
- data/lib/operators/position_crossover_operation.rb +50 -0
- data/lib/operators/reverse_sequence_mutation_operation.rb +13 -0
- data/lib/operators/shuffle_mutation_operation.rb +17 -0
- data/lib/operators/splice_crossover_operation.rb +42 -0
- data/lib/operators/subtour_exchange_crossover_operation.rb +54 -0
- data/lib/operators/swap_mutation_operation.rb +29 -0
- data/lib/operators/three_parent_crossover_operation.rb +16 -0
- data/lib/operators/two_point_crossover_operation.rb +31 -0
- data/lib/operators/twors_mutation_operation.rb +18 -0
- data/lib/operators/uniform_crossover_operation.rb +30 -0
- data/lib/operators/uniform_mutation_operation.rb +31 -0
- data/lib/operators/variable_one_point_crossover_operation.rb +80 -0
- data/lib/patches/enumerable.rb +85 -0
- data/lib/patches/init.rb +5 -0
- data/lib/patches/range.rb +13 -0
- data/lib/selectors/init.rb +5 -0
- data/lib/selectors/random_selector.rb +14 -0
- data/lib/selectors/roulette_selector.rb +23 -0
- data/lib/selectors/tournament_selector.rb +36 -0
- data/lib/species/array_species.rb +40 -0
- data/lib/species/bit_string_species.rb +18 -0
- data/lib/species/init.rb +4 -0
- data/lib/species/permutation_species.rb +22 -0
- data/lib/species/string_species.rb +29 -0
- data/lib/utility/init.rb +4 -0
- data/lib/utility/scaled_array.rb +88 -0
- data/lib/utility/sorted_array.rb +39 -0
- data/lib/wallace.rb +40 -0
- data/test/.gitkeep +0 -0
- metadata +248 -0
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
gem 'peach'
|
4
|
+
|
5
|
+
# GraphViz - Great for Trees, Graph and Network visualisation.
|
6
|
+
#gem 'ruby-graphviz'
|
7
|
+
#gem 'win32-open3'
|
8
|
+
|
9
|
+
group :development do
|
10
|
+
gem 'jeweler', '~> 1.8.7'
|
11
|
+
gem 'rake'
|
12
|
+
gem 'rdoc'
|
13
|
+
gem 'bundler'
|
14
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
**Wallace.rb**
|
2
|
+
==========
|
3
|
+
|
4
|
+
A highly expressive and modular evolutionary toolkit for performing genetic algorithms, genetic programming, grammatical evolution and meta-evolution in Ruby.
|
5
|
+
|
6
|
+
**Tested with:**
|
7
|
+
* Ruby >= 1.9.1
|
8
|
+
* JRuby >= 1.7.8
|
9
|
+
|
10
|
+
**Tested platforms:**
|
11
|
+
* Windows 7 (x64)
|
12
|
+
* Ubuntu 13.10 (x64)
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Load all dependencies.
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler'
|
4
|
+
require 'rake'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'rdoc/task'
|
7
|
+
require 'jeweler'
|
8
|
+
|
9
|
+
begin
|
10
|
+
Bundler.setup(:default, :development)
|
11
|
+
rescue Bundler::BundlerError => e
|
12
|
+
$stderr.puts e.message
|
13
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
14
|
+
exit e.status_code
|
15
|
+
end
|
16
|
+
|
17
|
+
# Gem Specification.
|
18
|
+
Jeweler::Tasks.new do |gem|
|
19
|
+
gem.name = "wallace"
|
20
|
+
gem.homepage = "http://github.com/ChrisTimperley/Wallace.rb"
|
21
|
+
gem.license = "MIT"
|
22
|
+
gem.summary = "A powerful, flexible and modular toolkit for running Evolutionary Algorithms in Ruby"
|
23
|
+
gem.description = <<-EOF
|
24
|
+
Wallace is a powerful, flexible and modular toolkit for running Evolutionary Algorithms in Ruby.
|
25
|
+
Out of the box it provides support for steady-state EAs, genetic algorithms, genetic programming,
|
26
|
+
grammatical evolution and other types of EAs.
|
27
|
+
EOF
|
28
|
+
gem.email = "christimperley@gmail.com"
|
29
|
+
gem.author = "Chris Timperley"
|
30
|
+
gem.add_dependency "peach", "~> 0.5.1"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Gem Management.
|
34
|
+
Jeweler::RubygemsDotOrgTasks.new
|
35
|
+
|
36
|
+
# Unit Testing.
|
37
|
+
Rake::TestTask.new(:test) do |test|
|
38
|
+
test.libs << 'lib' << 'test'
|
39
|
+
test.pattern = 'test/**/test_*.rb'
|
40
|
+
test.verbose = true
|
41
|
+
end
|
42
|
+
|
43
|
+
# Documentation.
|
44
|
+
task :default => :test
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "wallace #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/bin/.gitkeep
ADDED
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Wallace::Analysers::FitnessDistributionAnalyser < Wallace::Analyser
|
2
|
+
|
3
|
+
def initialize
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
def after_generation(state)
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
# Calculates the distribution of fitness values at the current evolution state.
|
14
|
+
#
|
15
|
+
# *Parameters:*
|
16
|
+
# * state, the current state of the evolution.
|
17
|
+
def calculate_distribution(state)
|
18
|
+
stats = {}
|
19
|
+
stats[:max] = state.population.fitness_max
|
20
|
+
stats[:min] = state.population.fitness_min
|
21
|
+
stats[:lq], stats[:median], stats[:uq] = state.population.fitness_quartiles
|
22
|
+
stats[:mean] = state.population.fitness_mean
|
23
|
+
stats[:std] =
|
24
|
+
stats[:var] =
|
25
|
+
return stats
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
module Wallace::Analysers; end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Analysers are used to analyse the current state of the evolution at given stages.
|
2
|
+
# These objects may be used to gather data, calculate statistics and log information
|
3
|
+
# during the evolution.
|
4
|
+
#
|
5
|
+
# Analysers may harness the outputs of attached analysers to supplement their input data.
|
6
|
+
# This ability can be exploited to perform multi-stage post-processing and to efficiently
|
7
|
+
# record information.
|
8
|
+
class Wallace::Analyser
|
9
|
+
|
10
|
+
attr_reader :inputs
|
11
|
+
|
12
|
+
# Constructs a new analyser.
|
13
|
+
#
|
14
|
+
# *Parameters:*
|
15
|
+
# * inputs, the input analysers which feed data into this analyser.
|
16
|
+
def initialize(inputs)
|
17
|
+
@inputs = inputs
|
18
|
+
end
|
19
|
+
|
20
|
+
# Runs this analyser at a given stage in the evolution.
|
21
|
+
#
|
22
|
+
# Executes the input analysers to gather the input data which is then
|
23
|
+
# fed into the appropriate stage handler of this analyser.
|
24
|
+
#
|
25
|
+
# *Parameters:*
|
26
|
+
# * stage, the current stage in the evolution.
|
27
|
+
# * state, the current state of the evolution.
|
28
|
+
#
|
29
|
+
# *Returns:*
|
30
|
+
# Output data for processing by any attached analysers.
|
31
|
+
def run(stage, state)
|
32
|
+
input_data = @inputs.map { |i| i.run(stage, state) }
|
33
|
+
self.method(stage).invoke(state, input_data)
|
34
|
+
end
|
35
|
+
|
36
|
+
# All stage handlers are protected and should not be called directly!
|
37
|
+
# Instead the 'run' method must be used so that input data is gathered
|
38
|
+
# for the analyser.
|
39
|
+
protected
|
40
|
+
|
41
|
+
# This analysis hook is called prior to the start of each generation.
|
42
|
+
#
|
43
|
+
# *Parameters:*
|
44
|
+
# * state, the current state of the evolution.
|
45
|
+
# * input_data, the data provided by the attached input analysers.
|
46
|
+
def before_generation(state, input_data = nil); end
|
47
|
+
|
48
|
+
# This analysis hook is called after the end of a generation.
|
49
|
+
#
|
50
|
+
# *Parameters:*
|
51
|
+
# * state, the current state of the evolution.
|
52
|
+
# * input_data, the data provided by the attached input analysers.
|
53
|
+
def after_generation(state, input_data = nil); end
|
54
|
+
|
55
|
+
# This analysis hook is called upon termination of the evolution.
|
56
|
+
#
|
57
|
+
# *Parameters:*
|
58
|
+
# * state, the current state of the evolution.
|
59
|
+
# * input_data, the data provided by the attached input analysers.
|
60
|
+
def on_termination(state, input_data = nil); end
|
61
|
+
alias_method :after_run, :on_termination
|
62
|
+
|
63
|
+
end
|
data/lib/core/breeder.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#
|
2
|
+
#
|
3
|
+
# The breeder is decoupled from the evolver, subpopulation and population models.
|
4
|
+
# This allows the breeder to be used in a number of different configurations, where
|
5
|
+
# one breeder is used per evolver, population or sub-population.
|
6
|
+
class Wallace::Breeder
|
7
|
+
|
8
|
+
attr_reader :elitism,
|
9
|
+
:graph,
|
10
|
+
:threads
|
11
|
+
|
12
|
+
# Constructs a new breeder.
|
13
|
+
#
|
14
|
+
# *Arguments*
|
15
|
+
# * opts, a hash of keyword options for this method.
|
16
|
+
# -> graph, the breeding graph for this breeder.
|
17
|
+
# -> elitism, the number (or fraction) of fittest individuals that should be carried over to the
|
18
|
+
# next generation. (default = 0).
|
19
|
+
# -> threads, the number of threads the breeding process is split across. (default = 1).
|
20
|
+
def initialize(opts = {})
|
21
|
+
@elitism = opts[:elitism]
|
22
|
+
@threads = opts[:threads] || 1
|
23
|
+
@graphs = Array.new(@threads) { opts[:graph].clone }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Breeds the next generation of individuals for the given subpopulation.
|
27
|
+
#
|
28
|
+
# *Parameters:*
|
29
|
+
# * rng, random number generation to use during breeding.
|
30
|
+
# * subpopulation, the target subpopulation.
|
31
|
+
def breed!(rng, subpopulation)
|
32
|
+
|
33
|
+
# Prepare the candidate list for each input for all graphs.
|
34
|
+
@graphs[0].inputs.each_index do |i|
|
35
|
+
candidates = subpopulation.contents
|
36
|
+
@graphs.each_index do |g|
|
37
|
+
candidates = @graphs[g].inputs[i].prepare!(candidates, random: rng, processed: g > 0)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create a temporary array for the new sub-population.
|
42
|
+
size = subpopulation.contents.size
|
43
|
+
buffer = Array.new(size)
|
44
|
+
|
45
|
+
# Add the elite individuals to the end of the sub-population if elitism is enabled.
|
46
|
+
elites = @elitism.nil? ? 0 : @elitism
|
47
|
+
elites = elites.value * size if elites.is_a? Wallace::Fraction
|
48
|
+
buffer[(size - elites)...size] = subpopulation.contents.nmin(elites)
|
49
|
+
|
50
|
+
# Spread the breeding process across multiple threads.
|
51
|
+
# using a separate breeding graph for each thread to ensure thread-safety.
|
52
|
+
thread_size = (size/@threads.to_f).ceil
|
53
|
+
(0...@threads).peach(@threads) do |t|
|
54
|
+
range = t * thread_size
|
55
|
+
range = range...([size, range + thread_size].min)
|
56
|
+
|
57
|
+
@graphs[t].breed!(rng, buffer, range)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Clean each breeding graph.
|
61
|
+
@graphs.each { |g| g.clean! }
|
62
|
+
|
63
|
+
# Swap the contents of the sub-population with the buffer.
|
64
|
+
subpopulation.contents = buffer
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class Wallace::BreedingGraph
|
2
|
+
|
3
|
+
attr_reader :outputs,
|
4
|
+
:inputs,
|
5
|
+
:nodes
|
6
|
+
|
7
|
+
# Constructs a new BreedingGraph.
|
8
|
+
#
|
9
|
+
# *Parameters:*
|
10
|
+
# * opts, a hash of keyword options.
|
11
|
+
# -> outputs, an array of terminal nodes in this breeding graph (can be weighted).
|
12
|
+
# -> buffered, flag indicating whether the process should be buffered.
|
13
|
+
def initialize(opts = {})
|
14
|
+
|
15
|
+
@outputs = opts[:outputs]
|
16
|
+
@buffered = opts[:buffered] || true
|
17
|
+
|
18
|
+
# Produce a list of nodes in the graph and find all inputs to the graph.
|
19
|
+
@nodes = []
|
20
|
+
@inputs = []
|
21
|
+
queue = @outputs.clone
|
22
|
+
|
23
|
+
until queue.empty?
|
24
|
+
node = queue.shift
|
25
|
+
@nodes << node
|
26
|
+
if node.is_a? Wallace::BreedingGraph::InputNode
|
27
|
+
@inputs << node
|
28
|
+
else
|
29
|
+
queue += node.inputs.map{ |i| i.source }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
# Discards all temporary information regarding the last breeding
|
36
|
+
# cycle and clears all the buffers.
|
37
|
+
def clean!
|
38
|
+
@nodes.each { |n| n.clean! }
|
39
|
+
end
|
40
|
+
|
41
|
+
# Breeds a portion of the associated given sub-population for the next generation.
|
42
|
+
#
|
43
|
+
# *Parameters:*
|
44
|
+
# * rng, the RNG to use when breeding individuals.
|
45
|
+
# * buffer, the buffer for the contents of the sub-population of the next generation.
|
46
|
+
# * range, the range of indices to be populated in the buffer by newly bred individuals.
|
47
|
+
def breed!(rng, buffer, range)
|
48
|
+
range.each { |i| buffer[i] = @outputs.sample(random: rng).take!(rng) }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Creates a clone of this breeding graph.
|
52
|
+
def clone
|
53
|
+
Wallace::BreedingGraph.new(
|
54
|
+
outputs: @outputs.map { |n| n.clone },
|
55
|
+
buffered: @buffered
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Used to represent input nodes (i.e. sub-population selection nodes) in the
|
2
|
+
# breeding graph.
|
3
|
+
class Wallace::BreedingGraph::InputNode < Wallace::BreedingGraph::Node
|
4
|
+
|
5
|
+
# Constructs a new input node.
|
6
|
+
#
|
7
|
+
# *Parameters:*
|
8
|
+
# * selector, the selection method used by this input node.
|
9
|
+
def initialize(selector)
|
10
|
+
super(selector, [])
|
11
|
+
@candidates = []
|
12
|
+
end
|
13
|
+
|
14
|
+
alias :selector :function
|
15
|
+
|
16
|
+
# Selects a single individual from the list of candidates using the selection method
|
17
|
+
# associated with this node.
|
18
|
+
#
|
19
|
+
# *Parameters:*
|
20
|
+
# * rng, the RNG to use when selecting an individual from the list of candidates.
|
21
|
+
def take!(rng)
|
22
|
+
@function.produce(rng, @candidates).clone
|
23
|
+
end
|
24
|
+
|
25
|
+
# Prepares this input node for the next breeding cycle by supplying the contents
|
26
|
+
# of the sub-population and performing any necessary post-processing.
|
27
|
+
#
|
28
|
+
# To prevent redundant post-processing when using multiple threads, we can supply
|
29
|
+
# a prepared candidate list from the same input node from an other breeding graph.
|
30
|
+
#
|
31
|
+
# *Parameters:*
|
32
|
+
# * candidates, a list of (possibly post-processed) candidates for selection.
|
33
|
+
# * opts, a hash of keyword options for this method.
|
34
|
+
# -> random, the RNG to use when preparing the candidate list.
|
35
|
+
# -> processed, a flag indicating if this candidate list has already been post-processed.
|
36
|
+
#
|
37
|
+
# *Returns:*
|
38
|
+
# The prepared candidate list (so that it can be exploited by identical nodes in other graphs).
|
39
|
+
def prepare!(candidates, opts = {})
|
40
|
+
@candidates = opts[:processed] ? candidates.clone : @function.prepare(candidates, opts)
|
41
|
+
return @candidates
|
42
|
+
end
|
43
|
+
|
44
|
+
# Creates a clone of this node and its inputs.
|
45
|
+
def clone
|
46
|
+
Wallace::BreedingGraph::InputNode.new(@function)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Clears the contents of the buffer and candidates list for this input node.
|
50
|
+
def clean!
|
51
|
+
super
|
52
|
+
@candidates.clear
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Represents a node within the breeding graph.
|
2
|
+
#
|
3
|
+
# Each node corresponds to a stage within the breeding process and is associated with
|
4
|
+
# a given operator or selection method which is used on the inputs to that node to produce
|
5
|
+
# some individuals for the next generation or for further processing by successive nodes in
|
6
|
+
# the graph.
|
7
|
+
class Wallace::BreedingGraph::Node
|
8
|
+
|
9
|
+
attr_reader :function,
|
10
|
+
:inputs
|
11
|
+
|
12
|
+
# Constructs a node for the breeding graph.
|
13
|
+
#
|
14
|
+
# *Parameters:*
|
15
|
+
# * function, the operator or selection method associated to this node.
|
16
|
+
# * inputs, an array of inputs to this node.
|
17
|
+
def initialize(function, inputs)
|
18
|
+
@inputs = inputs
|
19
|
+
@function = function
|
20
|
+
@buffer = []
|
21
|
+
end
|
22
|
+
|
23
|
+
# Takes and returns a single individual produced (or selected) by this node.
|
24
|
+
#
|
25
|
+
# If there are no individuals held in the buffer then a number are produced
|
26
|
+
# (or selected) using the operator (or selection method) attached to this node.
|
27
|
+
#
|
28
|
+
# *Parameters:*
|
29
|
+
# * rng, the RNG to use if new individuals are bred.
|
30
|
+
#
|
31
|
+
# *Returns:*
|
32
|
+
# An array of individuals produced at this node.
|
33
|
+
def take!(rng)
|
34
|
+
@buffer += @function.produce(rng, generate_inputs!(rng)) if @buffer.empty?
|
35
|
+
return @buffer.pop
|
36
|
+
end
|
37
|
+
|
38
|
+
# Clears the buffer of this node and discards any temporary
|
39
|
+
# information relating to the breeding processs.
|
40
|
+
def clean!
|
41
|
+
@buffer.clear
|
42
|
+
end
|
43
|
+
|
44
|
+
# Creates a clone of this node and its inputs.
|
45
|
+
def clone
|
46
|
+
Wallace::BreedingGraph::Node.new(
|
47
|
+
@function,
|
48
|
+
@inputs.map { |i| Wallace::BreedingGraph::NodeInput.new(i.source.clone, i.size) }
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
# Generates a set of individuals to use as input to this node using the information
|
55
|
+
# in the list of associated node inputs.
|
56
|
+
#
|
57
|
+
# *Parameters:*
|
58
|
+
# * rng, the RNG to use when producing individuals up the breeding chain.
|
59
|
+
#
|
60
|
+
# *Returns:*
|
61
|
+
# An array of individuals to use as input for this node.
|
62
|
+
def generate_inputs!(rng)
|
63
|
+
return @inputs.reduce([]) do |inds, input|
|
64
|
+
inds += Array.new(input.size) { input.source.take!(rng) }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# Used to represent inputs to a given node in the breeding graph.
|
2
|
+
#
|
3
|
+
# *Attributes:*
|
4
|
+
# * source, the source node to retrieve individuals from.
|
5
|
+
# * size, the number of individuals to retrieve from the source.
|
6
|
+
Wallace::BreedingGraph::NodeInput = Struct.new(:source, :size)
|