simple_ga 0.0.1 → 0.0.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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MTBjODlhNzViZjg1MDI4NTk3OWI4NmZjZGU1NGIyMDM1MDI3YWY5MA==
5
- data.tar.gz: !binary |-
6
- ZDg2OWU3YWFhNGVlZGU2OGUwNzkzMTFkMWQzMDE2OGQwZmMzMTRlMw==
2
+ SHA1:
3
+ metadata.gz: 9326ae742565530cf2b8dbb495cb4fc05f3d6cc0
4
+ data.tar.gz: 133e90581b775c54773b7a3cde6f09938ae6046e
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NzBhZTg0YTk3MTFjOWU3YmYxZjZjZDZjMTQ4OWM5ZDNmZmQ2NDFhYThlNzNh
10
- OWQ2OTU4NGJhYjFiYmZjM2ZmMmE0OGZhYjBjZjRlNTMyZDQ5NGQ3ZTAzNGRm
11
- ZDFiODFiNjJkMzBlMzhkNTVkZDFjMWRkMTczYWNiMTNhNThlMmI=
12
- data.tar.gz: !binary |-
13
- ZmNlYTMyOTg4OGM4N2YwZmE3YWU5ZmI2OTExYzFjYzYxMTE5YmZiOTYxNmJj
14
- YmVjOGJmOWU4ZmU0MzU5ZDMxMGJjOTBkNTUxZmNiMmVjY2U4NzEzZmE4OWEz
15
- ODRlMjY1MmE4NGIwZDFiZGM4NWE3ZDZhZjliMDA4NmU0MWFiMGU=
6
+ metadata.gz: d1c729e435f2b7586b68c33efd590ad759589a8e4894b8a18bf08ef07fc87a9184a344954b60ac713593a2d587749d50bb44386ee56fe88b77a5b984d9690177
7
+ data.tar.gz: a2668e1bb6f5fb702b513fff66d0a4e4da75ba3abee9fa5af8aa0b1c8387589435603e2da2a263216dd5d9ef6f3df34db5704ae76067cd52b5d249faeb0f4b93
@@ -0,0 +1,349 @@
1
+ module SimpleGa
2
+ # The GeneticAlgorithm module implements the GeneticSearch and Chromosome
3
+ # classes. The GeneticSearch class performs a stochastic search
4
+ # of the solution of a given problem.
5
+ #
6
+ # Both the GeneticSearch and Chromosome are "problem specific". SimpleGa built-in
7
+ # Chromosome class and GeneticSearch class were designed to model the
8
+ # probability distribution problem. If you want to solve other type of problem,
9
+ # you will have to modify both of the classes, by overwriting its run, uniquify,
10
+ # fitness, reproduce, and mutate functions, to model your specific problem.
11
+ module GeneticAlgorithm
12
+
13
+ # This class is used to automatically:
14
+ #
15
+ # 1. Choose initial population
16
+ # 2. Evaluate the fitness of each individual in the population
17
+ # 3. Repeat
18
+ # 1. Select best-ranking individuals to reproduce
19
+ # 2. Breed new generation through crossover and mutation (genetic operations)
20
+ # and give birth to offspring
21
+ # 3. Evaluate the individual fitnesses of the offspring
22
+ # 4. Replace worst ranked part of population with offspring
23
+ # 4. Until termination
24
+ class GeneticSearch
25
+
26
+ attr_accessor :population
27
+
28
+ def initialize(initial_population_size, generations)
29
+ @population_size = initial_population_size
30
+ @max_generation = generations
31
+ @generation = 0
32
+ end
33
+
34
+ def run
35
+ generate_initial_population
36
+ search_space = [] # All possible solutions to the problem.
37
+ @max_generation.times do
38
+ selected_to_breed = selection # Evaluates current population.
39
+ selected_to_breed.each do |chromosome|
40
+ search_space << chromosome.data.dup
41
+ end
42
+ offsprings = reproduction selected_to_breed
43
+ replace_worst_ranked offsprings
44
+ end
45
+ unique_solutions = uniquify search_space
46
+
47
+ return best_chromosome
48
+ end
49
+
50
+ def uniquify(search_space)
51
+ unique_search_space = search_space.uniq
52
+ # Turns every unselected courses data into nil
53
+ unique_search_space.each do |c|
54
+ 0.step(c.data.length-1, 2) do |index| # Odd index
55
+ if c[index] == 0
56
+ c[index] = nil
57
+ c[index+1] = nil
58
+ end
59
+ end
60
+ end
61
+ unique_solutions = unique_search_space.uniq
62
+
63
+ return unique_solutions
64
+ end
65
+
66
+ def generate_initial_population
67
+ @population = []
68
+ @population_size.times do
69
+ population << Chromosome.seed
70
+ end
71
+ end
72
+
73
+ # Select best-ranking individuals to reproduce
74
+ #
75
+ # Selection is the stage of a genetic algorithm in which individual
76
+ # genomes are chosen from a population for later breeding.
77
+ # There are several generic selection algorithms, such as
78
+ # tournament selection and roulette wheel selection. We implemented the
79
+ # latest.
80
+ #
81
+ # Steps:
82
+ #
83
+ # 1. The fitness function is evaluated for each individual, providing fitness values
84
+ # 2. The population is sorted by descending fitness values.
85
+ # 3. The fitness values are then normalized. (Highest fitness gets 1, lowest fitness gets 0). The normalized value is stored in the "normalized_fitness" attribute of the chromosomes.
86
+ # 4. A random number R is chosen. R is between 0 and the accumulated normalized value (all the normalized fitness values added togheter).
87
+ # 5. The selected individual is the first one whose accumulated normalized value (its is normalized value plus the normalized values of the chromosomes prior it) greater than R.
88
+ # 6. We repeat steps 4 and 5, 2/3 times the population size.
89
+ def selection
90
+ @population.sort! { |a, b| b.fitness <=> a.fitness}
91
+ best_fitness = @population[0].fitness
92
+ worst_fitness = @population.last.fitness
93
+ acum_fitness = 0
94
+ if best_fitness-worst_fitness > 0
95
+ @population.each do |chromosome|
96
+ chromosome.normalized_fitness = (chromosome.fitness - worst_fitness)/(best_fitness-worst_fitness)
97
+ acum_fitness += chromosome.normalized_fitness
98
+ end
99
+ else
100
+ @population.each { |chromosome| chromosome.normalized_fitness = 1}
101
+ end
102
+ selected_to_breed = []
103
+ ((2*@population_size)/3).times do
104
+ selected_to_breed << select_random_individual(acum_fitness)
105
+ end
106
+
107
+ selected_to_breed
108
+ end
109
+
110
+ # We combine each pair of selected chromosome using the method
111
+ # Chromosome.reproduce
112
+ #
113
+ # The reproduction will also call the Chromosome.mutate method with
114
+ # each member of the population. You should implement Chromosome.mutate
115
+ # to only change (mutate) randomly. E.g. You could effectivly change the
116
+ # chromosome only if
117
+ # rand < ((1 - chromosome.normalized_fitness) * 0.4)
118
+ def reproduction(selected_to_breed)
119
+ offsprings = []
120
+ 0.upto(selected_to_breed.length/2-1) do |i|
121
+ offsprings << Chromosome.reproduce(selected_to_breed[2*i], selected_to_breed[2*i+1])
122
+ end
123
+ @population.each do |individual|
124
+ Chromosome.mutate(individual)
125
+ end
126
+ return offsprings
127
+ end
128
+
129
+ # Replace worst ranked part of population with new offsprings.
130
+ def replace_worst_ranked(offsprings)
131
+ size = offsprings.length
132
+ # Replacing from the back because the population has been sorted accordingly.
133
+ @population = @population [0..((-1*size)-1)] + offsprings
134
+ end
135
+
136
+ # Select the best chromosome in the population.
137
+ def best_chromosome
138
+ the_best = @population[0]
139
+ @population.each do |chromosome|
140
+ the_best = chromosome if chromosome.fitness > the_best.fitness
141
+ # chromosome.fitness > the_best.fitness will produce the first best chromosome.
142
+ # chromosome.fitness >= the_best.fitness will product the last best chromosome.
143
+ # Hence, it is not a matter of concern unless the risk analysis is important.
144
+ # e.g. high risk approach and low risk approach.
145
+ end
146
+ return the_best
147
+ end
148
+
149
+ private
150
+ def select_random_individual(acum_fitness)
151
+ select_random_target = acum_fitness * rand
152
+ local_acum = 0
153
+ @population.each do |chromosome|
154
+ local_acum += chromosome.normalized_fitness
155
+ return chromosome if local_acum >= select_random_target
156
+ end
157
+ end
158
+ end # end/GeneticSearch
159
+
160
+ # A Chromosome is a representation of an individual solution for a specific
161
+ # problem. You will have to redifine the Chromosome representation for each
162
+ # particular problem, along with its fitness, mutate, reproduce, and seed methods.
163
+ class Chromosome
164
+
165
+ attr_accessor :data
166
+ attr_accessor :normalized_fitness
167
+
168
+ def initialize(data) # Chromosome.new
169
+ @data = data
170
+ end
171
+
172
+ # The fitness method quantifies the optimality of a solution
173
+ # (that is, a chromosome) in a genetic algorithm so that that particular
174
+ # chromosome may be ranked against all the other chromosomes.
175
+ #
176
+ # Optimal chromosomes, or at least chromosomes which are more optimal,
177
+ # are allowed to breed and mix their datasets by any of several techniques,
178
+ # producing a new generation that will (hopefully) be even better.
179
+ def fitness
180
+ return @fitness if @fitness
181
+
182
+ # Current state inputs to be retrieved from the database.
183
+ credits = [2,3,3,3,5,2,4,4,4,4,3]
184
+ old_gpa = 58
185
+ old_total_credits = 16
186
+ min_credits = 16
187
+ max_credits = 20
188
+ target_cgpa ||= 3.7
189
+
190
+ courses, grades, points = [], [], []
191
+ # Split the chromosome into 2.
192
+ 0.step(@data.length-1, 2) do |j|
193
+ courses << @data[j]
194
+ grades << @data[j+1]
195
+ end
196
+
197
+ total_credits = ([courses, credits].transpose.map {|x| x.inject(:*)}).inject{|sum,x| sum + x }
198
+ new_total_credits = old_total_credits + total_credits
199
+
200
+ grades.each do |grade|
201
+ case grade
202
+ when 1
203
+ points << 4.00
204
+ when 2
205
+ points << 3.70
206
+ when 3
207
+ points << 3.30
208
+ when 4
209
+ points << 3.00
210
+ when 5
211
+ points << 2.70
212
+ when 6
213
+ points << 2.30
214
+ when 7
215
+ points << 2.00
216
+ end
217
+ end
218
+
219
+ gpa = (([credits, courses, points].transpose.map {|x| x.inject(:*)}).inject{|sum,x| sum + x }).round(2)
220
+ new_gpa = old_gpa + gpa
221
+ cgpa = (new_gpa/new_total_credits).round(2)
222
+
223
+ # Core constraints.
224
+ # Elites own a high fitness value.
225
+ # The higher the fitness value, the higher the chance of being selected.
226
+ if total_credits <= max_credits && total_credits >= min_credits && cgpa >= target_cgpa
227
+ @fitness = cgpa
228
+ # This chromosome doesn't satisfy the important constraints
229
+ # e.g. within the range of min_credits and max_credits
230
+ # should be discarded.
231
+
232
+ # Perhaps, we should add cases that statisfy one of the constraints
233
+ # 1. credit hours + cgpa
234
+ # 2. credit hours
235
+ else
236
+ # Negative cgpa value will allow the invalid chromosome to be considered.
237
+ # However, surprisingly the solutions suggested are more consistent and
238
+ # diverse.
239
+ @fitness = 0
240
+ end
241
+ return @fitness
242
+ end
243
+
244
+ # Mutation method is used to maintain genetic diversity from one
245
+ # generation of a population of chromosomes to the next. It is analogous
246
+ # to biological mutation.
247
+ #
248
+ # The purpose of mutation in GAs is to allow the
249
+ # algorithm to avoid local minima by preventing the population of
250
+ # chromosomes from becoming too similar to each other, thus slowing or even
251
+ # stopping evolution.
252
+ #
253
+ # Callling the mutate function will "probably" slightly change a chromosome
254
+ # randomly.
255
+
256
+ def self.mutate(chromosome)
257
+ if chromosome.normalized_fitness && rand < ((1 - chromosome.normalized_fitness) * 0.4)
258
+ courses, grades = [], []
259
+ data = chromosome.data
260
+
261
+ # Split the chromosome into 2.
262
+ 0.step(data.length-1, 2) do |j|
263
+ courses << data[j]
264
+ grades << data[j+1]
265
+ end
266
+
267
+ p1 = (rand * courses.length-1).ceil
268
+ courses[p1] = rand(2)
269
+ p2 = (rand * grades.length-1).ceil
270
+ grades[p2] = (1 + rand(6))
271
+
272
+ # Recombine the chromosome.
273
+ # [0,1,2,3,4,5,6,7,8,9,10]
274
+ 0.upto(courses.length-1) do |j|
275
+ even_index = j * 2
276
+ odd_index = even_index + 1
277
+ data[even_index] = courses[j]
278
+ data[odd_index] = grades[j]
279
+ end
280
+
281
+ chromosome.data = data
282
+ @fitness = nil
283
+ end
284
+ end
285
+
286
+ # Reproduction method is used to combine two chromosomes (solutions) into
287
+ # a single new chromosome. There are several ways to
288
+ # combine two chromosomes: One-point crossover, Two-point crossover,
289
+ # "Cut and splice", edge recombination, and more.
290
+ #
291
+ # The method is usually dependant of the problem domain.
292
+ # In this case, we have implemented one-point crossover, which is the
293
+ # most used reproduction algorithm for the estimation of probablity distribution.
294
+
295
+ # Chromosome a and b might be the same.
296
+ # [NOTE] Why is chromosome a the same as chromosome b?
297
+ def self.reproduce(a, b)
298
+ # We know that (a.data.length == b.data.length) must be always true.
299
+ chromosomeLength = a.data.length
300
+ aCourses, bCourses, aGrades, bGrades = [], [], [], []
301
+
302
+ # Split the chromosome into 2.
303
+ 0.step(chromosomeLength-1, 2) do |index|
304
+ next_index = index + 1
305
+ aCourses << a.data[index]
306
+ aGrades << a.data[next_index]
307
+ bCourses << b.data[index]
308
+ bGrades << b.data[next_index]
309
+ end
310
+
311
+ # One-point crossover
312
+ # We know that (aCourses.length == aGrades.length) must be always true.
313
+ # However, we want to cut and cross at different points for the
314
+ # corresponding course and grade array.
315
+ # Avoid slice(0,0) or slice (11,11). It brings no changes.
316
+ course_Xpoint = rand(aCourses.length-1) + 1
317
+ grade_Xpoint = rand(aGrades.length-1) + 1
318
+ new_Courses = aCourses.slice(0, course_Xpoint) + bCourses.slice(course_Xpoint, aCourses.length)
319
+ new_Grades = aGrades.slice(0, grade_Xpoint) + bGrades.slice(grade_Xpoint, aGrades.length)
320
+
321
+ spawn = []
322
+ # We know that (new_Courses.length == new_Grades.length) must be always true.
323
+ 0.upto(new_Courses.length-1) do |i|
324
+ spawn << new_Courses[i]
325
+ spawn << new_Grades[i]
326
+ end
327
+
328
+ return Chromosome.new(spawn)
329
+ end
330
+
331
+ # Initializes an individual solution (chromosome) for the initial
332
+ # population. Usually the chromosome is generated randomly, but you can
333
+ # use some problem domain knowledge, to generate a (probably) better
334
+ # initial solution.
335
+
336
+ def self.seed
337
+ # Current state inputs to be retrieved from the database.
338
+ ncourse = 11
339
+ seed = []
340
+
341
+ 1.step(ncourse*2, 2) do |j|
342
+ seed << rand(2)
343
+ seed << (1 + rand(6))
344
+ end
345
+ return Chromosome.new(seed)
346
+ end
347
+ end # end/Chromosome
348
+ end # end/GeneticAlgorithm
349
+ end # end/SimpleGa
@@ -1,3 +1,3 @@
1
1
  module SimpleGa
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/simple_ga.rb CHANGED
@@ -1,6 +1,11 @@
1
- require "simple_ga/version"
2
- require "simple_ga/hello"
1
+ # Author:: Johnson Yeap
2
+ # License:: MPL 1.1
3
+ # Project:: Academic Planner - Pointa
4
+ # Url:: http://pointa.herokuapp.com/
5
+
6
+ require 'simple_ga/version'
7
+ require 'simple_ga/genetic_algorithm'
3
8
 
4
9
  module SimpleGa
5
10
  # Your code goes here...
6
- end
11
+ end
Binary file
@@ -0,0 +1,27 @@
1
+ describe SimpleGa::GeneticAlgorithm::Chromosome do
2
+ subject { SimpleGa::GeneticAlgorithm::Chromosome.seed }
3
+ subject(:c1) { SimpleGa::GeneticAlgorithm::Chromosome.new([0, 1, 1, 2, 0, 1, 1, 1, 0, 3, 1, 1, 0, 3, 1, 1, 1, 2, 0, 6, 1, 2]) }
4
+ subject(:c2) { SimpleGa::GeneticAlgorithm::Chromosome.new([0, 2, 0, 6, 0, 1, 0, 1, 0, 3, 0, 4, 1, 2, 0, 4, 1, 3, 1, 4, 1, 5]) }
5
+
6
+ context "when a new chromosome is created" do
7
+ it "has a length of an even number" do
8
+ expect(subject.data.length % 2).to eql(0)
9
+ end
10
+
11
+ it "has a positive or zero fitness value" do
12
+ expect(subject.fitness).to be >= 0
13
+ end
14
+ end
15
+
16
+ context "when two distinctive chromosomes crossover" do
17
+ it "reproduces a new distinctive chromosome" do
18
+ c3 = SimpleGa::GeneticAlgorithm::Chromosome.reproduce(c1, c2)
19
+ expect(c3.data).not_to eql(c1.data && c2.data)
20
+ end
21
+
22
+ it "reproduces a new chromosome with the same data length" do
23
+ c3 = SimpleGa::GeneticAlgorithm::Chromosome.reproduce(c1, c2)
24
+ expect(c3.data.length).to eql(c1.data.length && c2.data.length)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,24 @@
1
+ describe SimpleGa::GeneticAlgorithm do
2
+ subject(:search) { SimpleGa::GeneticAlgorithm::GeneticSearch.new(10, 5) }
3
+ context "when the genetic search is initiated" do
4
+ it "is expected that the selected array does not contain nil element" do
5
+ search.generate_initial_population
6
+ selected = search.selection
7
+ selected.each { |s| expect(s).not_to be_nil }
8
+ end
9
+
10
+ it "has the right amount of populations" do
11
+ search.generate_initial_population
12
+ expect(search.population.length).to eql(10)
13
+ end
14
+ end
15
+ context "when the worst ranked chromosomes are being replaced" do
16
+ it "expected that the offsprings are included in the new population" do
17
+ search.generate_initial_population
18
+ selected = search.selection
19
+ offsprings = search.reproduction selected
20
+ search.replace_worst_ranked offsprings
21
+ offsprings.each { |c| expect(search.population).to include(c)}
22
+ end
23
+ end
24
+ end
metadata CHANGED
@@ -1,97 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_ga
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johnson Yeap
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-07 00:00:00.000000000 Z
11
+ date: 2015-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.7'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.7'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ! '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: guard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ! '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ! '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: guard-rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ! '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ! '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: coveralls
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ! '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ! '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  description: This is a simple genetic algorithm gem
@@ -101,21 +101,23 @@ executables: []
101
101
  extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
- - .coveralls.yml
105
- - .gitignore
106
- - .rspec
107
- - .travis.yml
104
+ - ".coveralls.yml"
105
+ - ".gitignore"
106
+ - ".rspec"
107
+ - ".travis.yml"
108
108
  - Gemfile
109
109
  - Guardfile
110
110
  - LICENSE.txt
111
111
  - README.md
112
112
  - Rakefile
113
113
  - lib/simple_ga.rb
114
- - lib/simple_ga/hello.rb
114
+ - lib/simple_ga/genetic_algorithm.rb
115
115
  - lib/simple_ga/version.rb
116
+ - simple_ga-0.0.1.gem
116
117
  - simple_ga.gemspec
118
+ - spec/chromosome_spec.rb
119
+ - spec/genetic_algorithm_spec.rb
117
120
  - spec/spec_helper.rb
118
- - spec/test_spec.rb
119
121
  homepage: ''
120
122
  licenses:
121
123
  - MIT
@@ -126,20 +128,21 @@ require_paths:
126
128
  - lib
127
129
  required_ruby_version: !ruby/object:Gem::Requirement
128
130
  requirements:
129
- - - ! '>='
131
+ - - ">="
130
132
  - !ruby/object:Gem::Version
131
133
  version: '0'
132
134
  required_rubygems_version: !ruby/object:Gem::Requirement
133
135
  requirements:
134
- - - ! '>='
136
+ - - ">="
135
137
  - !ruby/object:Gem::Version
136
138
  version: '0'
137
139
  requirements: []
138
140
  rubyforge_project:
139
- rubygems_version: 2.3.0
141
+ rubygems_version: 2.2.2
140
142
  signing_key:
141
143
  specification_version: 4
142
144
  summary: Simple GA Gem
143
145
  test_files:
146
+ - spec/chromosome_spec.rb
147
+ - spec/genetic_algorithm_spec.rb
144
148
  - spec/spec_helper.rb
145
- - spec/test_spec.rb
@@ -1,9 +0,0 @@
1
- class Hello
2
- def hello
3
- puts "Hello World!"
4
- end
5
-
6
- def pow(a, b)
7
- a ** b
8
- end
9
- end
data/spec/test_spec.rb DELETED
@@ -1,16 +0,0 @@
1
- # describe "test one" do
2
- # context "first test" do
3
- # it "is a test" do
4
- # expect(1).to eql(1)
5
- # end
6
- # end
7
- # end
8
-
9
- describe Hello do
10
- context "first test" do
11
- it "is a test" do
12
- @hello = Hello.new
13
- expect(@hello.pow(3,2)).to eql(9)
14
- end
15
- end
16
- end