darwinning 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +1 -1
- data/darwinning-0.0.1.gem +0 -0
- data/darwinning-0.0.2.gem +0 -0
- data/darwinning-0.0.3.gem +0 -0
- data/darwinning-0.1.0.gem +0 -0
- data/darwinning-0.1.1.gem +0 -0
- data/darwinning.gemspec +18 -0
- data/lib/darwinning.rb +4 -2
- data/lib/darwinning/evolution_types/mutation.rb +2 -2
- data/lib/darwinning/monkey_patch.rb +7 -0
- data/lib/darwinning/organism.rb +2 -2
- data/lib/darwinning/population.rb +78 -28
- data/lib/darwinning/version.rb +1 -1
- data/spec/darwinning_spec.rb +3 -3
- data/spec/gene_spec.rb +3 -3
- data/spec/organism_spec.rb +4 -4
- data/spec/population_spec.rb +9 -1
- metadata +19 -14
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 00597c08fc47e731a886be9e68771c1e5a1d5ddc
|
4
|
+
data.tar.gz: d6f8e46f456c6c9734fef044cada94ebe951b8f4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8e0963dc3e6dd57ad76aa25565f1714cfcd74449c01d72bd9dadc9161715c4395b16bef6ee92e6c452fe79ea7ab1ba2c539a55127397264fd823f5081e6b8dbd
|
7
|
+
data.tar.gz: 5fdf2aa0bebd1bed384489440e415611f3560711913ccf7c140a0c4651e703ad4b86f6b88334fd45abae32e3ae47016567b744b926bef2d2b809932b212a783c
|
data/README.md
CHANGED
@@ -123,4 +123,4 @@ Check out the `/examples` folder for more examples. That seems like a good place
|
|
123
123
|
* [Dave Schwantes](https://github.com/dorkrawk "dorkrawk")
|
124
124
|
|
125
125
|
### With help from:
|
126
|
-
[lots of great contributers](https://github.com/dorkrawk/darwinning/graphs/contributors)
|
126
|
+
[lots of great contributers](https://github.com/dorkrawk/darwinning/graphs/contributors) and work based on forks from: [Nanosim-LIG](https://github.com/Nanosim-LIG)
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/darwinning.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "./lib/darwinning/version"
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'darwinning'
|
5
|
+
s.version = Darwinning::VERSION
|
6
|
+
|
7
|
+
s.authors = ['Dave Schwantes']
|
8
|
+
s.email = 'dave.schwantes@gmail.com'
|
9
|
+
s.summary = 'A Ruby gem to aid in the use of genetic algorithms.'
|
10
|
+
s.description = 'Darwinning provides tools to build genetic algorithm solutions using a Gene, Organism, and Population structure.'
|
11
|
+
s.homepage = 'https://github.com/dorkrawk/darwinning'
|
12
|
+
|
13
|
+
|
14
|
+
s.files = Dir["{lib}/**/*", "[A-Z]*"] - ["Gemfile.lock"]
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
|
17
|
+
s.test_files = Dir.glob("{test,spec,features}/**/*.rb")
|
18
|
+
end
|
data/lib/darwinning.rb
CHANGED
@@ -4,6 +4,8 @@ require_relative 'darwinning/evolution_types/mutation'
|
|
4
4
|
require_relative 'darwinning/evolution_types/reproduction'
|
5
5
|
require_relative 'darwinning/population'
|
6
6
|
require_relative 'darwinning/config'
|
7
|
+
require_relative 'darwinning/monkey_patch'
|
8
|
+
|
7
9
|
|
8
10
|
module Darwinning
|
9
11
|
extend Config
|
@@ -13,7 +15,7 @@ module Darwinning
|
|
13
15
|
gene_ranges.map { |k,v| Gene.new(name: k, value_range: v) }
|
14
16
|
end
|
15
17
|
|
16
|
-
def base.build_population(fitness_goal, population_size = 10, generations_limit = 100,
|
18
|
+
def base.build_population(fitness_goal, population_size = 10, generations_limit = 100,
|
17
19
|
evolution_types = Population::DEFAULT_EVOLUTION_TYPES)
|
18
20
|
Population.new(organism: self, population_size: population_size,
|
19
21
|
generations_limit: generations_limit, fitness_goal: fitness_goal,
|
@@ -61,4 +63,4 @@ module Darwinning
|
|
61
63
|
end
|
62
64
|
gt
|
63
65
|
end
|
64
|
-
end
|
66
|
+
end
|
@@ -20,7 +20,7 @@ module Darwinning
|
|
20
20
|
|
21
21
|
def mutate(members)
|
22
22
|
members.map do |member|
|
23
|
-
if
|
23
|
+
if rand < mutation_rate
|
24
24
|
re_express_random_genotype(member)
|
25
25
|
else
|
26
26
|
member
|
@@ -30,7 +30,7 @@ module Darwinning
|
|
30
30
|
|
31
31
|
# Selects a random genotype from the organism and re-expresses its gene
|
32
32
|
def re_express_random_genotype(member)
|
33
|
-
random_index = (
|
33
|
+
random_index = rand(member.genotypes.length - 1)
|
34
34
|
gene = member.genes[random_index]
|
35
35
|
|
36
36
|
if member.class.superclass == Darwinning::Organism
|
data/lib/darwinning/organism.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
module Darwinning
|
2
2
|
class Population
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
attr_reader :members, :generations_limit, :fitness_goal,
|
4
|
+
attr_reader :members, :generations_limit, :fitness_goal, :fitness_objective,
|
7
5
|
:organism, :population_size, :generation,
|
8
6
|
:evolution_types, :history
|
9
7
|
|
@@ -16,6 +14,7 @@ module Darwinning
|
|
16
14
|
@organism = options.fetch(:organism)
|
17
15
|
@population_size = options.fetch(:population_size)
|
18
16
|
@fitness_goal = options.fetch(:fitness_goal)
|
17
|
+
@fitness_objective = options.fetch(:fitness_objective, :nullify) # :nullify, :maximize, :minimize
|
19
18
|
@generations_limit = options.fetch(:generations_limit, 0)
|
20
19
|
@evolution_types = options.fetch(:evolution_types, DEFAULT_EVOLUTION_TYPES)
|
21
20
|
@members = []
|
@@ -23,7 +22,6 @@ module Darwinning
|
|
23
22
|
@history = []
|
24
23
|
|
25
24
|
build_population(@population_size)
|
26
|
-
@history << @members
|
27
25
|
end
|
28
26
|
|
29
27
|
def build_population(population_size)
|
@@ -41,16 +39,19 @@ module Darwinning
|
|
41
39
|
def set_members_fitness!(fitness_values)
|
42
40
|
throw "Invaid number of fitness values for population size" if fitness_values.size != members.size
|
43
41
|
members.to_enum.each_with_index { |m, i| m.fitness = fitness_values[i] }
|
42
|
+
sort_members
|
44
43
|
end
|
45
44
|
|
46
45
|
def make_next_generation!
|
47
46
|
verify_population_size_is_positive!
|
47
|
+
sort_members
|
48
|
+
@history << @members
|
48
49
|
|
49
50
|
new_members = []
|
50
51
|
|
51
52
|
until new_members.length >= members.length
|
52
|
-
m1 = weighted_select
|
53
|
-
m2 = weighted_select
|
53
|
+
m1 = weighted_select
|
54
|
+
m2 = weighted_select
|
54
55
|
|
55
56
|
new_members += apply_pairwise_evolutions(m1, m2)
|
56
57
|
end
|
@@ -59,6 +60,7 @@ module Darwinning
|
|
59
60
|
new_members.pop if new_members.length > members.length
|
60
61
|
|
61
62
|
@members = apply_non_pairwise_evolutions(new_members)
|
63
|
+
sort_members
|
62
64
|
@history << @members
|
63
65
|
@generation += 1
|
64
66
|
end
|
@@ -66,14 +68,18 @@ module Darwinning
|
|
66
68
|
def evolution_over?
|
67
69
|
# check if the fitness goal or generation limit has been met
|
68
70
|
if generations_limit > 0
|
69
|
-
generation == generations_limit ||
|
71
|
+
generation == generations_limit || goal_attained?
|
70
72
|
else
|
71
|
-
|
73
|
+
goal_attained?
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
75
77
|
def best_member
|
76
|
-
@members.
|
78
|
+
@members.first
|
79
|
+
end
|
80
|
+
|
81
|
+
def best_each_generation
|
82
|
+
@history.map(&:first)
|
77
83
|
end
|
78
84
|
|
79
85
|
def size
|
@@ -91,6 +97,28 @@ module Darwinning
|
|
91
97
|
|
92
98
|
private
|
93
99
|
|
100
|
+
def goal_attained?
|
101
|
+
case @fitness_objective
|
102
|
+
when :nullify
|
103
|
+
best_member.fitness.abs <= fitness_goal
|
104
|
+
when :maximize
|
105
|
+
best_member.fitness >= fitness_goal
|
106
|
+
else
|
107
|
+
best_member.fitness <= fitness_goal
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def sort_members
|
112
|
+
case @fitness_objective
|
113
|
+
when :nullify
|
114
|
+
@members = @members.sort_by { |m| m.fitness ? m.fitness.abs : m.fitness }
|
115
|
+
when :maximize
|
116
|
+
@members = @members.sort_by { |m| m.fitness }.reverse
|
117
|
+
else
|
118
|
+
@members = @members.sort_by { |m| m.fitness }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
94
122
|
def verify_population_size_is_positive!
|
95
123
|
unless @population_size.positive?
|
96
124
|
raise "Population size must be a positive number!"
|
@@ -99,7 +127,7 @@ module Darwinning
|
|
99
127
|
|
100
128
|
def build_member
|
101
129
|
member = organism.new
|
102
|
-
unless member.class
|
130
|
+
unless member.class < Darwinning::Organism
|
103
131
|
member.class.genes.each do |gene|
|
104
132
|
gene_expression = gene.express
|
105
133
|
member.send("#{gene.name}=", gene_expression)
|
@@ -108,27 +136,49 @@ module Darwinning
|
|
108
136
|
member
|
109
137
|
end
|
110
138
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
(m.fitness - fitness_goal)
|
116
|
-
|
117
|
-
|
139
|
+
def compute_normalized_fitness(membs=members)
|
140
|
+
normalized_fitness = nil
|
141
|
+
return membs.collect { |m| [1.0/membs.length, m] } if membs.first.fitness == membs.last.fitness
|
142
|
+
if @fitness_objective == :nullify
|
143
|
+
normalized_fitness = membs.collect { |m| [ m.fitness.abs <= fitness_goal ? Float::INFINITY : 1.0/(m.fitness.abs - fitness_goal), m] }
|
144
|
+
else
|
145
|
+
if @fitness_objective == :maximize
|
146
|
+
if fitness_goal == Float::INFINITY then
|
147
|
+
#assume goal to be at twice the maximum distance between fitness
|
148
|
+
goal = membs.first.fitness + ( membs.first.fitness - membs.last.fitness )
|
149
|
+
else
|
150
|
+
goal = fitness_goal
|
151
|
+
end
|
152
|
+
normalized_fitness = membs.collect { |m| [ m.fitness >= goal ? Float::INFINITY : 1.0/(goal - m.fitness), m] }
|
153
|
+
else
|
154
|
+
if fitness_goal == -Float::INFINITY then
|
155
|
+
goal = membs.first.fitness - ( membs.last.fitness - membs.first.fitness )
|
156
|
+
else
|
157
|
+
goal = fitness_goal
|
158
|
+
end
|
159
|
+
normalized_fitness = membs.collect { |m| [ m.fitness <= goal ? Float::INFINITY : 1.0/(m.fitness - goal), m] }
|
160
|
+
end
|
118
161
|
end
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
weighted_members.reverse! # In order to pop from the end we need the lowest ranked first
|
124
|
-
pick_sum = 0
|
125
|
-
|
126
|
-
until pick_sum > pick do
|
127
|
-
selected_member = weighted_members.pop
|
128
|
-
pick_sum += selected_member[1]
|
162
|
+
if normalized_fitness.first[0] == Float::INFINITY then
|
163
|
+
normalized_fitness.collect! { |m|
|
164
|
+
m[0] == Float::INFINITY ? [1.0, m[1]] : [0.0, m[1]]
|
165
|
+
}
|
129
166
|
end
|
167
|
+
sum = normalized_fitness.collect(&:first).inject(0.0, :+)
|
168
|
+
normalized_fitness.collect { |m| [m[0]/sum, m[1]] }
|
169
|
+
end
|
130
170
|
|
131
|
-
|
171
|
+
def weighted_select(membs=members)
|
172
|
+
normalized_fitness = compute_normalized_fitness
|
173
|
+
normalized_cumulative_sums = []
|
174
|
+
normalized_cumulative_sums[0] = normalized_fitness[0]
|
175
|
+
(1...normalized_fitness.length).each { |i|
|
176
|
+
normalized_cumulative_sums[i] = [ normalized_cumulative_sums[i-1][0] + normalized_fitness[i][0], normalized_fitness[i][1] ]
|
177
|
+
}
|
178
|
+
|
179
|
+
normalized_cumulative_sums.last[0] = 1.0
|
180
|
+
cut = rand
|
181
|
+
return normalized_cumulative_sums.find { |e| cut < e[0] }[1]
|
132
182
|
end
|
133
183
|
|
134
184
|
def apply_pairwise_evolutions(m1, m2)
|
data/lib/darwinning/version.rb
CHANGED
data/spec/darwinning_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative 'spec_helper'
|
2
2
|
|
3
3
|
describe Darwinning do
|
4
4
|
let(:triple_pop) { NewTriple.build_population(0, 20, 1000) }
|
@@ -18,7 +18,7 @@ describe Darwinning do
|
|
18
18
|
manual_fitness = (a_triple.first_digit + a_triple.second_digit + a_triple.third_digit - 15).abs
|
19
19
|
|
20
20
|
expect(a_triple.fitness).to eq manual_fitness
|
21
|
-
end
|
21
|
+
end
|
22
22
|
end
|
23
23
|
|
24
24
|
describe '#genes' do
|
@@ -53,7 +53,7 @@ describe Darwinning do
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
describe 'population member' do
|
56
|
+
describe 'population member' do
|
57
57
|
it 'is of the parent class' do
|
58
58
|
expect(triple_pop_member.class.name).to eq "NewTriple"
|
59
59
|
end
|
data/spec/gene_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative 'spec_helper'
|
2
2
|
|
3
3
|
describe Darwinning::Gene do
|
4
4
|
let(:digit) { Darwinning::Gene.new(name: "digit", value_range: (0..9)) }
|
@@ -10,7 +10,7 @@ describe Darwinning::Gene do
|
|
10
10
|
units: "o'clock"
|
11
11
|
)
|
12
12
|
}
|
13
|
-
|
13
|
+
|
14
14
|
it "name should be set" do
|
15
15
|
expect(digit.name).to eq "digit"
|
16
16
|
end
|
@@ -26,4 +26,4 @@ describe Darwinning::Gene do
|
|
26
26
|
it "units should be set" do
|
27
27
|
expect(day_hour.units).to eq "o'clock"
|
28
28
|
end
|
29
|
-
end
|
29
|
+
end
|
data/spec/organism_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative 'spec_helper'
|
2
2
|
|
3
3
|
describe Darwinning::Organism do
|
4
4
|
let(:org) { Darwinning::Organism.new }
|
@@ -16,8 +16,8 @@ describe Darwinning::Organism do
|
|
16
16
|
expect(org.genotypes).to be {}
|
17
17
|
end
|
18
18
|
|
19
|
-
it "fitness should default to
|
20
|
-
expect(org.fitness).to eq
|
19
|
+
it "fitness should default to nil" do
|
20
|
+
expect(org.fitness).to eq nil
|
21
21
|
end
|
22
22
|
|
23
23
|
it "child class should set name" do
|
@@ -32,4 +32,4 @@ describe Darwinning::Organism do
|
|
32
32
|
expect(triple.genotypes.length).to eq 3
|
33
33
|
end
|
34
34
|
|
35
|
-
end
|
35
|
+
end
|
data/spec/population_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative 'spec_helper'
|
2
2
|
|
3
3
|
describe Darwinning::Population do
|
4
4
|
let(:pop_triple) {
|
@@ -58,4 +58,12 @@ describe Darwinning::Population do
|
|
58
58
|
|
59
59
|
end
|
60
60
|
|
61
|
+
describe "#best_each_generation" do
|
62
|
+
|
63
|
+
it "should show the best member from each generations members" do
|
64
|
+
pop_triple.evolve!
|
65
|
+
expect(pop_triple.best_each_generation.last).to eq pop_triple.best_member
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
61
69
|
end
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: darwinning
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Dave Schwantes
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2017-09-15 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description: Darwinning provides tools to build genetic algorithm solutions using
|
15
14
|
a Gene, Organism, and Population structure.
|
@@ -18,18 +17,25 @@ executables: []
|
|
18
17
|
extensions: []
|
19
18
|
extra_rdoc_files: []
|
20
19
|
files:
|
20
|
+
- Gemfile
|
21
|
+
- README.md
|
22
|
+
- Rakefile
|
23
|
+
- darwinning-0.0.1.gem
|
24
|
+
- darwinning-0.0.2.gem
|
25
|
+
- darwinning-0.0.3.gem
|
26
|
+
- darwinning-0.1.0.gem
|
27
|
+
- darwinning-0.1.1.gem
|
28
|
+
- darwinning.gemspec
|
29
|
+
- lib/darwinning.rb
|
21
30
|
- lib/darwinning/config.rb
|
31
|
+
- lib/darwinning/evolution_types.rb
|
22
32
|
- lib/darwinning/evolution_types/mutation.rb
|
23
33
|
- lib/darwinning/evolution_types/reproduction.rb
|
24
|
-
- lib/darwinning/evolution_types.rb
|
25
34
|
- lib/darwinning/gene.rb
|
35
|
+
- lib/darwinning/monkey_patch.rb
|
26
36
|
- lib/darwinning/organism.rb
|
27
37
|
- lib/darwinning/population.rb
|
28
38
|
- lib/darwinning/version.rb
|
29
|
-
- lib/darwinning.rb
|
30
|
-
- Gemfile
|
31
|
-
- Rakefile
|
32
|
-
- README.md
|
33
39
|
- spec/classes/chimps.rb
|
34
40
|
- spec/classes/new_single.rb
|
35
41
|
- spec/classes/new_triple.rb
|
@@ -43,27 +49,26 @@ files:
|
|
43
49
|
- spec/spec_helper.rb
|
44
50
|
homepage: https://github.com/dorkrawk/darwinning
|
45
51
|
licenses: []
|
52
|
+
metadata: {}
|
46
53
|
post_install_message:
|
47
54
|
rdoc_options: []
|
48
55
|
require_paths:
|
49
56
|
- lib
|
50
57
|
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
58
|
requirements:
|
53
|
-
- -
|
59
|
+
- - ">="
|
54
60
|
- !ruby/object:Gem::Version
|
55
61
|
version: '0'
|
56
62
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
63
|
requirements:
|
59
|
-
- -
|
64
|
+
- - ">="
|
60
65
|
- !ruby/object:Gem::Version
|
61
66
|
version: '0'
|
62
67
|
requirements: []
|
63
68
|
rubyforge_project:
|
64
|
-
rubygems_version:
|
69
|
+
rubygems_version: 2.4.5
|
65
70
|
signing_key:
|
66
|
-
specification_version:
|
71
|
+
specification_version: 4
|
67
72
|
summary: A Ruby gem to aid in the use of genetic algorithms.
|
68
73
|
test_files:
|
69
74
|
- spec/classes/chimps.rb
|