genetica 0.0.1.beta.1
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.
- data/lib/genetica.rb +4 -0
- data/lib/genetica/chromosome.rb +40 -0
- data/lib/genetica/chromosome_builder.rb +20 -0
- data/lib/genetica/population.rb +101 -0
- data/lib/genetica/population_builder.rb +44 -0
- metadata +52 -0
data/lib/genetica.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Genetica
|
2
|
+
class Chromosome
|
3
|
+
|
4
|
+
attr_reader :chromosome
|
5
|
+
|
6
|
+
def initialize(chromosome)
|
7
|
+
@chromosome = chromosome
|
8
|
+
end
|
9
|
+
|
10
|
+
def single_point_crossover(chromosome)
|
11
|
+
other_chromosome = chromosome.chromosome
|
12
|
+
locus = rand(other_chromosome.size) + 1
|
13
|
+
|
14
|
+
offspring_a = @chromosome.take(locus) + other_chromosome.last(@chromosome.size - locus)
|
15
|
+
offspring_b = other_chromosome.take(locus) + @chromosome.last(@chromosome.size - locus)
|
16
|
+
|
17
|
+
return Chromosome.new(offspring_a), Chromosome.new(offspring_b)
|
18
|
+
end
|
19
|
+
|
20
|
+
def mutate!(mutation_probability, alleles)
|
21
|
+
if mutation_probability > 0
|
22
|
+
@chromosome.collect! do |gene|
|
23
|
+
if rand.between? 0, mutation_probability
|
24
|
+
# Mutated Gene, we select a different gene from the alleles
|
25
|
+
(alleles - [gene]).sample
|
26
|
+
else
|
27
|
+
# Gene without mutation
|
28
|
+
gene
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
return @chromosome.join
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Genetica
|
2
|
+
class ChromosomeBuilder
|
3
|
+
|
4
|
+
attr_accessor :length
|
5
|
+
attr_accessor :alleles
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
# Default Chromosome values
|
9
|
+
@length = 8
|
10
|
+
@alleles = [0, 1]
|
11
|
+
end
|
12
|
+
|
13
|
+
def chromosome
|
14
|
+
chromosome = Array.new
|
15
|
+
@length.times { chromosome << @alleles.sample }
|
16
|
+
return Chromosome.new(chromosome)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Genetica
|
2
|
+
class Population
|
3
|
+
|
4
|
+
attr_reader :population
|
5
|
+
attr_reader :generation
|
6
|
+
|
7
|
+
attr_accessor :alleles
|
8
|
+
attr_accessor :crossover_probability
|
9
|
+
attr_accessor :mutation_probability
|
10
|
+
attr_accessor :fitness_function
|
11
|
+
|
12
|
+
def initialize(population)
|
13
|
+
@generation = 0
|
14
|
+
@population = population
|
15
|
+
end
|
16
|
+
|
17
|
+
def best_chromosome
|
18
|
+
@population.at @population_fitness.index(self.best_fitness)
|
19
|
+
end
|
20
|
+
|
21
|
+
def best_fitness
|
22
|
+
@population_fitness.max
|
23
|
+
end
|
24
|
+
|
25
|
+
def average_fitness
|
26
|
+
@population_fitness.inject(:+) / @population_fitness.size.to_f
|
27
|
+
end
|
28
|
+
|
29
|
+
def population_fitness
|
30
|
+
@population.collect { |chromosome| @fitness_function.call(chromosome) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def fitness_function=(new_fitness_function)
|
34
|
+
@fitness_function = new_fitness_function
|
35
|
+
@population_fitness = self.population_fitness
|
36
|
+
end
|
37
|
+
|
38
|
+
def population=(new_population)
|
39
|
+
@population = new_population
|
40
|
+
@population_fitness = self.population_fitness
|
41
|
+
end
|
42
|
+
|
43
|
+
def fitness_proportionate_selection
|
44
|
+
# FUTURE: With Ruby 1.9.3 you can use rand with ranges, e.g. rand 0.0..3.4
|
45
|
+
# Get random number
|
46
|
+
random_generator = Random.new
|
47
|
+
random_number = random_generator.rand 0.0..@population_fitness.inject(:+)
|
48
|
+
|
49
|
+
# Chromosome selection
|
50
|
+
fitness_counter = 0
|
51
|
+
@population.each_with_index do |chromosome, i|
|
52
|
+
fitness_counter += @population_fitness[i]
|
53
|
+
if fitness_counter >= random_number
|
54
|
+
return chromosome
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def run(generations=1)
|
60
|
+
generations.times do
|
61
|
+
# Generate a new chromosome population
|
62
|
+
population = Array.new
|
63
|
+
|
64
|
+
while population.size < @population.size
|
65
|
+
# 1. Selection Step
|
66
|
+
# Select a pair of parent chromosomes from the current population.
|
67
|
+
# This selection is 'with replacement', the same chromosome can be selected
|
68
|
+
# more than once to become a parent.
|
69
|
+
chromosome_a = self.fitness_proportionate_selection
|
70
|
+
chromosome_b = self.fitness_proportionate_selection
|
71
|
+
|
72
|
+
# 2. Crossover Step
|
73
|
+
# TODO: Maybe crossover probability check would be in the single_point_crossover of
|
74
|
+
# Chromosome class.
|
75
|
+
if @crossover_probability > 0 and rand.between? 0, @crossover_probability
|
76
|
+
offspring_a, offspring_b = chromosome_a.single_point_crossover chromosome_b
|
77
|
+
else
|
78
|
+
offspring_a, offspring_b = chromosome_a, chromosome_b
|
79
|
+
end
|
80
|
+
|
81
|
+
# 3. Mutation Step
|
82
|
+
offspring_a.mutate! @mutation_probability, @alleles
|
83
|
+
offspring_b.mutate! @mutation_probability, @alleles
|
84
|
+
|
85
|
+
# 4. Adding offsprings to new chromosome population
|
86
|
+
population << offspring_a << offspring_b
|
87
|
+
end
|
88
|
+
|
89
|
+
# If original population size is odd discard a random chromosome
|
90
|
+
population.delete_at rand population.size if @population.size.odd?
|
91
|
+
|
92
|
+
# Replacing chromosome population with the new one
|
93
|
+
self.population = population
|
94
|
+
|
95
|
+
# A new generation has been created
|
96
|
+
@generation += 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Genetica
|
2
|
+
class PopulationBuilder
|
3
|
+
|
4
|
+
# Population attributes
|
5
|
+
attr_accessor :size
|
6
|
+
attr_accessor :crossover_probability
|
7
|
+
attr_accessor :mutation_probability
|
8
|
+
attr_accessor :fitness_function
|
9
|
+
# Chromosome attributes
|
10
|
+
attr_accessor :chromosome_length
|
11
|
+
attr_accessor :chromosome_alleles
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
# Default Population values
|
15
|
+
@size = 20
|
16
|
+
@crossover_probability = 0.7
|
17
|
+
@mutation_probability = 0.001
|
18
|
+
@fitness_function = nil
|
19
|
+
# Default Chromosome values
|
20
|
+
@chromosome_length = 8
|
21
|
+
@chromosome_alleles = [0, 1]
|
22
|
+
end
|
23
|
+
|
24
|
+
def population
|
25
|
+
# Generating Chromosome population
|
26
|
+
chromosome_builder = ChromosomeBuilder.new
|
27
|
+
chromosome_builder.length = @chromosome_length
|
28
|
+
chromosome_builder.alleles = @chromosome_alleles
|
29
|
+
|
30
|
+
chromosome_population = Array.new
|
31
|
+
@size.times { chromosome_population << chromosome_builder.chromosome }
|
32
|
+
|
33
|
+
# Generating Population
|
34
|
+
population = Population.new chromosome_population
|
35
|
+
population.alleles = @chromosome_alleles
|
36
|
+
population.crossover_probability = @crossover_probability
|
37
|
+
population.mutation_probability = @mutation_probability
|
38
|
+
population.fitness_function = @fitness_function
|
39
|
+
|
40
|
+
return population
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: genetica
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.beta.1
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- José Francisco Calvo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-08 00:00:00.000000000 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
description: Genetica is a library to create and use Genetic Algorithms solutions
|
16
|
+
using Ruby language.
|
17
|
+
email: josefranciscocalvo@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- lib/genetica.rb
|
23
|
+
- lib/genetica/chromosome.rb
|
24
|
+
- lib/genetica/chromosome_builder.rb
|
25
|
+
- lib/genetica/population.rb
|
26
|
+
- lib/genetica/population_builder.rb
|
27
|
+
has_rdoc: true
|
28
|
+
homepage: http://dev.monsterzen.com/projects/genetica.html
|
29
|
+
licenses: []
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>'
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.3.1
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 1.6.2
|
49
|
+
signing_key:
|
50
|
+
specification_version: 3
|
51
|
+
summary: The Ruby Genetic Algorithms Gem.
|
52
|
+
test_files: []
|