evolvable 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/README.md +214 -79
- data/lib/evolvable/evaluation.rb +1 -1
- data/lib/evolvable/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9b226220f12cc98cfd94f14caf0f3898f0b1dab435bc4e8ce58696c053c8ea8
|
4
|
+
data.tar.gz: d8f03fb093698fd25c24ee0038e813832caba6c80a802933c0d3cc97125e96b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d25f4af589b828b4791c52b469e91f5814e5e06f372a331f4214cbfab6daf8d74dd2f7db777e6117c9b97fb04e55c9f007a612d31b6fba7b253784117df4edca
|
7
|
+
data.tar.gz: ad7d7a46306d20512d199dc32eb688c0c2e8f03ff86358a9ef17e8f9e868117f40ebf5fe4cbafedf8ad843b8a055e722b1781bf145feaa9e51369889ee3131a5
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -7,9 +7,7 @@ A framework for building evolutionary behaviors in Ruby.
|
|
7
7
|
With a straightforward and extensible API, Evolvable aims to make building simple as well as complex evolutionary algorithms fun and relatively easy.
|
8
8
|
|
9
9
|
### The Evolvable Abstraction
|
10
|
-
Population objects are composed of instances that include the `Evolvable` module. Instances are composed of gene objects that include the `Evolvable::Gene` module. Evaluation and evolution objects are used by population objects to evolve your instances. An evaluation object has one goal object and the evolution object is composed of selection, crossover, and mutation objects by default.
|
11
|
-
|
12
|
-
All classes exposed by Evolvable are prefixed with `Evolvable::` and can be configured, inherited, removed, and extended. You can also choose between various Evolvable implementations documented below or substitute your own. Don't worry if none of this made sense, this will become clearer as you continue reading.
|
10
|
+
Population objects are composed of instances that include the `Evolvable` module. Instances are composed of gene objects that include the `Evolvable::Gene` module. Evaluation and evolution objects are used by population objects to evolve your instances. An evaluation object has one goal object and the evolution object is composed of selection, crossover, and mutation objects by default. All classes exposed by Evolvable are prefixed with `Evolvable::` and can be configured, inherited, removed, and extended.
|
13
11
|
|
14
12
|
## Installation
|
15
13
|
|
@@ -21,22 +19,22 @@ After installing and requiring the "evolvable" Ruby gem:
|
|
21
19
|
|
22
20
|
1. Include the `Evolvable` module in the class for the instances you want to evolve. (See [Configuration](#Configuration)).
|
23
21
|
2. Implement `.gene_space`, define any gene classes referenced by it, and include the `Evolvable::Gene` module for each. (See [Genes](#Genes)).
|
24
|
-
3. Implement `#value`. (See [Evaluation](#
|
22
|
+
3. Implement `#value`. (See [Evaluation](#evaluation-1)).
|
25
23
|
4. Initialize a population and start evolving. (See [Populations](#Populations)).
|
26
24
|
|
27
|
-
Visit the [
|
25
|
+
Visit the [Evolving Strings](https://github.com/mattruzicka/evolvable/wiki/Evolving-Strings) tutorial to see these steps in action. It walks through a simplified implementation of the [evolve string](https://github.com/mattruzicka/evolve_string) command-line program. Here's the [example source code](https://github.com/mattruzicka/evolvable/blob/master/examples/evolvable_string.rb) for the tutorial.
|
28
26
|
|
29
27
|
If you’d like to quickly play around with an evolvable string Population object, you can do so by cloning this repo and running the command `bin/console` in this project's directory.
|
30
28
|
|
31
29
|
## Usage
|
32
30
|
- [Configuration](#Configuration)
|
33
31
|
- [Genes](#Genes)
|
34
|
-
- [Evaluation](#Evaluation)
|
35
32
|
- [Populations](#Populations)
|
36
|
-
- [
|
37
|
-
- [
|
33
|
+
- [Evaluation](#evaluation-1)
|
34
|
+
- [Evolution](#evolution-1)
|
35
|
+
- [Selection](#selection-1)
|
38
36
|
- [Crossover](#Crossover)
|
39
|
-
- [Mutation](#
|
37
|
+
- [Mutation](#mutation-1)
|
40
38
|
|
41
39
|
## Configuration
|
42
40
|
|
@@ -47,83 +45,73 @@ class Melody
|
|
47
45
|
include Evolvable
|
48
46
|
|
49
47
|
def self.gene_space
|
50
|
-
|
48
|
+
{ instrument: { type: 'InstrumentGene', count: 1 },
|
49
|
+
notes: { type: 'NoteGene', count: 16 } }
|
51
50
|
end
|
52
51
|
|
53
52
|
def value
|
54
|
-
#
|
53
|
+
average_rating # ...
|
55
54
|
end
|
56
55
|
end
|
57
56
|
```
|
58
57
|
|
59
|
-
The `Evolvable` module
|
60
|
-
|
61
|
-
#### .gene_space
|
58
|
+
The `Evolvable` module expects the [".gene_space" class method](#evolvableclassgene_space) and requires the ["#value" instance method](#evolvableclassvalue) to be defined as documented below. Other methods exposed by `Evolvable` have also been documented below.
|
62
59
|
|
63
|
-
|
60
|
+
### EvolvableClass.gene_space
|
64
61
|
|
65
|
-
|
66
|
-
|
67
|
-
```ruby
|
68
|
-
def self.gene_space
|
69
|
-
{ instrument: { type: 'InstrumentGene', count: 1 },
|
70
|
-
notes: { type: 'NoteGene', count: 16 } }
|
71
|
-
end
|
72
|
-
```
|
62
|
+
You're expected to override this and return a gene space configuration hash or GeneSpace object. It defines the mapping for a hyperdimensional "gene space" so to speak. The above sample definition for the melody class configures each instance to have 16 note genes and 1 instrument gene.
|
73
63
|
|
74
64
|
See the section on [Genes](#genes) for more details.
|
75
65
|
|
76
|
-
|
66
|
+
### EvolvableClass.new_population(keyword_args = {})
|
77
67
|
|
78
68
|
Initializes a new population. Example: `population = Melody.new_population(size: 100)`
|
79
69
|
|
80
|
-
Accepts the same arguments as
|
81
|
-
|
82
|
-
#### .new_instance(population: nil, genes: [], population_index: nil)
|
70
|
+
Accepts the same arguments as [Population.new](#evolvablepopulationnew)
|
83
71
|
|
84
|
-
|
72
|
+
### EvolvableClass.new_instance(population: nil, genes: [], population_index: nil)
|
85
73
|
|
86
|
-
This method is useful for re-initializing instances and populations that have been saved.
|
74
|
+
Initializes a new instance. Accepts a population object, an array of gene objects, and the instance's population index. This method is useful for re-initializing instances and populations that have been saved.
|
87
75
|
|
88
76
|
_It is not recommended that you override this method_ as it is used by Evolvable internals. If you need to customize how your instances are initialized you can override either of the following two "initialize_instance" methods.
|
89
77
|
|
90
|
-
|
78
|
+
### EvolvableClass.initialize_instance
|
91
79
|
|
92
80
|
The default implementation simply delegates to `.new` and is useful for instances with custom initialize methods.
|
93
81
|
|
94
|
-
|
82
|
+
### EvolvableClass#initialize_instance
|
95
83
|
|
96
84
|
Runs after Evolvable finishes building your instance. It's useful for stuff like implementing custom gene initialization logic. For example, the Evolvable Strings web demo (coming soon) uses it to read from a "length gene" and add or remove "char genes" accordingly.
|
97
85
|
|
98
|
-
|
86
|
+
### EvolvableClass#population, #population=
|
99
87
|
|
100
88
|
The population object being used to evolve this instance.
|
101
89
|
|
102
|
-
|
90
|
+
### EvolvableClass#genes, #genes=
|
103
91
|
|
104
92
|
An array of all an instance's genes. You can find specific types of genes with the following two methods.
|
105
93
|
|
106
|
-
|
94
|
+
### EvolvableClass#find_genes(key)
|
107
95
|
|
108
|
-
Returns an array of genes that have the given key. Gene keys are defined in the [.gene_space](
|
96
|
+
Returns an array of genes that have the given key. Gene keys are defined in the [EvolvableClass.gene_space](#evolvableclassgene_space) method. In the Melody example above, the key for the note genes would be `:notes`. The following would return an array of them: `note_genes = melody.find_genes(:notes)`
|
109
97
|
|
110
|
-
|
98
|
+
### EvolvableClass#find_gene(key)
|
111
99
|
|
112
100
|
Returns the first gene with the given key. In the Melody example above, the instrument gene has the key `:instrument` so we might write something like: `instrument_gene = melody.find_gene(instrument)`
|
113
101
|
|
114
|
-
|
102
|
+
### EvolvableClass#population_index, #population_index=
|
115
103
|
|
116
104
|
Returns an instance's population index - an integer representing the order in which it was initialized in a population. It's the most basic way to distinguish instances in a population.
|
117
105
|
|
118
|
-
|
106
|
+
### EvolvableClass#value
|
119
107
|
|
120
|
-
|
108
|
+
You must implement this method. It is used when evaluating instances before undergoing evolution. The above melody example imagines that the melodies have ratings and uses them as the basis for evaluation and selection.
|
121
109
|
|
122
|
-
Technically, this method can return any object that implements Ruby's [Comparable](https://ruby-doc.org/core-2.7.1/Comparable.html). See the section on [Evaluation](#
|
110
|
+
Technically, this method can return any object that implements Ruby's [Comparable](https://ruby-doc.org/core-2.7.1/Comparable.html). See the section on [Evaluation](#evaluation-1) for details.
|
123
111
|
|
124
|
-
|
112
|
+
### Evolvable Hooks
|
125
113
|
|
126
|
-
The following class
|
114
|
+
The following class method hooks can be overridden. The hooks run for each evolution in the following order:
|
127
115
|
|
128
116
|
**.before_evaluation(population)**
|
129
117
|
|
@@ -152,7 +140,7 @@ end
|
|
152
140
|
|
153
141
|
Instances rely on gene objects to compose behaviors. In other words, a gene can be thought of as an object that in some way affects the behavior of an instance. They are used to encapsulate a "sample space" and return a sample outcome when accessed.
|
154
142
|
|
155
|
-
|
143
|
+
### The Evolvable::Gene module
|
156
144
|
|
157
145
|
Gene objects must include the `Evolvable::Gene` module which enables them to undergo evolutionary operations such as crossover and mutation.
|
158
146
|
|
@@ -169,11 +157,9 @@ class NoteGene
|
|
169
157
|
end
|
170
158
|
end
|
171
159
|
```
|
172
|
-
Here, the "sample space" for the NoteGene class has twelve notes, but each
|
160
|
+
Here, the "sample space" for the NoteGene class has twelve notes, but each object will have only one note which is randomly chosen when the "value" method is invoked for the first time. _It is important that the data for a particular gene never change._ Ruby's or-equals operator `||=` is super useful for memoizing gene attributes. It is used above to randomly pick a note only once and return the same note for the lifetime of the object.
|
173
161
|
|
174
|
-
|
175
|
-
|
176
|
-
A melody instance with multiple note genes might use the `NoteGene#value` method to compose the notes of its melody like so: `melody.find_genes(:note).map(&:value)`. Let's keep going with this example and implement the `InstrumentGene` too:
|
162
|
+
A melody instance with multiple note genes might use the `NoteGene#value` method to compose the notes of its melody like so: `melody.find_genes(:note).map(&:value)`. Let's keep humming with the melody example and implement the `InstrumentGene` too:
|
177
163
|
|
178
164
|
```ruby
|
179
165
|
class InstrumentGene
|
@@ -211,76 +197,225 @@ class Melody
|
|
211
197
|
end
|
212
198
|
```
|
213
199
|
|
214
|
-
In this way, instances can express behaviors via genes and even orchestrate interactions between them. Genes can also interact with each other during an instance's initialization process via the [#initialize_instance](#
|
200
|
+
In this way, instances can express behaviors via genes and even orchestrate interactions between them. Genes can also interact with each other during an instance's initialization process via the [EvolvableClass#initialize_instance](#evolvableclassinitialize_instance-1) method
|
201
|
+
|
202
|
+
### The Evolvable::GeneSpace object
|
203
|
+
|
204
|
+
The `Evolvable::GeneSpace` object is responsible for initializing the full set of genes for a particular instance according to the configuration returned by the [EvolvableClass.gene_space](#evolvableclassgene_space) method. It is used by the `Evolvable::Population` to initialize new instances.
|
205
|
+
|
206
|
+
Technically, any object that responds to a `new_genes` method which returns an array of genes for a particular instance can function as a GeneSpace object. Custom implementations will be used if returned by the `.gene_space` method.
|
207
|
+
|
208
|
+
|
209
|
+
## Populations
|
210
|
+
|
211
|
+
The `Evolvable::Population` object is responsible for generating and evolving instances. It orchestrates all the other Evolvable objects to do so.
|
212
|
+
|
213
|
+
### Evolvable::Population.new
|
214
|
+
|
215
|
+
Initializes an Evolvable::Population.
|
215
216
|
|
216
|
-
|
217
|
+
Keyword arguments:
|
217
218
|
|
218
|
-
|
219
|
+
#### evolvable_class
|
220
|
+
Required. Implicitly specified when using EvolvableClass.new_population.
|
221
|
+
#### id, name
|
222
|
+
Both default to `nil`. Not used by Evolvable, but convenient when working with multiple populations.
|
223
|
+
#### size
|
224
|
+
Defaults to `40`. Specifies the number of instances in the population.
|
225
|
+
#### evolutions_count
|
226
|
+
Defaults to `0`. Useful when re-initializing a saved population with instances.
|
227
|
+
#### gene_space
|
228
|
+
Defaults to `evolvable_class.new_gene_space` which uses the [EvolvableClass.gene_space](#evolvableclassgene_space) method
|
229
|
+
#### evolution
|
230
|
+
Defaults to `Evolvable::Evolution.new`. See [evolution](#evolution-1)
|
231
|
+
#### evaluation
|
232
|
+
Defaults to `Evolvable::Evaluation.new`, with a goal of maximizing towards Float::INFINITY. See [evaluation](#evaluation-1)
|
233
|
+
#### instances
|
234
|
+
Defaults to initializing a `size` number of `evolvable_class` instances using the `gene_space` object. Any given instances are assigned, but if given less than `size`, more will be initialized.
|
235
|
+
|
236
|
+
### Evolvable::Population#evolve
|
237
|
+
|
238
|
+
Keyword arguments:
|
239
|
+
|
240
|
+
#### count
|
241
|
+
The number of evolutions to run. Expects a positive integer and Defaults to Float::INFINITY and will therefore run indefinitely unless a `goal_value` is specified.
|
242
|
+
#### goal_value
|
243
|
+
Assigns the goal object's value. Will continue running until any instance's value reaches it. See [evaluation](#evaluation-1)
|
244
|
+
|
245
|
+
### Evolvable::Population#best_instance
|
246
|
+
Returns an instance with the value that is nearest to the goal value.
|
247
|
+
|
248
|
+
### Evolvable::Population#met_goal?
|
249
|
+
Returns true if any instance's value matches the goal value, otherwise false.
|
250
|
+
|
251
|
+
### Evolvable::Population#new_instance
|
252
|
+
Initializes an instance for the population. Note that this method does not add the new instance to its array of instances.
|
253
|
+
|
254
|
+
Keyword arguments:
|
255
|
+
|
256
|
+
#### genes
|
257
|
+
An array of initialized gene objects. Defaults to `[]`
|
258
|
+
#### population_index
|
259
|
+
Defaults to `nil` and expects an integer. See (EvolvableClass#population_index)[#evolvableclasspopulation_index-population_index]
|
260
|
+
|
261
|
+
|
262
|
+
### Population#selection, #selection=
|
263
|
+
The [selection](#selection-1) object.
|
264
|
+
|
265
|
+
### Population#crossover, #crossover=
|
266
|
+
The [crossover](#crossover) object.
|
267
|
+
|
268
|
+
### Population#mutation, #mutation=
|
269
|
+
The [mutation](#mutation-1) object.
|
270
|
+
|
271
|
+
### Population#goal, #goal=
|
272
|
+
The [evaluation](#evaluation-1)'s goal object.
|
219
273
|
|
220
274
|
## Evaluation
|
221
275
|
|
222
|
-
|
276
|
+
For selection to be effective in the context of progressive evolution, there needs to be some way of comparing various instances with each other. In traditional genetic algorithms, this is referred to as the "fitness function". The `Evolvable::Evaluation` object expects instances to define a [EvolvableClass#value](#evolvableclassvalue) method that it uses to evaluate them relative to each other and against a definable goal.
|
223
277
|
|
224
|
-
|
278
|
+
A goal object has a value that can be most easily assigned via an argument to `Evolvable::Population#evolve` like this: `population.evolve(goal_value: 1000)`. Evolvable provides the following goal object implementations and goal value defaults.
|
225
279
|
|
226
|
-
|
280
|
+
### The Evolvable::Goal::Maximize object
|
227
281
|
|
228
|
-
|
282
|
+
Prioritizes instances with greater values. This is the default.
|
229
283
|
|
230
|
-
|
284
|
+
The default goal value is `Float::INFINITY`, but it can be reassigned as anything that implements the Ruby [Comparable](https://ruby-doc.org/core-2.7.1/Comparable.html) module.
|
231
285
|
|
232
|
-
|
286
|
+
### The Evolvable::Goal::Minimize object
|
233
287
|
|
234
|
-
|
288
|
+
Prioritizes instances with lesser values.
|
235
289
|
|
236
|
-
|
290
|
+
The default goal value is `-Float::INFINITY`, but it can be reassigned as anything that implements the Ruby [Comparable](https://ruby-doc.org/core-2.7.1/Comparable.html) module.
|
237
291
|
|
238
|
-
|
292
|
+
### The Evolvable::Goal::Equalize object
|
239
293
|
|
240
|
-
|
294
|
+
Prioritizes instances that equal the goal value.
|
295
|
+
|
296
|
+
The default goal value is `0`, but it can be reassigned as anything that implements the Ruby [Comparable](https://ruby-doc.org/core-2.7.1/Comparable.html) module.
|
297
|
+
|
298
|
+
### Custom Goal Objects
|
299
|
+
|
300
|
+
You can implement custom goal object like so:
|
241
301
|
|
242
|
-
|
302
|
+
```ruby
|
303
|
+
class CustomGoal
|
304
|
+
include Evolvable::Goal
|
243
305
|
|
244
|
-
|
306
|
+
def evaluate(instance)
|
307
|
+
# Required by Evolvable::Evaluation in order to sort instances in preparation for selection.
|
308
|
+
end
|
245
309
|
|
246
|
-
|
310
|
+
def met?(instance)
|
311
|
+
# Used by Evolvable::Population#evolve to stop evolving when the goal value has been reached.
|
312
|
+
end
|
313
|
+
end
|
314
|
+
```
|
315
|
+
|
316
|
+
The goal for a population can be specified via assignment - `population.goal = Evolvable::Goal::Equalize.new` - or by passing an evaluation object when [initializing a population](#evolvablepopulationnew).
|
317
|
+
|
318
|
+
You can intialize the `Evolvable::Evaluation` object with any goal object like this:
|
319
|
+
|
320
|
+
```ruby
|
321
|
+
goal_object = SomeGoal.new(value: 100)
|
322
|
+
Evolvable::Evaluation.new(goal_object)
|
323
|
+
```
|
324
|
+
|
325
|
+
or more succinctly like this:
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
Evolvable::Evaluation.new(:maximize) # Uses default goal value of Float::INFINITY
|
329
|
+
Evolvable::Evaluation.new(maximize: 50) # Sets goal value to 50
|
330
|
+
Evolvable::Evaluation.new(:minimize) # Uses default goal value of -Float::INFINITY
|
331
|
+
Evolvable::Evaluation.new(minimize: 100) # Sets goal value to 100
|
332
|
+
Evolvable::Evaluation.new(:equalize) # Uses default goal value of 0
|
333
|
+
Evolvable::Evaluation.new(equalize: 1000) # Sets goal value to 1000
|
334
|
+
|
335
|
+
```
|
247
336
|
|
248
337
|
## Evolution
|
249
338
|
|
250
|
-
|
339
|
+
After a population's instances are evaluated, they undergo evolution. The default `Evolvable::Evolution` object is composed of selection, crossover, and mutation objects and applies them as operations to the population in that order.
|
340
|
+
|
341
|
+
Populations can be assigned with custom evolution objects. The only necessary dependency for evolution objects is that they implement the `#call` method which accepts a population as the first argument. Population objects also expect evolution objects to define a getter and setter for selection, crossover, and mutation, but these methods are simply for ease-of-use and not necessary.
|
342
|
+
|
343
|
+
### Evolvable::Evolution.new
|
251
344
|
|
252
|
-
|
345
|
+
Initializes a new evolution object.
|
253
346
|
|
254
|
-
|
347
|
+
Keyword arguments:
|
348
|
+
|
349
|
+
#### selection
|
350
|
+
The default is `Selection.new`
|
351
|
+
#### crossover
|
352
|
+
The default is `GeneCrossover.new`
|
353
|
+
#### mutation
|
354
|
+
The default is `Mutation.new`
|
255
355
|
|
256
356
|
## Selection
|
257
357
|
|
258
|
-
|
358
|
+
The selection process assumes that the population's instances have already been sorted by the `Evaluation` object. It leaves only a select number of instances in a given population's instances array.
|
359
|
+
|
360
|
+
Custom selection objects must implement the `#call` method which accepts the population as the first object.
|
361
|
+
|
362
|
+
### Evolvable::Selection.new
|
259
363
|
|
260
|
-
|
364
|
+
Initializes a new selection object.
|
261
365
|
|
262
|
-
|
366
|
+
Keyword arguments:
|
367
|
+
|
368
|
+
#### size
|
369
|
+
The number of instances to select from each generation from which to perform crossover and generate or "breed" the next generation. The number of parents The default is 2.
|
263
370
|
|
264
371
|
## Crossover
|
265
372
|
|
266
|
-
|
373
|
+
Generates new instances by combining the genes of selected instances. You can think of it as a mixing of parent genes from one generation to produce a next generation.
|
374
|
+
|
375
|
+
Custom crossover objects must implement the `#call` method which accepts the population as the first object.
|
267
376
|
|
268
|
-
|
377
|
+
### The Evolvable::GeneCrossover object
|
269
378
|
|
270
|
-
|
379
|
+
Enables gene types to define crossover behaviors. Each gene class can implement a unique behavior for crossover by overriding the following default implementation which mirrors the behavior of `Evolvable::UniformCrossover`
|
380
|
+
|
381
|
+
```ruby
|
382
|
+
def self.crossover(gene_a, gene_b)
|
383
|
+
[gene_a, gene_b].sample
|
384
|
+
end
|
385
|
+
```
|
271
386
|
|
272
|
-
|
387
|
+
### The Evolvable::UniformCrossover object
|
273
388
|
|
274
|
-
|
389
|
+
Randomly chooses a gene from one of the parents for each gene position.
|
275
390
|
|
276
|
-
|
391
|
+
### The Evolvable::PointCrossover object
|
277
392
|
|
278
|
-
|
393
|
+
Supports single and multi-point crossover. The default is single-point crossover via a `points_count` of 1 which can be changed on an existing population (`population.crossover.points_count = 5`) or during initialization (`Evolvable::PointCrossover.new(5)`)
|
279
394
|
|
280
395
|
## Mutation
|
281
396
|
|
282
|
-
|
397
|
+
Mutation serves the role of increasing genetic variation, especially when a population's instances are small in number and mostly homogeneous. When an instance undergoes a mutation, it means that one of its existing genes is replaced with a newly initialized gene. Using the language from the [section on genes](genes), a gene mutation invokes a new outcome from the gene's sample space.
|
283
398
|
|
284
|
-
|
399
|
+
### Evolvable::Mutation.new
|
400
|
+
|
401
|
+
Initializes a new mutation object.
|
402
|
+
|
403
|
+
Keyword arguments:
|
404
|
+
|
405
|
+
#### probability
|
406
|
+
The probability that a particular instance undergoes a mutation. By default, the probability is 0.03 which translates to 3%. If initialized with a `rate`, the probability will be 1 which means all genes _can_ undergo mutation, but actual gene mutations will be subject to the given mutation rate.
|
407
|
+
#### rate
|
408
|
+
the rate at which individual genes mutate. The default rate is 0 which, when combined with a non-zero `probability` (the default), means that one gene for each instance that undergoes mutation will change. If a rate is given, but no `probability` is given, then the `probability` will bet set to 1 which always defers to the mutation rate.
|
409
|
+
|
410
|
+
To summarize, the `probability` represents the chance of mutation on the instance level and the `rate` represents the chance on the gene level. The `probability` and `rate` can be any number from 0 to 1. When the `probability` is 0, no mutation will ever happen. When the `probability` is not 0 but the rate is 0, then any instance that undergoes mutation will only receive one mutant gene. If the rate is not 0, then if an instance has been chosen to undergo mutation, each of its genes will mutate with a probability as defined by the `rate`.
|
411
|
+
|
412
|
+
Example Initializations:
|
413
|
+
|
414
|
+
```ruby
|
415
|
+
Evolvable::Mutation.new # Approximately 3% of instances will receive one mutant gene
|
416
|
+
Evolvable::Mutation.new(probability: 0.5) # Approximately 50% of instances will receive one mutant gene
|
417
|
+
Evolvable::Mutation.new(rate: 0.03) # Approximately 3% of all genes in the population will mutate.
|
418
|
+
Evolvable::Mutation.new(probability: 0.3, rate: 0.03) # Approximately 30% of instances will have approximately 3% of their genes mutated.
|
419
|
+
```
|
285
420
|
|
286
|
-
|
421
|
+
Custom mutation objects must implement the `#call` method which accepts the population as the first object.
|
data/lib/evolvable/evaluation.rb
CHANGED
data/lib/evolvable/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: evolvable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Ruzicka
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|