gemetics 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.
- checksums.yaml +4 -4
- data/lib/gemetics.rb +87 -31
- data/lib/genetic_object.rb +14 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ddeeb3132c636e9788f6ec9c1e4a8fd7cf7e584
|
4
|
+
data.tar.gz: 6136a2cb2d02172058db28b24fbc4e7858b94b56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39a8fe2e1265bb761643846387c11150e63a8b30566671062db7b87ffee9330c9ef3231601d81b861451aeee33b89dc52ff2e23824b9ffc1634330aeed653635
|
7
|
+
data.tar.gz: 76dea21c731cdb8f7249db6e601ec2feadf9189d733f3380ae81e034d13418715086474ca09e0e51ba03200f10902a8f7d733f4bbcad19e706a6be11b0dee152
|
data/lib/gemetics.rb
CHANGED
@@ -1,27 +1,33 @@
|
|
1
|
+
require_relative 'genetic_object'
|
2
|
+
|
1
3
|
def default_GA_options()
|
2
4
|
return {
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
greaterBetter: true,
|
6
|
+
totalPopReplace: true,
|
7
|
+
genMax: 1000,
|
8
|
+
selectionStyle: 'tournament',
|
9
|
+
mutationPercent: 0.05,
|
10
|
+
elitism: 0,
|
11
|
+
debug: false,
|
9
12
|
}
|
10
13
|
end
|
11
14
|
|
12
|
-
def
|
15
|
+
def runGeneticAlgorithm(initialPopulation, eval, threshold, options)
|
13
16
|
# make sure options is assigned
|
14
17
|
if(options == nil)
|
15
18
|
options = default_GA_options
|
16
19
|
end
|
20
|
+
validOptions(options,population.size()) # Raises error if options are not correct
|
17
21
|
currentGen = 0
|
18
22
|
bestCanidate = initialPopulation[0]
|
19
23
|
population = initialPopulation
|
20
|
-
while(
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
while(continue?(bestCanidate.fitness, threshold, currentGen, options)) do
|
25
|
+
if(options[:debug])
|
26
|
+
puts 'Best Canidate Soultion:'
|
27
|
+
puts bestCanidate.inspect
|
28
|
+
puts 'Current Generation:'
|
29
|
+
puts currentGen
|
30
|
+
end
|
25
31
|
# evaluate the population
|
26
32
|
population = eval.call(population)
|
27
33
|
if(options[:greaterBetter])
|
@@ -37,9 +43,16 @@ def runAlgorithm(initialPopulation, eval, threshold, options)
|
|
37
43
|
mates = selection(sortedPopulation.clone(), options[:selectionStyle])
|
38
44
|
|
39
45
|
# mate and replace
|
40
|
-
|
46
|
+
results = mateOrgs(mates[0], mates[1])
|
47
|
+
replaced = []
|
48
|
+
if(options[:elitism] > 0)
|
49
|
+
population = sortedPopulation
|
50
|
+
for i in 0...options[:elitism]
|
51
|
+
replaced.append(0)
|
52
|
+
end
|
53
|
+
end
|
41
54
|
for i in 0...results.size()
|
42
|
-
results[i].mutate() if Random.new.rand() < options[:
|
55
|
+
results[i].mutate() if Random.new.rand() < options[:mutationPercent]
|
43
56
|
temp = Random.new.rand(population.size())
|
44
57
|
while(!replaced.includes?(temp)) do
|
45
58
|
temp = Random.new.rand(population.size())
|
@@ -52,42 +65,63 @@ def runAlgorithm(initialPopulation, eval, threshold, options)
|
|
52
65
|
needed = population.size()
|
53
66
|
have = 0
|
54
67
|
newPopulation = Array.new(population.size(), GeneticObject.new)
|
68
|
+
if(option[:elitism] > 0)
|
69
|
+
if(options[:greaterBetter])
|
70
|
+
sortedPopulation = population.sort{ |x , y| y.fitness <=> x.fitness }
|
71
|
+
else
|
72
|
+
sortedPopulation = population.sort{ |x , y| x.fitness <=> y.fitness }
|
73
|
+
end
|
74
|
+
for i in 0...options[:elitism]
|
75
|
+
newPopulation[i] = sortedPopulation[i]
|
76
|
+
end
|
77
|
+
end
|
55
78
|
while have < needed do
|
56
79
|
mates = selection(sortedPopulation.clone(), options[:selectionStyle])
|
57
80
|
|
58
81
|
# mate and put them into new pop
|
59
|
-
results = mates[0]
|
82
|
+
results = mateOrgs(mates[0], mates[1])
|
60
83
|
for i in 0...results.size()
|
61
|
-
results[i].mutate() if Random.new.rand() < options[:
|
84
|
+
results[i].mutate() if Random.new.rand() < options[:mutationPercent]
|
62
85
|
newPopulation[have+i] = result[i] if (have+i) < needed
|
63
86
|
end
|
64
87
|
have += results.size()
|
65
88
|
end
|
66
89
|
population = newPopulation
|
67
90
|
end
|
91
|
+
# Increment generations
|
68
92
|
currentGen += 1
|
69
93
|
end
|
70
94
|
return bestCanidate
|
71
95
|
end
|
72
96
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
97
|
+
# Internal Logic
|
98
|
+
|
99
|
+
def continue?(highestFitness, threshold, currentGen, options)
|
100
|
+
return false if exceedsThreshold?(options[:greaterBetter], highestFitness, threshold)
|
101
|
+
return false if currentGen > options[:maxGen]
|
102
|
+
return true
|
103
|
+
end
|
104
|
+
|
105
|
+
def exceedsThreshold?(greaterBetter, val, threshold)
|
106
|
+
if(val == nil)
|
107
|
+
return false
|
108
|
+
end
|
77
109
|
if(greaterBetter)
|
78
110
|
return val>=threshold
|
79
111
|
else
|
80
112
|
return val<=threshold
|
81
113
|
end
|
114
|
+
return false
|
82
115
|
end
|
83
116
|
|
84
117
|
def selection(population, type)
|
85
118
|
# select mates
|
86
119
|
if(type == 'tournament')
|
87
120
|
return tournamentSelection(population)
|
88
|
-
|
121
|
+
elsif(type == 'best')
|
89
122
|
return bestSelection(population)
|
90
123
|
end
|
124
|
+
raise 'Problem with selection type'
|
91
125
|
end
|
92
126
|
|
93
127
|
def tournamentSelection(population)
|
@@ -99,17 +133,39 @@ def bestSelection(population)
|
|
99
133
|
return population[0..1]
|
100
134
|
end
|
101
135
|
|
102
|
-
|
103
|
-
|
136
|
+
def mateOrgs(one, two)
|
137
|
+
return one.mate(two)
|
138
|
+
end
|
104
139
|
|
105
|
-
|
106
|
-
end
|
140
|
+
# Validation
|
107
141
|
|
108
|
-
|
109
|
-
|
110
|
-
|
142
|
+
def validOptions(options, populationSize)
|
143
|
+
raise 'Required Option Missing' if !hasRequiredOptions(options)
|
144
|
+
raise 'Options Not Within Limits' if !withinLimits(options, populationSize)
|
145
|
+
return true
|
146
|
+
end
|
111
147
|
|
112
|
-
|
113
|
-
|
114
|
-
|
148
|
+
def hasRequiredOptions(options)
|
149
|
+
return false if !options.has_key?(:greaterBetter)
|
150
|
+
return false if !options.has_key?(:totalPopReplace)
|
151
|
+
return false if !options.has_key?(:genMax)
|
152
|
+
return false if !options.has_key?(:mutation_percent)
|
153
|
+
return false if !options.has_key?(:debug)
|
154
|
+
return false if !options.has_key?(:elitism)
|
155
|
+
return true
|
156
|
+
end
|
157
|
+
|
158
|
+
def withinLimits(options, populationSize)
|
159
|
+
possibleGreaterBetter = [true, false]
|
160
|
+
possibleTotalPopReplace = [true, false]
|
161
|
+
possibleDebug = [true, false]
|
162
|
+
possibleSelectionStyle = ['tournament', 'best']
|
163
|
+
return false if !(possibleGreaterBetter.include?(options[:greaterBetter]))
|
164
|
+
return false if !(possibleTotalPopReplace.include?(options[:totalPopReplace]))
|
165
|
+
return false if !(options[:genMax]>0)
|
166
|
+
return false if !(possibleSelectionStyle.include?(options[:selectionStyle]))
|
167
|
+
return false if !(options[:mutationPercent]>0.0)
|
168
|
+
return false if !(possibleDebug.include?(options[:debug]))
|
169
|
+
return false if !(options[:elitism]>=0 && options[:elitism]<populationSize)
|
170
|
+
return true
|
115
171
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemetics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Huelsman
|
@@ -17,6 +17,7 @@ extensions: []
|
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
19
|
- lib/gemetics.rb
|
20
|
+
- lib/genetic_object.rb
|
20
21
|
homepage: https://github.com/xLeachimx/Gemetics
|
21
22
|
licenses:
|
22
23
|
- MIT
|