gemetics 0.0.3 → 0.1.0

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/gemetics.rb +112 -43
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ddeeb3132c636e9788f6ec9c1e4a8fd7cf7e584
4
- data.tar.gz: 6136a2cb2d02172058db28b24fbc4e7858b94b56
3
+ metadata.gz: 03348853673a345fd2653bf0300963de087664ef
4
+ data.tar.gz: e0bc73e5ed66e085a859769b7ac2f644eacae404
5
5
  SHA512:
6
- metadata.gz: 39a8fe2e1265bb761643846387c11150e63a8b30566671062db7b87ffee9330c9ef3231601d81b861451aeee33b89dc52ff2e23824b9ffc1634330aeed653635
7
- data.tar.gz: 76dea21c731cdb8f7249db6e601ec2feadf9189d733f3380ae81e034d13418715086474ca09e0e51ba03200f10902a8f7d733f4bbcad19e706a6be11b0dee152
6
+ metadata.gz: d593ebf10f86fe18f6fade87886b39834bdd01cf10f581cf8528e262c4fa2caf92e1d155bfc744af4a647b3f62d7e56dd450240eac3c49d41594070b503e3cb4
7
+ data.tar.gz: b4191a88f4cf2163ad10033b1afed03e573946ba42419a63053a88505ec9e8a0fa52b4072f1db0ec498f4ae4997d2a6271cfd7cf7d4d4deaf0d03c19aa512c38
data/lib/gemetics.rb CHANGED
@@ -9,55 +9,64 @@ def default_GA_options()
9
9
  mutationPercent: 0.05,
10
10
  elitism: 0,
11
11
  debug: false,
12
+ tournamentSize: 10,
12
13
  }
13
14
  end
14
15
 
15
16
  def runGeneticAlgorithm(initialPopulation, eval, threshold, options)
16
- # make sure options is assigned
17
+ # make sure options is assigned
17
18
  if(options == nil)
18
- options = default_GA_options
19
+ options = default_GA_options()
19
20
  end
20
- validOptions(options,population.size()) # Raises error if options are not correct
21
+ validOptions(options,initialPopulation.size()) # Raises error if options are not correct
21
22
  currentGen = 0
22
23
  bestCanidate = initialPopulation[0]
23
24
  population = initialPopulation
24
25
  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
31
26
  # evaluate the population
32
27
  population = eval.call(population)
33
- if(options[:greaterBetter])
28
+
29
+ if(options[:greaterBetter])
34
30
  sortedPopulation = population.sort{ |x , y| y.fitness <=> x.fitness }
35
31
  else
36
32
  sortedPopulation = population.sort{ |x , y| x.fitness <=> y.fitness }
37
33
  end
38
34
  bestCanidate = population[0].clone
39
35
 
36
+ if(options[:debug])
37
+ puts 'Best Canidate Soultion:'
38
+ puts bestCanidate.inspect
39
+ puts 'Current Generation:'
40
+ puts currentGen
41
+ puts 'Average Fitness:'
42
+ cumulative = 0
43
+ for org in population
44
+ cumulative += org.fitness
45
+ end
46
+ puts cumulative/population.size()
47
+ end
48
+
40
49
 
41
50
  if(options[:totalPopReplace] == false)
42
51
  # Do not replace every organism
43
- mates = selection(sortedPopulation.clone(), options[:selectionStyle])
52
+ mates = selection(sortedPopulation.clone(), options)
44
53
 
45
54
  # mate and replace
46
55
  results = mateOrgs(mates[0], mates[1])
47
56
  replaced = []
48
- if(options[:elitism] > 0)
49
- population = sortedPopulation
50
- for i in 0...options[:elitism]
51
- replaced.append(0)
52
- end
53
- end
57
+ if(options[:elitism] > 0)
58
+ population = sortedPopulation
59
+ for i in 0...options[:elitism]
60
+ replaced.append(i)
61
+ end
62
+ end
54
63
  for i in 0...results.size()
55
64
  results[i].mutate() if Random.new.rand() < options[:mutationPercent]
56
65
  temp = Random.new.rand(population.size())
57
- while(!replaced.includes?(temp)) do
66
+ while(replaced.include?(temp)) do
58
67
  temp = Random.new.rand(population.size())
59
68
  end
60
- replaced.append(temp)
69
+ replaced.push(temp)
61
70
  population[replaced[-1]] = results[i]
62
71
  end
63
72
  else
@@ -65,24 +74,19 @@ def runGeneticAlgorithm(initialPopulation, eval, threshold, options)
65
74
  needed = population.size()
66
75
  have = 0
67
76
  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
77
+ if(options[:elitism] > 0)
78
+ for i in 0...options[:elitism]
79
+ newPopulation[i] = sortedPopulation[i]
80
+ end
81
+ end
78
82
  while have < needed do
79
- mates = selection(sortedPopulation.clone(), options[:selectionStyle])
83
+ mates = selection(sortedPopulation.clone(), options)
80
84
 
81
85
  # mate and put them into new pop
82
86
  results = mateOrgs(mates[0], mates[1])
83
87
  for i in 0...results.size()
84
88
  results[i].mutate() if Random.new.rand() < options[:mutationPercent]
85
- newPopulation[have+i] = result[i] if (have+i) < needed
89
+ newPopulation[have+i] = results[i] if (have+i) < needed
86
90
  end
87
91
  have += results.size()
88
92
  end
@@ -98,13 +102,13 @@ end
98
102
 
99
103
  def continue?(highestFitness, threshold, currentGen, options)
100
104
  return false if exceedsThreshold?(options[:greaterBetter], highestFitness, threshold)
101
- return false if currentGen > options[:maxGen]
105
+ return false if currentGen > options[:genMax]
102
106
  return true
103
107
  end
104
108
 
105
109
  def exceedsThreshold?(greaterBetter, val, threshold)
106
110
  if(val == nil)
107
- return false
111
+ return false
108
112
  end
109
113
  if(greaterBetter)
110
114
  return val>=threshold
@@ -114,25 +118,73 @@ def exceedsThreshold?(greaterBetter, val, threshold)
114
118
  return false
115
119
  end
116
120
 
117
- def selection(population, type)
121
+ def selection(population, options)
118
122
  # select mates
119
- if(type == 'tournament')
120
- return tournamentSelection(population)
121
- elsif(type == 'best')
123
+ if(options[:selectionStyle] == 'tournament')
124
+ return tournamentSelection(population, options[:tournamentSize])
125
+ elsif(options[:selectionStyle] == 'best')
122
126
  return bestSelection(population)
127
+ elsif(options[:selectionStyle] == 'roulette')
128
+ return rouletteSelection(population)
123
129
  end
124
130
  raise 'Problem with selection type'
125
131
  end
126
132
 
127
- def tournamentSelection(population)
133
+ # Selection algorithms are based on population being sorted
134
+
135
+ def tournamentSelection(population, size)
128
136
  population = population.shuffle
129
- return population[0..10].sort{ |x , y| x.fitness <=> y.fitness }[0..1]
137
+ subPop = population[0...size]
138
+ additiveFitness = 0
139
+ result = []
140
+ for member in subPop
141
+ additiveFitness += member.fitness
142
+ end
143
+ for member in subPop
144
+ if Random.new.rand() <= (member.fitness/additiveFitness)
145
+ result.push(member)
146
+ break
147
+ end
148
+ end
149
+ for member in subPop
150
+ if Random.new.rand() <= (member.fitness/additiveFitness)
151
+ result.push(member)
152
+ break
153
+ end
154
+ end
155
+ result.push(subPop[0]) while result.size() < 2
156
+ return result
130
157
  end
131
158
 
132
159
  def bestSelection(population)
133
160
  return population[0..1]
134
161
  end
135
162
 
163
+ def rouletteSelection(population)
164
+ additiveFitness = 0.0
165
+ for member in population
166
+ additiveFitness += member.fitness
167
+ end
168
+
169
+ result = []
170
+ for member in population
171
+ if Random.new.rand() <= (member.fitness/additiveFitness)
172
+ result.push(member)
173
+ break
174
+ end
175
+ end
176
+
177
+ for member in population
178
+ if Random.new.rand() <= (member.fitness/additiveFitness)
179
+ result.push(member)
180
+ break
181
+ end
182
+ end
183
+
184
+ result.push(population[0]) while result.size() < 2
185
+ return result
186
+ end
187
+
136
188
  def mateOrgs(one, two)
137
189
  return one.mate(two)
138
190
  end
@@ -141,17 +193,27 @@ end
141
193
 
142
194
  def validOptions(options, populationSize)
143
195
  raise 'Required Option Missing' if !hasRequiredOptions(options)
196
+ raise 'Required Dependent Options Missing' if !hasRequiredDependentOptions(options)
144
197
  raise 'Options Not Within Limits' if !withinLimits(options, populationSize)
198
+ raise 'Dependent Options Not Within Limits' if !dependentOptionsWithinLimits(options, populationSize)
145
199
  return true
146
200
  end
147
201
 
148
202
  def hasRequiredOptions(options)
149
203
  return false if !options.has_key?(:greaterBetter)
150
204
  return false if !options.has_key?(:totalPopReplace)
205
+ return false if !options.has_key?(:selectionStyle)
151
206
  return false if !options.has_key?(:genMax)
152
- return false if !options.has_key?(:mutation_percent)
207
+ return false if !options.has_key?(:mutationPercent)
153
208
  return false if !options.has_key?(:debug)
154
- return false if !options.has_key?(:elitism)
209
+ return false if !options.has_key?(:elitism)
210
+ return true
211
+ end
212
+
213
+ def hasRequiredDependentOptions(options)
214
+ if(options[:selectionStyle] == 'tournament')
215
+ return false if !options.has_key?(:tournamentSize)
216
+ end
155
217
  return true
156
218
  end
157
219
 
@@ -159,13 +221,20 @@ def withinLimits(options, populationSize)
159
221
  possibleGreaterBetter = [true, false]
160
222
  possibleTotalPopReplace = [true, false]
161
223
  possibleDebug = [true, false]
162
- possibleSelectionStyle = ['tournament', 'best']
224
+ possibleSelectionStyle = ['tournament', 'best', 'roulette']
163
225
  return false if !(possibleGreaterBetter.include?(options[:greaterBetter]))
164
226
  return false if !(possibleTotalPopReplace.include?(options[:totalPopReplace]))
165
227
  return false if !(options[:genMax]>0)
166
228
  return false if !(possibleSelectionStyle.include?(options[:selectionStyle]))
167
229
  return false if !(options[:mutationPercent]>0.0)
168
230
  return false if !(possibleDebug.include?(options[:debug]))
169
- return false if !(options[:elitism]>=0 && options[:elitism]<populationSize)
231
+ return false if !(options[:elitism]>=0 && options[:elitism]<populationSize)
232
+ return true
233
+ end
234
+
235
+ def dependentOptionsWithinLimits(options, populationSize)
236
+ if(options[:selectionStyle] == 'tournament')
237
+ return false if !(options[:tournamentSize] > 0 && options[:tournamentSize] <= populationSize)
238
+ end
170
239
  return true
171
240
  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.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Huelsman