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 +5 -13
- data/lib/simple_ga/genetic_algorithm.rb +349 -0
- data/lib/simple_ga/version.rb +1 -1
- data/lib/simple_ga.rb +8 -3
- data/simple_ga-0.0.1.gem +0 -0
- data/spec/chromosome_spec.rb +27 -0
- data/spec/genetic_algorithm_spec.rb +24 -0
- metadata +27 -24
- data/lib/simple_ga/hello.rb +0 -9
- data/spec/test_spec.rb +0 -16
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZDg2OWU3YWFhNGVlZGU2OGUwNzkzMTFkMWQzMDE2OGQwZmMzMTRlMw==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9326ae742565530cf2b8dbb495cb4fc05f3d6cc0
|
4
|
+
data.tar.gz: 133e90581b775c54773b7a3cde6f09938ae6046e
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
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
|
data/lib/simple_ga/version.rb
CHANGED
data/lib/simple_ga.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
-
|
2
|
-
|
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
|
data/simple_ga-0.0.1.gem
ADDED
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.
|
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-
|
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/
|
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.
|
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
|
data/lib/simple_ga/hello.rb
DELETED
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
|