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
@@ -0,0 +1,53 @@
|
|
1
|
+
# This class is used to hold sub-populations of individuals. For at least
|
2
|
+
# some length of time, subpopulations evolve independently, only interacting
|
3
|
+
# with the rest of the population (other subpopulations) during migration.
|
4
|
+
class Wallace::Subpopulation
|
5
|
+
|
6
|
+
attr_accessor :contents
|
7
|
+
attr_reader :capacity,
|
8
|
+
:species
|
9
|
+
|
10
|
+
# Constructs a new subpopulation.
|
11
|
+
#
|
12
|
+
# *Arguments*
|
13
|
+
# * opts, a hash of keyword options for this method.
|
14
|
+
# -> size, the size of this subpopulation.
|
15
|
+
# -> species, the species of individuals within this sub-population.
|
16
|
+
def initialize(opts = {})
|
17
|
+
@capacity = opts[:size]
|
18
|
+
@contents = []
|
19
|
+
@species = opts[:species]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Initialises a fresh sub-population of individuals.
|
23
|
+
#
|
24
|
+
# *Parameters:*
|
25
|
+
# * rng, the random number generator to use.
|
26
|
+
def fresh!(rng)
|
27
|
+
@contents = Array.new(@capacity) { @species.spawn(random: rng) }
|
28
|
+
end
|
29
|
+
|
30
|
+
# Clears the contents of this sub-population.
|
31
|
+
def clear!
|
32
|
+
@contents = []
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the best individual within this sub-population.
|
36
|
+
def best
|
37
|
+
@contents.min
|
38
|
+
end
|
39
|
+
alias :min :best
|
40
|
+
|
41
|
+
# Returns the worst individual within this sub-population.
|
42
|
+
def worst
|
43
|
+
@contents.max
|
44
|
+
end
|
45
|
+
alias :max :worst
|
46
|
+
|
47
|
+
# Returns the actual number of individuals within this population.
|
48
|
+
def size
|
49
|
+
@contents.size
|
50
|
+
end
|
51
|
+
alias_method :length, :size
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# This class is used to store and check against the termination criteria of the evolutionary
|
2
|
+
# process.
|
3
|
+
class Wallace::Termination
|
4
|
+
|
5
|
+
attr_reader :generation_limit,
|
6
|
+
:stagnation_limit,
|
7
|
+
:fitness_limit,
|
8
|
+
:error
|
9
|
+
|
10
|
+
# Constructs a new termination criteria.
|
11
|
+
#
|
12
|
+
# *Parameters:*
|
13
|
+
# * opts, a hash of keyword options for this method.
|
14
|
+
# -> generations, limit on the total number of generations to perform.
|
15
|
+
# -> stagnation, limit on the successive number of generations without change to the best solution.
|
16
|
+
# -> fitness, target fitness value.
|
17
|
+
# -> error, the maximum allowed error in the target fitness value.
|
18
|
+
def initialize(opts = {})
|
19
|
+
@generation_limit = opts[:generations] || 200
|
20
|
+
@stagnation_limit = opts[:stagnation]
|
21
|
+
@fitness_limit = opts[:fitness]
|
22
|
+
@error = opts[:error] || 0
|
23
|
+
end
|
24
|
+
|
25
|
+
# Determines whether the evolutionary process has reached its termination
|
26
|
+
# criteria or not.
|
27
|
+
#
|
28
|
+
# *Parameters:*
|
29
|
+
# * state, the current state of the evolution.
|
30
|
+
#
|
31
|
+
# Returns true if it has finished and false if otherwise.
|
32
|
+
def finished?(state)
|
33
|
+
return true if not @generation_limit.nil? and state.generations == @generation_limit
|
34
|
+
return true if not @fitness_limit.nil? and state.best.fitness.value <= @fitness_limit + @error
|
35
|
+
return true if not @stagnation_limit.nil? and state.stagnation == @stagnation_limit
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Used to represent and sample values from a given Gaussian distribution.
|
2
|
+
#
|
3
|
+
# Uses the popular Box-Muller transformation to generate two values,
|
4
|
+
# one of which is returned, the other which is cached (and returned
|
5
|
+
# upon the next request).
|
6
|
+
#
|
7
|
+
# Since the Box-Muller transform samples two values from the distribution,
|
8
|
+
# rather than discarding the extra value, we cache it and return it
|
9
|
+
# upon the next request.
|
10
|
+
#
|
11
|
+
# *Credit to:*
|
12
|
+
# http://stackoverflow.com/questions/5825680/code-to-generate-gaussian-normally-distributed-random-numbers-in-ruby
|
13
|
+
class Wallace::Distributions::GaussianDistribution
|
14
|
+
|
15
|
+
# Constructs a new Gaussian distribution.
|
16
|
+
#
|
17
|
+
# *Parameters:*
|
18
|
+
# * mean, the mean of this distribution.
|
19
|
+
# * std_dev, the standard deviation of this distribution.
|
20
|
+
def initialize(mean, std_dev)
|
21
|
+
@mean = mean
|
22
|
+
@std_dev = std_dev
|
23
|
+
@cached = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# Samples a value from this distribution.
|
27
|
+
#
|
28
|
+
# Uses the popular Box-Muller transformation to generate two values,
|
29
|
+
# one of which is returned, the other which is cached (and returned
|
30
|
+
# upon the next request).
|
31
|
+
#
|
32
|
+
# *Parameters:*
|
33
|
+
# * opts, keyword arguments for this method.
|
34
|
+
# * -> random, the random number generation to use to seed the selection process.
|
35
|
+
def sample(opts = {})
|
36
|
+
|
37
|
+
# Create a RNG if one isn't already provided.
|
38
|
+
random = opts[:random] || Random.new
|
39
|
+
|
40
|
+
# Return a cached value if there is one.
|
41
|
+
# We could collapse these 4 lines into a much nicer:
|
42
|
+
# return @values.pop if @values.empty?
|
43
|
+
# However .empty? is much more expensive!
|
44
|
+
unless @cached.nil?
|
45
|
+
value = @cached
|
46
|
+
@cached = nil
|
47
|
+
return value
|
48
|
+
end
|
49
|
+
|
50
|
+
# Otherwise calculate two new values, caching one and
|
51
|
+
# returning the other.
|
52
|
+
theta = 2 * Math::PI * random.rand
|
53
|
+
rho = Math.sqrt(-2 * Math.log(1 - random.rand))
|
54
|
+
scale = @std_dev * rho
|
55
|
+
@cached = @mean + scale * Math.cos(theta)
|
56
|
+
return @mean + scale * Math.sin(theta)
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/lib/fitness/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'raw_fitness.rb'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# The raw fitness model uses a single numeric type to describe the fitness of a given individual.
|
2
|
+
# Ordering of fitnesses, and thus of individuals, is achieved via ordering on these simple numeric
|
3
|
+
# types.
|
4
|
+
class Wallace::Fitness::RawFitness < Wallace::Fitness
|
5
|
+
|
6
|
+
# Allow the fitness value to be read but not changed.
|
7
|
+
attr_reader :value
|
8
|
+
|
9
|
+
# Constructs a new raw fitness.
|
10
|
+
#
|
11
|
+
# *Parameters:*
|
12
|
+
# * value, the raw fitness value.
|
13
|
+
def initialize(value)
|
14
|
+
@value = value
|
15
|
+
end
|
16
|
+
|
17
|
+
# Compares this raw fitness to another.
|
18
|
+
#
|
19
|
+
# *Parameters:*
|
20
|
+
# * other, the fitness to compare against.
|
21
|
+
#
|
22
|
+
# *Warning:*
|
23
|
+
# It is assumed that a RawFitness object is provided for comparison.
|
24
|
+
def <=>(other)
|
25
|
+
return -1 if other.value.is_a? Float and other.value.nan?
|
26
|
+
return 1 if @value.is_a? Float and @value.nan?
|
27
|
+
return @value <=> other.value
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# The CSV logger records information in a
|
2
|
+
class Wallace::Loggers::CsvLogger < Wallace::Logger
|
3
|
+
|
4
|
+
# Constructs a new CSV logger.
|
5
|
+
#
|
6
|
+
# *Parameters:*
|
7
|
+
# * file, the CSV file to log to.
|
8
|
+
# * opts, a hash of keyword options for this logger.
|
9
|
+
# -> columns, an ordered list of columns in this CSV.
|
10
|
+
# -> headers, an optional hash of headers for the columns in the CSV file.
|
11
|
+
def initialize(file)
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def write(data)
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/lib/loggers/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
module Wallace::Loggers; end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# Used to hold token values.
|
2
|
+
Wallace::GE::Literal = Struct.new(:value)
|
3
|
+
Wallace::GE::Symbol = Struct.new(:value)
|
4
|
+
|
5
|
+
# This class holds the details of a BNF grammar and provides methods for producing
|
6
|
+
# a derivation from a given sequence of integers.
|
7
|
+
#
|
8
|
+
# Rather than having a special class for grammar sequences, we simply use arrays to
|
9
|
+
# store grammar sequences, ensuring the best possible compatibility with existing
|
10
|
+
# array-based operators.
|
11
|
+
class Wallace::GE::BackusNaurForm
|
12
|
+
|
13
|
+
# The root symbol for this grammar (where all derivations begin).
|
14
|
+
attr_reader :root
|
15
|
+
|
16
|
+
# Constructs a new BNF Grammar.
|
17
|
+
#
|
18
|
+
# *Parameters:*
|
19
|
+
# * root, the root symbol in the grammar (at which all derivations start).
|
20
|
+
# * rules, the rules of this grammar, given as a hash, indexed by symbol.
|
21
|
+
def initialize(root, rules)
|
22
|
+
|
23
|
+
# Convert each rule into a sequence of symbol derivations.
|
24
|
+
# Transform each string-based derivation into a sequence of tokens.
|
25
|
+
@rules = Hash[rules.map { |rule, derivations|
|
26
|
+
derivations.map! { |derivation|
|
27
|
+
tokens = []
|
28
|
+
until derivation.empty?
|
29
|
+
left, tag, right = derivation.partition(/{\w+}/)
|
30
|
+
tokens << Wallace::GE::Literal.new(left) unless left.empty?
|
31
|
+
tokens << Wallace::GE::Symbol.new(tag[1...tag.length-1]) unless tag.empty?
|
32
|
+
derivation = right
|
33
|
+
end
|
34
|
+
tokens
|
35
|
+
}
|
36
|
+
[rule.to_s, derivations]
|
37
|
+
}].freeze
|
38
|
+
|
39
|
+
# Could ensure that the root is a valid symbol.
|
40
|
+
@root = root.to_s.freeze
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the number of symbols in the BNF.
|
45
|
+
def size
|
46
|
+
@rules.size
|
47
|
+
end
|
48
|
+
alias :length :size
|
49
|
+
|
50
|
+
# Returns the list of possible derivations for a given symbol.
|
51
|
+
def [](symbol)
|
52
|
+
@rules[symbol]
|
53
|
+
end
|
54
|
+
alias :derivations :[]
|
55
|
+
|
56
|
+
# Produces a grammar derivation from a given sequence of integers.
|
57
|
+
#
|
58
|
+
# *Parameters:*
|
59
|
+
# * sequence, the sequence of integers to produce a derivation from.
|
60
|
+
# * opts, a hash of keyword options for this method.
|
61
|
+
# -> random, the RNG to use during the derivation process.
|
62
|
+
# -> wrap, flag indicating whether the sequence should be wrapped when
|
63
|
+
# all genetic material has been used.
|
64
|
+
# -> max_wraps, the maximum number of times the sequence should be
|
65
|
+
# wrapped.
|
66
|
+
#
|
67
|
+
# *Returns:*
|
68
|
+
# A grammar derivation object for the produced derivation.
|
69
|
+
def derive(sequence, opts = {})
|
70
|
+
|
71
|
+
# For now wrapping is forced.
|
72
|
+
opts[:wrap] = true
|
73
|
+
opts[:max_wraps] ||= 1 if opts[:wrap]
|
74
|
+
|
75
|
+
derivation = Wallace::GE::GrammarDerivation.new
|
76
|
+
|
77
|
+
# Keep processing the sequence of tokens until none remain.
|
78
|
+
#
|
79
|
+
# * Literal tokens are appended to the end of the derivation.
|
80
|
+
# * Symbol tokens are converted into a given symbol derivation,
|
81
|
+
# using the next codon as the index if there is more than a single
|
82
|
+
# choice.
|
83
|
+
# * When there are no codons left to consume then we either:
|
84
|
+
# a) Add a new codon to the sequence (until the limit is reached). [DISABLED]
|
85
|
+
# b) Reset the codon index to zero, wrapping the sequence round.
|
86
|
+
queue = [Wallace::GE::Symbol.new(@root)]
|
87
|
+
codon_index = 0
|
88
|
+
sequence_length = sequence.length
|
89
|
+
num_wraps = 0
|
90
|
+
|
91
|
+
until queue.empty?
|
92
|
+
token = queue.shift
|
93
|
+
if token.is_a? Wallace::GE::Literal
|
94
|
+
derivation << token.value
|
95
|
+
else
|
96
|
+
options = @rules[token.value]
|
97
|
+
if options.length == 1
|
98
|
+
queue += options[0]
|
99
|
+
else
|
100
|
+
|
101
|
+
# Check if there are no remaining codons in the sequence.
|
102
|
+
if (codon_index >= sequence_length)
|
103
|
+
|
104
|
+
# If wrapping is enabled, reset the codon pointer to the
|
105
|
+
# start of the sequence, unless the maximum number of wraps
|
106
|
+
# has been encountered.
|
107
|
+
if opts[:wrap]
|
108
|
+
raise Wallace::Errors::GenotypeExhaustedError if num_wraps != opts[:max_wraps] # throw error?
|
109
|
+
codon_index = 0
|
110
|
+
num_wraps += 1
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
queue = options[sequence[codon_index] % options.length] + queue
|
116
|
+
codon_index += 1
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
return derivation.freeze
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# The GrammarDerivation class is used to hold a derivation of a grammar produced by some provided
|
2
|
+
# sequence of integers. This class implements methods for transforming the derivation into other
|
3
|
+
# forms.
|
4
|
+
class Wallace::GE::GrammarDerivation < String
|
5
|
+
|
6
|
+
# Produces a lambda function from a given grammar derivation and a set
|
7
|
+
# of arguments.
|
8
|
+
#
|
9
|
+
# *Parameters:*
|
10
|
+
# * args, an ordered array of the arguments to the lambda function.
|
11
|
+
# * derivation, the grammar derivation to use as the body of the function.
|
12
|
+
#
|
13
|
+
# *Returns:*
|
14
|
+
# The corresponding lambda function.
|
15
|
+
def self.to_lambda(args, derivation)
|
16
|
+
eval("lambda { |#{args.join(',')}| #{derivation} }")
|
17
|
+
end
|
18
|
+
|
19
|
+
# Converts this derivation into a usable lambda function.
|
20
|
+
#
|
21
|
+
# *Parameters:*
|
22
|
+
# * args, an ordered array of the arguments to the lambda function.
|
23
|
+
#
|
24
|
+
# *Returns:*
|
25
|
+
# The corresponding lambda function.
|
26
|
+
def to_lambda(args)
|
27
|
+
Wallace::GE::GrammarDerivation.to_lambda(args, self)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# The grammar species represents each individual in the species as an array of integers which
|
2
|
+
# map to a derivation of the grammar attached to the species.
|
3
|
+
class Wallace::GE::GrammarSpecies < Wallace::Species::ArraySpecies
|
4
|
+
|
5
|
+
name = :grammar
|
6
|
+
|
7
|
+
attr_reader :grammar
|
8
|
+
|
9
|
+
# Constructs a new grammar-based species.
|
10
|
+
#
|
11
|
+
# *Parameters:*
|
12
|
+
# * opts, hash of keyword options used by this method.
|
13
|
+
# -> id, the unique identifier for this species.
|
14
|
+
# -> grammar, the grammar used by individuals of this species.
|
15
|
+
# -> length, the length constraints on individuals of the species.
|
16
|
+
def initialize(opts = {})
|
17
|
+
|
18
|
+
# By default grammar derivations are between 10 and 200 symbols and contain
|
19
|
+
# integers in the range 0 to 2147483647 inclusive.
|
20
|
+
opts[:length] ||= 10..200
|
21
|
+
opts[:values] ||= 0..2147483647
|
22
|
+
|
23
|
+
super(opts)
|
24
|
+
|
25
|
+
@grammar = opts[:grammar]
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/lib/modules/init.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# The base class used by all Koza tree builders.
|
2
|
+
class Wallace::Koza::Builder
|
3
|
+
|
4
|
+
# The range of depths that trees within this species may have.
|
5
|
+
attr_accessor :depth_limits
|
6
|
+
|
7
|
+
attr_reader :terminals,
|
8
|
+
:non_terminals
|
9
|
+
|
10
|
+
# Prepares the builder.
|
11
|
+
#
|
12
|
+
# *Parameters:*
|
13
|
+
# * terminals, the list of terminals.
|
14
|
+
# * non_terminals, the list of non-terminals.
|
15
|
+
# * depth_limits, the range of depths that trees within the species may have.
|
16
|
+
def prepare(terminals, non_terminals, depth_limits)
|
17
|
+
@terminals = terminals
|
18
|
+
@non_terminals = non_terminals
|
19
|
+
@depth_limits = depth_limits
|
20
|
+
end
|
21
|
+
|
22
|
+
# Builds a new tree according to this build method that meets the depth
|
23
|
+
# constraints of the species.
|
24
|
+
#
|
25
|
+
# *Parameters:*
|
26
|
+
# * opts, a hash of keyword options for this method.
|
27
|
+
# -> random, the RNG to use for building the tree.
|
28
|
+
#
|
29
|
+
# *Returns:*
|
30
|
+
# The built tree.
|
31
|
+
def build_tree(opts = {})
|
32
|
+
raise NotImplementedError, 'No "build_tree" function was implemented by this builder.'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Builds a new subtree of a maximum given depth.
|
36
|
+
#
|
37
|
+
# *Parameters:*
|
38
|
+
# * max_depth, the maximum depth of the sub-tree.
|
39
|
+
# * opts, a hash of keyword options for this method.
|
40
|
+
# -> random, the RNG to use for building the subtree.
|
41
|
+
#
|
42
|
+
# *Returns:*
|
43
|
+
# The root node of the built sub-tree.
|
44
|
+
def build_subtree(max_depth, opts = {})
|
45
|
+
raise NotImplementedError, 'No "build_subtree" function was implemented by this builder.'
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|