darwinning 0.0.2 → 0.0.3
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.
- data/Gemfile +12 -0
- data/README.md +27 -17
- data/lib/darwinning.rb +2 -1
- data/lib/darwinning/config.rb +1 -1
- data/lib/darwinning/evolution_types.rb +6 -0
- data/lib/darwinning/evolution_types/mutation.rb +41 -0
- data/lib/darwinning/evolution_types/reproduction.rb +34 -0
- data/lib/darwinning/gene.rb +12 -10
- data/lib/darwinning/organism.rb +4 -9
- data/lib/darwinning/population.rb +57 -55
- data/lib/darwinning/version.rb +2 -2
- data/spec/classes/triple.rb +13 -0
- data/{test → spec}/darwinning_spec.rb +34 -30
- metadata +10 -4
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -27,9 +27,9 @@ class Triple < Darwinning::Organism
|
|
27
27
|
|
28
28
|
@name = "Triple"
|
29
29
|
@genes = [
|
30
|
-
Darwinning::Gene.new("first digit", (0..9)),
|
31
|
-
Darwinning::Gene.new("second digit", (0..9)),
|
32
|
-
Darwinning::Gene.new("third digit", (0..9))
|
30
|
+
Darwinning::Gene.new(name: "first digit", value_range: (0..9)),
|
31
|
+
Darwinning::Gene.new(name: "second digit", value_range: (0..9)),
|
32
|
+
Darwinning::Gene.new(name: "third digit", value_range: (0..9))
|
33
33
|
]
|
34
34
|
|
35
35
|
def fitness
|
@@ -38,7 +38,10 @@ class Triple < Darwinning::Organism
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
p = Darwinning::Population.new(
|
41
|
+
p = Darwinning::Population.new(
|
42
|
+
organism: Triple, population_size: 10,
|
43
|
+
fitness_goal: 0, generations_limit: 100
|
44
|
+
)
|
42
45
|
p.evolve!
|
43
46
|
|
44
47
|
p.best_member.nice_print # prints the member representing the solution
|
@@ -57,22 +60,25 @@ class Cookie < Darwinning::Organism
|
|
57
60
|
|
58
61
|
@name = "Chocolate Chip Cookie"
|
59
62
|
@genes = [
|
60
|
-
Darwinning::Gene.new("white sugar", (0..1),
|
61
|
-
Darwinning::Gene.new("brown sugar", (0..1),
|
62
|
-
Darwinning::Gene.new("flour", (0..3),
|
63
|
-
Darwinning::Gene.new("eggs", (0..3)),
|
64
|
-
Darwinning::Gene.new("baking powder", (0..2),
|
65
|
-
Darwinning::Gene.new("salt", (0..2),
|
66
|
-
Darwinning::Gene.new("butter", (0..2),
|
67
|
-
Darwinning::Gene.new("vanilla extract", (0..2),
|
68
|
-
Darwinning::Gene.new("chocolate chips", (0..20),
|
69
|
-
Darwinning::Gene.new("oven temp", (300..400),
|
70
|
-
Darwinning::Gene.new("cook time", (5..20),
|
63
|
+
Darwinning::Gene.new(name: "white sugar", value_range: (0..1), units: "cup"),
|
64
|
+
Darwinning::Gene.new(name: "brown sugar", value_range: (0..1), units: "cup"),
|
65
|
+
Darwinning::Gene.new(name: "flour", value_range: (0..3), units: "cup"),
|
66
|
+
Darwinning::Gene.new(name: "eggs", value_range: (0..3)),
|
67
|
+
Darwinning::Gene.new(name: "baking powder", value_range: (0..2), units: "teaspoon"),
|
68
|
+
Darwinning::Gene.new(name: "salt", value_range: (0..2), units: "teaspoon"),
|
69
|
+
Darwinning::Gene.new(name: "butter", value_range: (0..2), units: "cup"),
|
70
|
+
Darwinning::Gene.new(name: "vanilla extract", value_range: (0..2), units: "teaspoon"),
|
71
|
+
Darwinning::Gene.new(name: "chocolate chips", value_range: (0..20), units: "ounce"),
|
72
|
+
Darwinning::Gene.new(name: "oven temp", value_range: (300..400), units: "degrees F"),
|
73
|
+
Darwinning::Gene.new(name: "cook time", value_range: (5..20), units: "minute")
|
71
74
|
]
|
72
75
|
|
73
76
|
end
|
74
77
|
|
75
|
-
p = Darwinning::Population.new(
|
78
|
+
p = Darwinning::Population.new(
|
79
|
+
organism: Cookie, population_size: 10,
|
80
|
+
fitness_goal: 5, generations_limit: 100
|
81
|
+
)
|
76
82
|
|
77
83
|
first_gen_ratings = [1.5, 4, 3, 3.5, 2, 1, 1.5, 3, 2.5, 0.5]
|
78
84
|
p.set_members_fitness!(first_gen_ratings)
|
@@ -98,4 +104,8 @@ end
|
|
98
104
|
```
|
99
105
|
|
100
106
|
## Built by:
|
101
|
-
* [Dave Schwantes](https://github.com/dorkrawk "dorkrawk")
|
107
|
+
* [Dave Schwantes](https://github.com/dorkrawk "dorkrawk")
|
108
|
+
|
109
|
+
### With help from:
|
110
|
+
* [Cameron Dutro](https://github.com/camertron "camertron")
|
111
|
+
* [Maurizio Del Corno](https://github.com/druzn3k "druzn3k")
|
data/lib/darwinning.rb
CHANGED
data/lib/darwinning/config.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Darwinning
|
2
|
+
module EvolutionTypes
|
3
|
+
|
4
|
+
class Mutation
|
5
|
+
attr_reader :mutation_rate
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@mutation_rate = options.fetch(:mutation_rate, 0.0)
|
9
|
+
end
|
10
|
+
|
11
|
+
def evolve(members)
|
12
|
+
mutate(members)
|
13
|
+
end
|
14
|
+
|
15
|
+
def pairwise?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def mutate(members)
|
22
|
+
members.map do |member|
|
23
|
+
if (0..100).to_a.sample < mutation_rate * 100
|
24
|
+
re_express_random_genotype(member)
|
25
|
+
else
|
26
|
+
member
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Selects a random genotype from the organism and re-expresses its gene
|
32
|
+
def re_express_random_genotype(member)
|
33
|
+
random_index = (0..member.genotypes.length - 1).to_a.sample
|
34
|
+
new_gene = member.genes[random_index].express
|
35
|
+
member.genotypes[random_index] = member.genes[random_index].express
|
36
|
+
member
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Darwinning
|
2
|
+
module EvolutionTypes
|
3
|
+
|
4
|
+
class Reproduction
|
5
|
+
def evolve(organism, m1, m2)
|
6
|
+
sexytimes(organism, m1, m2)
|
7
|
+
end
|
8
|
+
|
9
|
+
def pairwise?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def sexytimes(organism, m1, m2)
|
16
|
+
genotypes1 = []
|
17
|
+
genotypes2 = []
|
18
|
+
|
19
|
+
m1.genotypes.zip(m2.genotypes).each do |g|
|
20
|
+
if m1.genotypes.index(g[0]) % 2 == 0
|
21
|
+
genotypes1 << g[0]
|
22
|
+
genotypes2 << g[1]
|
23
|
+
else
|
24
|
+
genotypes1 << g[1]
|
25
|
+
genotypes2 << g[0]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
[organism.new(genotypes1), organism.new(genotypes2)]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/darwinning/gene.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
1
|
module Darwinning
|
2
|
-
class Gene
|
3
|
-
attr_accessor :name, :value, :value_range, :invalid_values, :units
|
4
2
|
|
5
|
-
|
3
|
+
class Gene
|
4
|
+
attr_accessor :name, :value_range, :invalid_values, :units
|
5
|
+
attr_accessor :value
|
6
6
|
|
7
|
-
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
7
|
+
def initialize(options = {})
|
8
|
+
@name = options.fetch(:name, '')
|
9
|
+
@value_range = Array(options.fetch(:value_range, []))
|
10
|
+
@invalid_values = Array(options.fetch(:invalid_values, []))
|
11
|
+
@units = options.fetch(:units, '')
|
11
12
|
end
|
12
13
|
|
13
14
|
def express
|
14
|
-
(
|
15
|
+
(value_range - invalid_values).sample
|
15
16
|
end
|
16
17
|
|
17
18
|
def is_valid_value?(value)
|
18
|
-
|
19
|
+
value_range.include?(value) && !invalid_values.include?(value)
|
19
20
|
end
|
20
21
|
end
|
21
|
-
|
22
|
+
|
23
|
+
end
|
data/lib/darwinning/organism.rb
CHANGED
@@ -26,8 +26,8 @@ module ClassLevelInheritableAttributes
|
|
26
26
|
end
|
27
27
|
|
28
28
|
module Darwinning
|
29
|
-
class Organism
|
30
29
|
|
30
|
+
class Organism
|
31
31
|
include ClassLevelInheritableAttributes
|
32
32
|
inheritable_attributes :genes, :name
|
33
33
|
attr_accessor :genotypes, :fitness, :name, :genes
|
@@ -45,14 +45,8 @@ module Darwinning
|
|
45
45
|
else
|
46
46
|
@genotypes = genotypes
|
47
47
|
end
|
48
|
-
@fitness = -1
|
49
|
-
end
|
50
48
|
|
51
|
-
|
52
|
-
def mutate!
|
53
|
-
random_index = (0..@genotypes.length-1).to_a.sample
|
54
|
-
@genotypes[random_index] = self.class.genes[random_index].express
|
55
|
-
self
|
49
|
+
@fitness = -1
|
56
50
|
end
|
57
51
|
|
58
52
|
def nice_print
|
@@ -69,4 +63,5 @@ module Darwinning
|
|
69
63
|
self.class.genes
|
70
64
|
end
|
71
65
|
end
|
72
|
-
|
66
|
+
|
67
|
+
end
|
@@ -1,23 +1,30 @@
|
|
1
1
|
module Darwinning
|
2
2
|
|
3
3
|
class Population
|
4
|
-
attr_accessor :members, :
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
attr_accessor :members, :generations_limit, :fitness_goal
|
5
|
+
attr_accessor :organism, :generation, :population_size
|
6
|
+
attr_accessor :evolution_types
|
7
|
+
|
8
|
+
DEFAULT_EVOLUTION_TYPES = [
|
9
|
+
Darwinning::EvolutionTypes::Reproduction.new,
|
10
|
+
Darwinning::EvolutionTypes::Mutation.new(mutation_rate: 0.10)
|
11
|
+
]
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
@organism = options.fetch(:organism)
|
15
|
+
@population_size = options.fetch(:population_size)
|
16
|
+
@fitness_goal = options.fetch(:fitness_goal)
|
17
|
+
@generations_limit = options.fetch(:generations_limit, 0)
|
18
|
+
@evolution_types = options.fetch(:evolution_types, DEFAULT_EVOLUTION_TYPES)
|
12
19
|
@members = []
|
13
20
|
@generation = 0 # initial population is generation 0
|
14
21
|
|
15
|
-
build_population(population_size)
|
22
|
+
build_population(@population_size)
|
16
23
|
end
|
17
24
|
|
18
25
|
def build_population(population_size)
|
19
26
|
population_size.times do |i|
|
20
|
-
@members <<
|
27
|
+
@members << organism.new
|
21
28
|
end
|
22
29
|
end
|
23
30
|
|
@@ -27,32 +34,15 @@ module Darwinning
|
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
30
|
-
def crossover(m1, m2)
|
31
|
-
genotypes1 = []
|
32
|
-
genotypes2 = []
|
33
|
-
|
34
|
-
m1.genotypes.zip(m2.genotypes).each do |g|
|
35
|
-
if m1.genotypes.index(g[0]) % 2 == 0
|
36
|
-
genotypes1 << g[0]
|
37
|
-
genotypes2 << g[1]
|
38
|
-
else
|
39
|
-
genotypes1 << g[1]
|
40
|
-
genotypes2 << g[0]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
[@organism.new(genotypes1), @organism.new(genotypes2)]
|
45
|
-
end
|
46
|
-
|
47
|
-
def sexytimes(m1, m2)
|
48
|
-
crossover(m1, m2)
|
49
|
-
end
|
50
|
-
|
51
37
|
def weighted_select(members)
|
52
38
|
e = 0.01
|
53
39
|
fitness_sum = members.inject(0) { |sum, m| sum + m.fitness }
|
54
40
|
|
55
|
-
weighted_members = members.sort_by
|
41
|
+
weighted_members = members.sort_by do |m|
|
42
|
+
(m.fitness - fitness_goal).abs
|
43
|
+
end.map do |m|
|
44
|
+
[m, fitness_sum / ((m.fitness - fitness_goal).abs + e)]
|
45
|
+
end
|
56
46
|
|
57
47
|
weight_sum = weighted_members.inject(0) { |sum, m| sum + m[1] }
|
58
48
|
pick = (0..weight_sum).to_a.sample
|
@@ -65,56 +55,68 @@ module Darwinning
|
|
65
55
|
pick_sum += selected_member[1]
|
66
56
|
end
|
67
57
|
|
68
|
-
selected_member
|
69
|
-
end
|
70
|
-
|
71
|
-
def mutate!
|
72
|
-
@members.map! { |m|
|
73
|
-
if (0..100).to_a.sample < @mutation_rate*100
|
74
|
-
m.mutate!
|
75
|
-
else
|
76
|
-
m
|
77
|
-
end
|
78
|
-
}
|
58
|
+
selected_member.first
|
79
59
|
end
|
80
60
|
|
81
61
|
def set_members_fitness!(fitness_values)
|
82
|
-
|
62
|
+
members.to_enum.each_with_index { |m, i| m.fitness = fitness_values[i] }
|
83
63
|
end
|
84
64
|
|
85
65
|
def make_next_generation!
|
86
|
-
temp_members =
|
66
|
+
temp_members = members
|
87
67
|
used_members = []
|
88
68
|
new_members = []
|
89
69
|
|
90
|
-
until new_members.length ==
|
91
|
-
m1 = weighted_select(
|
70
|
+
until new_members.length == members.length / 2
|
71
|
+
m1 = weighted_select(members - used_members)
|
92
72
|
used_members << m1
|
93
|
-
m2 = weighted_select(
|
73
|
+
m2 = weighted_select(members - used_members)
|
94
74
|
used_members << m2
|
95
75
|
|
96
|
-
new_members <<
|
76
|
+
new_members << apply_pairwise_evolutions(organism, m1, m2)
|
97
77
|
end
|
98
78
|
|
99
79
|
new_members.flatten!
|
80
|
+
@members = apply_non_pairwise_evolutions(new_members)
|
81
|
+
@generation += 1
|
82
|
+
end
|
100
83
|
|
101
|
-
|
84
|
+
def apply_pairwise_evolutions(organism, m1, m2)
|
85
|
+
evolution_types.inject([m1, m2]) do |ret, evolution_type|
|
86
|
+
if evolution_type.pairwise?
|
87
|
+
evolution_type.evolve(organism, *ret)
|
88
|
+
else
|
89
|
+
ret
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
102
93
|
|
103
|
-
|
104
|
-
|
94
|
+
def apply_non_pairwise_evolutions(members)
|
95
|
+
evolution_types.inject(members) do |ret, evolution_type|
|
96
|
+
if evolution_type.pairwise?
|
97
|
+
ret
|
98
|
+
else
|
99
|
+
evolution_type.evolve(ret)
|
100
|
+
end
|
101
|
+
end
|
105
102
|
end
|
106
103
|
|
107
104
|
def evolution_over?
|
108
105
|
# check if the fiteness goal or generation limit has been met
|
109
|
-
|
106
|
+
if generations_limit > 0
|
107
|
+
generation == generations_limit || best_member.fitness == fitness_goal
|
108
|
+
else
|
109
|
+
generation == generations_limit || best_member.fitness == fitness_goal
|
110
|
+
end
|
110
111
|
end
|
111
112
|
|
112
113
|
def best_member
|
113
|
-
@members.sort_by { |m| m.fitness }
|
114
|
+
@members.sort_by { |m| m.fitness }.first
|
114
115
|
end
|
115
116
|
|
116
117
|
def size
|
117
118
|
@members.length
|
118
119
|
end
|
119
120
|
end
|
120
|
-
|
121
|
+
|
122
|
+
end
|
data/lib/darwinning/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Darwinning
|
2
|
-
VERSION = "0.0.
|
3
|
-
end
|
2
|
+
VERSION = "0.0.3"
|
3
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Triple < Darwinning::Organism
|
2
|
+
@name = "Triple"
|
3
|
+
@genes = [
|
4
|
+
Darwinning::Gene.new(name: "first digit", value_range: (0..9)),
|
5
|
+
Darwinning::Gene.new(name: "second digit", value_range: (0..9)),
|
6
|
+
Darwinning::Gene.new(name: "third digit", value_range: (0..9))
|
7
|
+
]
|
8
|
+
|
9
|
+
def fitness
|
10
|
+
# Try to get the sum of the 3 digits to add up to 15
|
11
|
+
(genotypes.inject{ |sum, x| sum + x } - 15).abs
|
12
|
+
end
|
13
|
+
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
require 'darwinning'
|
2
|
+
require './spec/classes/triple'
|
2
3
|
|
3
4
|
describe Darwinning::Gene do
|
4
5
|
before do
|
5
|
-
@digit = Darwinning::Gene.new("digit", (0..9))
|
6
|
-
@day_hour = Darwinning::Gene.new(
|
6
|
+
@digit = Darwinning::Gene.new(name: "digit", value_range: (0..9))
|
7
|
+
@day_hour = Darwinning::Gene.new(
|
8
|
+
name: "hour",
|
9
|
+
value_range: (0..23),
|
10
|
+
invalid_values: [0, 1, 2, 3, 4, 20, 21, 22, 23],
|
11
|
+
units: "o'clock"
|
12
|
+
)
|
7
13
|
end
|
8
14
|
|
9
15
|
it "name should be set" do
|
@@ -15,43 +21,17 @@ describe Darwinning::Gene do
|
|
15
21
|
end
|
16
22
|
|
17
23
|
it "invalid values should be set" do
|
18
|
-
@day_hour.invalid_values.should == [0,1,2,3,4,20,21,22,23]
|
24
|
+
@day_hour.invalid_values.should == [0, 1, 2, 3, 4, 20, 21, 22, 23]
|
19
25
|
end
|
20
26
|
|
21
27
|
it "units should be set" do
|
22
28
|
@day_hour.units.should == "o'clock"
|
23
29
|
end
|
24
|
-
|
25
|
-
describe "#express" do
|
26
|
-
|
27
|
-
it "expressed value should be within range" do
|
28
|
-
(0..9).to_a.include?(@digit.express).should == true # uncertain test
|
29
|
-
end
|
30
|
-
|
31
|
-
it "expressed value should not be invalid value" do
|
32
|
-
@day_hour.invalid_values.include?(@digit.express).should == false # uncertain test
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
30
|
end
|
37
31
|
|
38
32
|
describe Darwinning::Organism do
|
39
33
|
before do
|
40
34
|
@org = Darwinning::Organism.new
|
41
|
-
|
42
|
-
class Triple < Darwinning::Organism
|
43
|
-
@name = "Triple"
|
44
|
-
@genes = [
|
45
|
-
Darwinning::Gene.new("first digit", (0..9)),
|
46
|
-
Darwinning::Gene.new("second digit", (0..9)),
|
47
|
-
Darwinning::Gene.new("third digit", (0..9))
|
48
|
-
]
|
49
|
-
|
50
|
-
def fitness
|
51
|
-
# Try to get the sum of the 3 digits to add up to 15
|
52
|
-
(genotypes.inject{ |sum, x| sum + x } - 15).abs
|
53
|
-
end
|
54
|
-
end
|
55
35
|
@triple = Triple.new
|
56
36
|
end
|
57
37
|
|
@@ -86,5 +66,29 @@ describe Darwinning::Organism do
|
|
86
66
|
end
|
87
67
|
|
88
68
|
describe Darwinning::Population do
|
69
|
+
before do
|
70
|
+
@pop_triple = Darwinning::Population.new(
|
71
|
+
organism: Triple, population_size: 10, fitness_goal: 0
|
72
|
+
)
|
73
|
+
end
|
89
74
|
|
90
|
-
|
75
|
+
it "fitness goal should be set to 0" do
|
76
|
+
@pop_triple.fitness_goal.should == 0
|
77
|
+
end
|
78
|
+
|
79
|
+
it "population size should be 10" do
|
80
|
+
@pop_triple.members.length.should == 10
|
81
|
+
end
|
82
|
+
|
83
|
+
it "population should start on generation 0" do
|
84
|
+
@pop_triple.generation.should == 0
|
85
|
+
end
|
86
|
+
|
87
|
+
it "make_next_generation! should evolve population by one generation" do
|
88
|
+
old_members = @pop_triple.members
|
89
|
+
@pop_triple.make_next_generation!
|
90
|
+
@pop_triple.generation.should == 1
|
91
|
+
@pop_triple.members.should_not == old_members
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: darwinning
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-12-02 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Darwinning provides tools to build genetic algorithm solutions using
|
15
15
|
a Gene, Organism, and Population structure.
|
@@ -19,14 +19,19 @@ extensions: []
|
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
21
|
- lib/darwinning/config.rb
|
22
|
+
- lib/darwinning/evolution_types/mutation.rb
|
23
|
+
- lib/darwinning/evolution_types/reproduction.rb
|
24
|
+
- lib/darwinning/evolution_types.rb
|
22
25
|
- lib/darwinning/gene.rb
|
23
26
|
- lib/darwinning/organism.rb
|
24
27
|
- lib/darwinning/population.rb
|
25
28
|
- lib/darwinning/version.rb
|
26
29
|
- lib/darwinning.rb
|
30
|
+
- Gemfile
|
27
31
|
- Rakefile
|
28
32
|
- README.md
|
29
|
-
-
|
33
|
+
- spec/classes/triple.rb
|
34
|
+
- spec/darwinning_spec.rb
|
30
35
|
homepage: https://github.com/dorkrawk/darwinning
|
31
36
|
licenses: []
|
32
37
|
post_install_message:
|
@@ -52,4 +57,5 @@ signing_key:
|
|
52
57
|
specification_version: 3
|
53
58
|
summary: A Ruby gem to aid in the use of genetic algorithms.
|
54
59
|
test_files:
|
55
|
-
-
|
60
|
+
- spec/classes/triple.rb
|
61
|
+
- spec/darwinning_spec.rb
|