evopop 0.0.5 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04d8cc00d713a77a686106e3be50d26d95889ec0
4
- data.tar.gz: 0ee8bc2bca81622f24aa80184fa942fce901064d
3
+ metadata.gz: 5e6f9dc9b3385fbd06d69e3f4c8d062dab99b93b
4
+ data.tar.gz: e6ed6c011086a7901b5db7cad7c1e818827b7520
5
5
  SHA512:
6
- metadata.gz: 2cae28bdfd5bc8d7e9aa431bfd2ff5765cbe7c5e4a7e2e1f28fb07269b8b42daf90e0554c772dfbe060735c3a278937bdf59752a192c1e623dacce55fd51679f
7
- data.tar.gz: 6d418afe3bf3d4ec71e1e0f10d6877528fba2206759672d6299b27957e3d4f7e508740c5717fb13fab832933d4ebde93dbadf20849f52198950153f189ad9600
6
+ metadata.gz: 7cbcf3830e9c614853391008bce76aba3e55a74290cdc9059386af79a3681999fcc53c4bbda2e1c159a82d73300197f52fb2a9b9d45264e0976f84cb5f3a5c18
7
+ data.tar.gz: eb45100eee7f64bd1bfa03a2fbc3d050f852beaeb32c2e5f94ba6046773bbf06b0467ba19c26443c8018dbea391bce3ac8cbc3d7a3951da57e5a98fb0bac552d
data/README.md CHANGED
@@ -1,7 +1,11 @@
1
+ [![Build Status](https://travis-ci.org/elvinlucero/evopop.svg?branch=master)](https://travis-ci.org/elvinlucero/evopop)
2
+ [![Code Climate](https://codeclimate.com/github/elvinlucero/evopop/badges/gpa.svg)](https://codeclimate.com/github/elvinlucero/evopop)
3
+
1
4
  Evopop
2
5
  ------------------------
3
6
 
4
- This is a library for implementing simple genetic algorithms to evolve over a fitness function.
7
+ This is a library for implementing simple genetic algorithms to evolve
8
+ over a fitness function.
5
9
 
6
10
 
7
11
  ``` ruby
@@ -9,7 +13,7 @@ This is a library for implementing simple genetic algorithms to evolve over a fi
9
13
  require 'evopop'
10
14
 
11
15
  # Initialize the population to be trained with good defaults.
12
- population = Population.new
16
+ population = Evopop::Population.new
13
17
  population.population_size = 1000
14
18
  population.dna_len = 2
15
19
  population.max_generations = 1000
@@ -19,7 +23,7 @@ population.mutation_range_min = -10.0
19
23
  population.mutation_range_max = 10.0
20
24
  population.mutation_num = 10
21
25
  population.crossover_params = { ordinal: (DNA_LEN / 2) }.freeze
22
- population.crossover_function = Crossover.method(:one_point)
26
+ population.crossover_function = Evopop::Crossover.method(:one_point)
23
27
  population.fitness_function = proc do |dna|
24
28
  Math.sin(dna[0]) + Math.cos(dna[1])
25
29
  end
@@ -36,7 +40,9 @@ end
36
40
 
37
41
  # Sort and print out candidate with highest fitness in the last generation.
38
42
  population.train
39
- puts "Finished #{population.max_generations} generations with the fittest candidate with a dna of #{population.candidates[0].dna} and a fitness of #{population.candidates[0].fitness}."
43
+ puts "Finished #{population.max_generations} generations with the fittest
44
+ candidate with a dna of #{population.candidates[0].dna} and a fitness
45
+ of #{population.candidates[0].fitness}."
40
46
 
41
47
 
42
48
  ```
@@ -1,11 +1,22 @@
1
- # Public: Represents a candidate in the population. Candidates are abstracted
2
- # as a simple data structure which contains the DNA and fitness over the
3
- # fitness function.
4
- class Candidate
5
- attr_accessor :dna, :fitness
1
+ # frozen_string_literal: true
6
2
 
7
- # Simple initialization of candidate object.
8
- def initialize(dna = [])
9
- @dna = dna
3
+ module Evopop
4
+ # Public: Represents a candidate in the population.Evopop::Candidates are
5
+ # abstracted as a simple data structure which contains the DNA and fitness
6
+ # over the fitness function.
7
+ class Candidate
8
+ attr_accessor :dna, :fitness
9
+
10
+ # Simple initialization of candidate object.
11
+ def initialize(dna)
12
+ @dna = dna
13
+ end
14
+
15
+ def compose_parent_dna(c0, c1)
16
+ # Compose the dna of the first child from the first chunk of the
17
+ # first candidate and the second chunk of the second candidate
18
+ # dna0_left = c0.dna.take(ordinal)
19
+ # dna1_right = c1.dna.drop(ordinal)
20
+ end
10
21
  end
11
22
  end
@@ -1,101 +1,125 @@
1
- # Represents a collection of well known crossover functions.
2
- #
3
- module Crossover
4
- # Perform 1 point crossover for a pair of candidates at the ordinal.
5
- # http://en.wikipedia.org/wiki/Crossover_(genetic_algorithm)#One-point_crossover
6
- def self.one_point(candidates, params)
7
- ordinal = params[:ordinal]
8
-
9
- # Compose the dna of the first child from the first chunk of the
10
- # first candidate and the second chunk of the second candidate
11
- dna0_left = candidates[0].dna.take(ordinal)
12
- dna1_right = candidates[1].dna.drop(ordinal)
13
-
14
- # Compose the dna of the second child from the first chunk of the
15
- # first candidate and the second chunk of the second candidate
16
- dna1_left = candidates[1].dna.take(ordinal)
17
- dna0_right = candidates[0].dna.drop(ordinal)
18
-
19
- # Initialize and assign DNA to children.
20
- children = [Candidate.new(dna0_left + dna1_right),
21
- Candidate.new(dna1_left + dna0_right)]
22
-
23
- children
24
- end
1
+ # frozen_string_literal: true
25
2
 
26
- # Perform two point crossover over a pair of candidates. Will output two
27
- # children with genes spliced over the crossover points.
3
+ module Evopop
4
+ # Represents a collection of well known crossover functions.
5
+ #
6
+ module Crossover
7
+ # Perform 1 point crossover for a pair of candidates at the ordinal.
8
+ # http://en.wikipedia.org/wiki/Crossover_(genetic_algorithm)#One-point_crossover
9
+ def self.one_point(candidates, params)
10
+ ordinal = params[:ordinal]
11
+
12
+ # Compose the dna of the first child from the first chunk of the
13
+ # first candidate and the second chunk of the second candidate
14
+ dna_a_left = candidates[0].dna.take(ordinal)
15
+ dna_b_right = candidates[1].dna.drop(ordinal)
16
+
17
+ # Compose the dna of the second child from the first chunk of the
18
+ # first candidate and the second chunk of the second candidate
19
+ dna_b_left = candidates[1].dna.take(ordinal)
20
+ dna_a_right = candidates[0].dna.drop(ordinal)
21
+
22
+ min_range = candidates[0].dna.min_range
23
+ max_range = candidates[1].dna.max_range
24
+
25
+ min_mutation = candidates[1].dna.min_mutation
26
+ max_mutation = candidates[1].dna.max_mutation
27
+
28
+ dna_a = Evopop::Dna.create(min_range, max_range, min_mutation, max_mutation, dna_a_left + dna_b_right)
29
+ dna_b = Evopop::Dna.create(min_range, max_range, min_mutation, max_mutation, dna_b_left + dna_a_right)
30
+
31
+ # Initialize and assign DNA to children.
32
+ [
33
+ Evopop::Candidate.new(dna_a),
34
+ Evopop::Candidate.new(dna_b)
35
+ ]
36
+ end
28
37
 
29
- def self.two_point(candidates, params)
30
- # Ordinals should be stored in params as a comma separated list. I.e. "1,2".
31
- # Make sure to sort.
32
- ordinals = params[:ordinals].split(',').sort.collect(&:to_i)
38
+ # Perform two point crossover over a pair of candidates. Will output two
39
+ # children with genes spliced over the crossover points.
33
40
 
34
- # Initialize and assign the DNA of the children.
35
- cdna0 = candidates[0].dna
36
- cdna1 = candidates[1].dna
41
+ def self.two_point(candidates, params)
42
+ # Ordinals should be stored in params as a comma separated list. I.e. "1,2".
43
+ # Make sure to sort.
44
+ ordinals = params[:ordinals].split(',').sort.collect(&:to_i)
37
45
 
38
- children = [
39
- Candidate.new(cdna0[0..ordinals[0]] + cdna1[(ordinals[0] + 1)..ordinals[1]] + cdna0[(ordinals[1] + 1)..cdna0.length - 1]),
40
- Candidate.new(cdna1[0..ordinals[0]] + cdna0[(ordinals[0] + 1)..ordinals[1]] + cdna1[(ordinals[1] + 1)..cdna1.length - 1])
41
- ]
46
+ # Initialize and assign the DNA of the children.
47
+ cdna_a = candidates[0].dna
48
+ cdna_b = candidates[1].dna
42
49
 
43
- children
44
- end
50
+ [
51
+ Evopop::Candidate.new(combine_on_ordinal(cdna_a, cdna_b, ordinals)),
52
+ Evopop::Candidate.new(combine_on_ordinal(cdna_b, cdna_a, ordinals))
53
+ ]
54
+ end
45
55
 
46
- # Perform n_point crossover for a pair of candidates. Will output two children from the n_point crossover.
47
- #
48
- # Example:
49
- # n_point
50
- def self.n_point(candidates, params)
51
- ordinals = params[:ordinals].split(',').sort.collect(&:to_i)
56
+ def self.combine_on_ordinal(dna_a, dna_b, ordinals)
57
+ # TODO: Would this be better in dna.rb?
58
+ dna_a[0..ordinals[0]] + dna_b[(ordinals[0] + 1)..ordinals[1]] + dna_a[(ordinals[1] + 1)..dna_a.length - 1]
59
+ end
52
60
 
53
- pdna0 = candidates[0].dna
54
- pdna1 = candidates[1].dna
61
+ # Perform n_point crossover for a pair of candidates. Will output two children from the n_point crossover.
62
+ #
63
+ # Example:
64
+ # n_point
65
+ def self.n_point(candidates, params)
66
+ ordinals = params[:ordinals].split(',').sort.collect(&:to_i)
55
67
 
56
- dna_length = candidates[0].dna.length
68
+ pdna_a = candidates[0].dna
69
+ pdna_b = candidates[1].dna
57
70
 
58
- cdna0 = []
59
- cdna1 = []
71
+ dna_length = candidates[0].dna.length
60
72
 
61
- old_ordinal = 0
62
- synchronous = ordinals[0] == 0 ? false : true
73
+ cdna_a = []
74
+ cdna_b = []
63
75
 
64
- ordinals.each do |i|
65
- if synchronous
66
- cdna0 += pdna0[old_ordinal..i]
67
- cdna1 += pdna1[old_ordinal..i]
68
- else
69
- cdna0 += pdna1[old_ordinal..i]
70
- cdna1 += pdna0[old_ordinal..i]
71
- end
76
+ old_ordinal = 0
77
+ synchronous = ordinals[0] == 0 ? false : true
72
78
 
73
- synchronous = !synchronous
74
- old_ordinal = i + 1
79
+ ordinals.each do |i|
80
+ n_ordinal = old_ordinal..i
75
81
 
76
- next if ordinals.last != old_ordinal - 1
82
+ cdna_a, cdna_b = build_dna_by_synchronous(cdna_a, cdna_b, pdna_a, pdna_b, n_ordinal, synchronous)
77
83
 
78
- if synchronous
79
- cdna0 += pdna0[old_ordinal..dna_length - 1]
80
- cdna1 += pdna1[old_ordinal..dna_length - 1]
81
- else
82
- cdna0 += pdna1[old_ordinal..dna_length - 1]
83
- cdna1 += pdna0[old_ordinal..dna_length - 1]
84
+ synchronous = !synchronous
85
+ next_ordinal = i + 1
86
+
87
+ next if ordinals.last != next_ordinal - 1
88
+
89
+ ordinal_range = next_ordinal..(dna_length - 1)
90
+ cdna_a, cdna_b = build_dna_by_synchronous(cdna_a, cdna_b, pdna_a, pdna_b, ordinal_range, synchronous)
84
91
  end
85
- end
86
92
 
87
- [Candidate.new(cdna0), Candidate.new(cdna1)]
88
- end
93
+ [
94
+ Evopop::Candidate.new(cdna_a),
95
+ Evopop::Candidate.new(cdna_b)
96
+ ]
97
+ end
89
98
 
90
- def self.average(candidates, _params)
91
- child = Candidate.new
92
- dna_length = candidates[0].dna.length
99
+ def self.build_dna_by_synchronous(cdna_a, cdna_b, pdna_a, pdna_b, ordinal_range, synchronous)
100
+ pdnas = [pdna_a, pdna_b]
101
+ pdnas.reverse! unless synchronous
102
+ cdna_a += pdnas[0][ordinal_range]
103
+ cdna_b += pdnas[1][ordinal_range]
93
104
 
94
- (0...dna_length).each do |j|
95
- # Initialize the dna of the child with the average of the parents' dna.
96
- child.dna << (candidates[0].dna[j] + candidates[1].dna[j]) / 2.0
105
+ [cdna_a, cdna_b]
97
106
  end
98
107
 
99
- [child]
108
+ def self.average(candidates, _params)
109
+ new_dna = Evopop::Dna.new(
110
+ candidates[0].dna.min_range,
111
+ candidates[0].dna.max_range,
112
+ candidates[0].dna.min_mutation,
113
+ candidates[0].dna.max_mutation,
114
+ candidates[0].dna.length
115
+ )
116
+ new_dna.dna = []
117
+ (0...candidates[0].dna.length).each do |j|
118
+ # Initialize the dna of the child with the average of the parents' dna.
119
+ new_dna.dna << (candidates[0].dna[j] + candidates[1].dna[j]) / 2.0
120
+ end
121
+
122
+ [Evopop::Candidate.new(new_dna)]
123
+ end
100
124
  end
101
125
  end
data/lib/evopop/dna.rb ADDED
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Evopop
4
+ # Represents a Dna structure, like an array of floating point values
5
+ class Dna
6
+ attr_accessor :dna, :dna_len, :min_range, :max_range, :min_mutation, :max_mutation
7
+
8
+ def initialize(min_range, max_range, min_mutation, max_mutation, dna_len)
9
+ # TODO: Extract these to a DnaProperties class or something so we don't
10
+ # have to couple parameter passsing so much.
11
+ @min_range = min_range
12
+ @max_range = max_range
13
+ @min_mutation = min_mutation
14
+ @max_mutation = max_mutation
15
+ @dna = []
16
+ @dna_len = dna_len
17
+
18
+ dna_len_range.each do
19
+ @dna << random_dna_val
20
+ end
21
+ end
22
+
23
+ def self.create(min_range, max_range, min_mutation, max_mutation, dna)
24
+ new_dna = new(min_range, max_range, min_mutation, max_mutation, dna.size)
25
+ new_dna.dna = dna
26
+ new_dna
27
+ end
28
+
29
+ def dna_len_range
30
+ 0...@dna_len
31
+ end
32
+
33
+ def random_dna_val
34
+ Random.rand(@min_range...@max_range)
35
+ end
36
+
37
+ def random_mutation_val
38
+ Random.rand(@min_mutation...@max_mutation)
39
+ end
40
+
41
+ def mutate(i)
42
+ @dna[i] += [random_mutation_val, -1 * random_mutation_val].sample
43
+ end
44
+
45
+ def length
46
+ @dna.length
47
+ end
48
+
49
+ def take(num)
50
+ @dna.take(num)
51
+ end
52
+
53
+ def drop(ordinal)
54
+ @dna.drop(ordinal)
55
+ end
56
+
57
+ def [](key)
58
+ @dna[key]
59
+ end
60
+
61
+ def []=(key, value)
62
+ @dna[key] = value
63
+ end
64
+
65
+ def ==(other)
66
+ @dna == other.dna
67
+ end
68
+
69
+ def to_s
70
+ @dna.to_s
71
+ end
72
+ end
73
+ end
@@ -1,110 +1,108 @@
1
-
2
- # Represents the population that is being trained. Has various methods
3
- # relevant to training.
4
- #
5
- #
6
- # Examples
7
- # population = Population.new
8
- # ... initialize population with parameters ...
9
- # population.train
10
- # population.crossover
11
- # population.mutate
12
- class Population
13
- attr_accessor :candidates, :population_size, :max_generations, :crossover_function, :crossover_params, :initial_range_min, :initial_range_max, :mutation_range_min, :mutation_range_max, :mutation_num, :fitness_function, :dna_len, :average_fitness
14
-
15
- # Initializes the attributes with default values. This is not guaranteed
16
- # to reach maxima.
17
- def initialize
18
- @average_fitness = []
19
- @population_size = 100
20
- @max_generations = 100
21
- @initial_range_min = -100
22
- @initial_range_max = 100
23
- @mutation_range_min = -10
24
- @mutation_range_max = 10
25
- @mutation_num = (0.10 * @population_size).to_i
26
- @dna_len = 1
27
- @crossover_params = { ordinal: (@dna_len / 2) }
28
-
29
- @crossover_function = Crossover.method(:one_point)
30
- @fitness_function = proc do |dna|
31
- Math.sin(dna[0])
32
- end
33
-
34
- create
35
-
36
- self
37
- end
38
-
39
- # Creates a new population class. Should be called after all the
40
- # parameters have been set to the attributes.
41
- def create
42
- @candidates = Array.new(@population_size) do
43
- candidate = Candidate.new
44
- (0...@dna_len).each do
45
- candidate.dna << Random.rand(@initial_range_min...@initial_range_max)
1
+ # frozen_string_literal: true
2
+
3
+ module Evopop
4
+ # Represents the population that is being trained. Has various methods
5
+ # relevant to training.
6
+ #
7
+ #
8
+ # Examples
9
+ # population = Evopop::Population.new
10
+ # ... initialize population with parameters ...
11
+ # population.train
12
+ # population.crossover
13
+ # population.mutate
14
+ class Population
15
+ attr_accessor :candidates, :population_size, :max_generations,
16
+ :crossover_function, :crossover_params, :initial_range_min,
17
+ :initial_range_max, :mutation_range_min, :mutation_range_max,
18
+ :mutation_num, :fitness_function, :dna_len, :average_fitness
19
+
20
+ # Initializes the attributes with default values. This is not guaranteed
21
+ # to reach maxima.
22
+ def initialize
23
+ Evopop.config.instance_variables.each do |iv|
24
+ instance_variable_set(
25
+ iv,
26
+ Evopop.config.instance_variable_get(iv)
27
+ )
46
28
  end
47
- candidate
29
+ create
30
+ self
48
31
  end
49
- end
50
32
 
51
- # Determines the fitness of the population and thereafter sorts it
52
- # based on fitness descdending (high fitness first, low fitness last).
53
- def train
54
- average_fitness = 0
55
- @candidates.each do |c|
56
- c.fitness = fitness_function.call(c.dna)
57
- average_fitness += + c.fitness
33
+ # Creates a new set of population. Should be called after all the
34
+ # parameters have been set to the attributes.
35
+ def create
36
+ @candidates = Array.new(@population_size) do
37
+ dna = Evopop::Dna.new(
38
+ @initial_range_min,
39
+ @initial_range_max,
40
+ @mutation_range_min,
41
+ @mutation_range_max,
42
+ @dna_len
43
+ )
44
+ candidate = Evopop::Candidate.new(dna)
45
+ candidate
46
+ end
58
47
  end
59
48
 
60
- average_fitness /= @population_size
61
-
62
- @average_fitness << average_fitness
63
-
64
- @candidates = @candidates.sort_by(&:fitness)
65
- @candidates = @candidates.reverse
66
- end
49
+ # Determines the fitness of the population and thereafter sorts it
50
+ # based on fitness descdending (high fitness first, low fitness last).
51
+ def train
52
+ average_fitness = 0
53
+ @candidates.each do |c|
54
+ c.fitness = fitness_function.call(c.dna)
55
+ average_fitness += + c.fitness
56
+ end
67
57
 
68
- # Performs simple mechanism of crossover - in this case picks two
69
- # random candidates in from a top percentile of the population and
70
- # performs one point crossover, producing new offspring equal to the
71
- # population size attribute.
72
- def crossover
73
- # Define the candidates that can have children.
74
- @candidates = @candidates.take((@population_size * 0.75).to_i)
58
+ average_fitness /= @population_size
75
59
 
76
- new_generation = []
60
+ @average_fitness << average_fitness
77
61
 
78
- (0...@population_size).each do
79
- # For each of the top 75% of the population take 2
80
- couple = @candidates.sample(2)
81
- params = @crossover_params
62
+ @candidates = @candidates.sort_by(&:fitness)
63
+ @candidates = @candidates.reverse
64
+ end
82
65
 
83
- children = @crossover_function.call(couple, params)
66
+ # Performs simple mechanism of crossover - in this case picks two
67
+ # random candidates in from a top percentile of the population and
68
+ # performs one point crossover, producing new offspring equal to the
69
+ # population size attribute.
70
+ def crossover
71
+ new_generation = []
72
+
73
+ # For all the top candidates, take the top 2 and crossover
74
+ (0...@population_size).each do
75
+ children = @crossover_function.call(top_candidates.sample(2), @crossover_params)
76
+ new_generation += children
77
+
78
+ if new_generation.length >= population_size
79
+ new_generation = new_generation.take(population_size)
80
+ break
81
+ end
82
+ end
84
83
 
85
- new_generation += children
84
+ @candidates = new_generation
85
+ end
86
86
 
87
- # When we go above set population_size, take the first population_size
88
- # candidates, ignore the rest.
89
- if new_generation.length >= population_size
90
- new_generation = new_generation.take(population_size)
91
- break
87
+ # Performs simple mutation over the next generation. In this case,
88
+ # it either adds or substracts an amount to each dimension given the
89
+ # mutation range attributes.
90
+ def mutate
91
+ mutated_candidates.each do |c|
92
+ c.dna.dna_len_range.each do |i|
93
+ c.dna.mutate(i)
94
+ end
92
95
  end
93
96
  end
94
97
 
95
- @candidates = new_generation
96
- end
98
+ private
97
99
 
98
- # Performs simple mutation over the next generation. In this case,
99
- # it either adds or substracts an amount to each dimension given the
100
- # mutation range attributes.
101
- def mutate
102
- mutated = @candidates.sample(mutation_num)
100
+ def top_candidates
101
+ @candidates.take((@population_size * 0.75).to_i)
102
+ end
103
103
 
104
- mutated.each do |c|
105
- (0...@dna_len).each do |i|
106
- c.dna[i] = c.dna[i] + Random.rand(@mutation_range_min...@mutation_range_max)
107
- end
104
+ def mutated_candidates
105
+ @candidates.sample(@mutation_num)
108
106
  end
109
107
  end
110
108
  end
data/lib/evopop.rb CHANGED
@@ -1,7 +1,48 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'evopop/population'
2
4
  require 'evopop/candidate'
3
5
  require 'evopop/crossover'
6
+ require 'evopop/dna'
4
7
 
5
8
  # Toplevel class for evopop project
6
9
  module Evopop
10
+ class << self
11
+ attr_accessor :config
12
+ end
13
+
14
+ def self.popconfig
15
+ @config ||= PopulationConfig.new
16
+ yield(@config)
17
+ end
18
+
19
+ # Defines the configuration to be available to all of Evopop
20
+ class PopulationConfig
21
+ attr_accessor :average_fitness, :population_size, :max_generations,
22
+ :initial_range_min, :initial_range_max, :mutation_range_min,
23
+ :mutation_range_max, :mutation_num, :dna_len,
24
+ :crossover_params, :crossover_function, :fitness_function
25
+
26
+ def initialize
27
+ @average_fitness = []
28
+ @population_size = 100
29
+ @max_generations = 100
30
+ @initial_range_min = -100
31
+ @initial_range_max = 100
32
+ @mutation_range_min = -10
33
+ @mutation_range_max = 10
34
+ @mutation_num = (0.10 * @population_size).to_i
35
+ @dna_len = 1
36
+ @crossover_params = { ordinal: (@dna_len / 2) }
37
+
38
+ @crossover_function = Evopop::Crossover.method(:one_point)
39
+ @fitness_function = proc do |dna|
40
+ Math.sin(dna[0])
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ Evopop.popconfig do |config|
47
+ # Configure evopop here.
7
48
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evopop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elvin Lucero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-24 00:00:00.000000000 Z
11
+ date: 2017-07-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A simple library for implementing simple genetic algorithms.
14
- email: elvin+evopop@pluots.io
14
+ email: elvin+evopop@1au.io
15
15
  executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
@@ -21,6 +21,7 @@ files:
21
21
  - lib/evopop.rb
22
22
  - lib/evopop/candidate.rb
23
23
  - lib/evopop/crossover.rb
24
+ - lib/evopop/dna.rb
24
25
  - lib/evopop/population.rb
25
26
  homepage: https://rubygems.org/gems/evopop
26
27
  licenses:
@@ -42,7 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
42
43
  version: '0'
43
44
  requirements: []
44
45
  rubyforge_project:
45
- rubygems_version: 2.4.5.1
46
+ rubygems_version: 2.6.12
46
47
  signing_key:
47
48
  specification_version: 4
48
49
  summary: A simple library for implementing simple genetic algorithms.