Permalink
Browse files

added test skeleton

  • Loading branch information...
1 parent 8853616 commit 620aee252355b224dbedba21a08e3310a154c932 David Heitzman committed Dec 9, 2012
Showing with 162 additions and 145 deletions.
  1. +4 −145 ruby/gahelloworld.rb
  2. +128 −0 ruby/lib/gahelloworld.rb
  3. +30 −0 ruby/test/gahelloworld_test.rb
View
@@ -1,131 +1,4 @@
-
-module GAHelloWorld
- RAND_SEED=srand
- TARGET_GENE='Hello World!'
- ALLOWED_LETTERS = (32..122).to_a.map{|i| i.chr}
-
- class Chromosome
- attr_reader :gene_ary, :target_ary, :gene
-
- class << self
- def gen_random()
- str=''
- TARGET_GENE.size.times do |i|
- str << ALLOWED_LETTERS[rand(ALLOWED_LETTERS.size)-1]
- end
- Chromosome.new(str)
- end
-
- def to_int_array(str)
- #convenience method to get an array of strings for any string, compatible with ruby 1.9.3 and 1.8.7
- out=[]
- str.each_byte do |c| out << c end
- out
- end
- end
-
- def initialize(str='')
- @gene=str == '' ? Chromosome.gen_random.gene : str
- @gene_ary ||= Chromosome.to_int_array(@gene)
- @target_ary ||= Chromosome.to_int_array(TARGET_GENE)
- end
-
- def fitness
- @fitness ||=
- begin
- diff=0
- gene_ary.size.times do |i| diff += (gene_ary[i].to_i - target_ary[i].to_i).abs end
- diff
- end
- end
-
- def mate partner
- #split the chromosome at some random point.
- #create two new chromosomes and return them.
- # chrom1 gets the first half from itself and the second from the partner
- # chrom2 gets the first half from the partner and the second from itself
- pivot = rand( gene_ary.size() - 1)
- ng1= gene[0..pivot] + partner.gene[pivot+1..-1]
- ng2= partner.gene[0..pivot] + gene[pivot+1..-1]
- [ Chromosome.new(ng1) , Chromosome.new(ng2) ]
- end
-
- def mutate
- newstr=@gene.clone
- newstr[rand(@gene.size)] = ALLOWED_LETTERS[ rand(ALLOWED_LETTERS.size) ]
- Chromosome.new newstr
- end
-
-
- end
-
- class Population
- attr_accessor :population
- Tourney_size = 3
-
- def each(&block)
- @population.each do |i|
- block.call(i)
- end
- end
-
- def initialize(size, crossover, elitism, mutation, seed)
- @size = size
- @seed = seed
- srand @seed
- @crossover=crossover
- @elitism=elitism
- @mutation=mutation
- buf = []
- @size.times do |i|
- buf << Chromosome::gen_random()
- end
- # puts @seed.to_s
- @population = buf.sort!{ |a,b| a.fitness <=> b.fitness }
- end
-
- def tournament_selection
- best = @population[rand(@population.size)]
- Tourney_size.times do |i|
- cont = @population[rand(@population.size)]
- best = cont if cont.fitness < best.fitness
- end
- best
- end
-
- def evolve
- # inspect
- elitism_mark=(@elitism*@population.size).to_i - 1
- buf = @population[0..elitism_mark]
- sub_pop=@population[elitism_mark+1..-1]
- sub_pop.each_with_index do |chrom, ind|
- if rand <= @crossover
- parent1=tournament_selection
- parent2=tournament_selection
- children = parent1.mate parent2
- children[0] = children[0].mutate if rand < @mutation
- children[1] = children[1].mutate if rand < @mutation
- buf += children
- else
- chrom = chrom.mutate if rand < @mutation
- buf << chrom
- end
- break if buf.size >= @size
- end
- @population = (buf+@population[elitism_mark+1...@size]).sort!{|a,b| a.fitness <=> b.fitness}
- # inspect
- end
-
- def inspect
- ind ||= -1
- @population[0,5].each do |chrome|
- ind += 1
- puts "[" + ind.to_s + "] "+chrome.gene + ": fitness => " + chrome.fitness.to_s
- end
- end
- end
-
-end
+require 'lib/gahelloworld'
# puts ARGV.inspect
if ARGV.empty? || ARGV.include?("-h") || ARGV.include?("--help")
puts "Genetic Algorithm Hello World. Ruby version by David Heitzman, 2012"
@@ -163,7 +36,8 @@ def inspect
max_generations = 16384
pop = GAHelloWorld::Population.new(size, crossover, elitism, mutation, seed)
curgen = 1
- begin
+ finished=false
+ while curgen <= 16384 && !finished
finished=false
puts("Generation #{curgen}: #{pop.population[0].gene}. Fitness: #{pop.population[0].fitness}" )
if pop.population[0].fitness == 0
@@ -174,20 +48,5 @@ def inspect
end
curgen += 1
puts "Reached max generation (#{max_generations}). Current best: #{pop.population.first.gene}" if curgen > max_generations
- end while curgen <= 16384 && !finished
-
-# tests
-# 100.times do |i|
-# @test_chrom = (GAHelloWorld::Chromosome.gen_random)
-# @test_chrom2 = (GAHelloWorld::Chromosome.gen_random)
-# puts @test_chrom.gene.inspect
-# @test_chrom = @test_chrom.mutate
-# puts @test_chrom.gene.inspect
-# kid=@test_chrom.mate(@test_chrom2)
-# puts @test_chrom2.gene.inspect
-# puts kid.first.gene
-# puts kid.last.gene
-# end
-
-# pop.inspect
+ end
@@ -0,0 +1,128 @@
+module GAHelloWorld
+ RAND_SEED=srand
+ TARGET_GENE='Hello World!'
+ ALLOWED_LETTERS = (32..122).to_a.map{|i| i.chr}
+
+ class Chromosome
+ attr_reader :gene_ary, :target_ary, :gene
+
+ class << self
+ def gen_random()
+ str=''
+ TARGET_GENE.size.times do |i|
+ str << ALLOWED_LETTERS[rand(ALLOWED_LETTERS.size)-1]
+ end
+ Chromosome.new(str)
+ end
+
+ def to_int_array(str)
+ #convenience method to get an array of strings for any string, compatible with ruby 1.9.3 and 1.8.7
+ out=[]
+ str.each_byte do |c| out << c end
+ out
+ end
+ end
+
+ def initialize(str='')
+ @gene=str == '' ? Chromosome.gen_random.gene : str
+ @gene_ary ||= Chromosome.to_int_array(@gene)
+ @target_ary ||= Chromosome.to_int_array(TARGET_GENE)
+ end
+
+ def fitness
+ @fitness ||=
+ begin
+ #normal -- matches the target string
+ diff=0
+ gene_ary.size.times do |i| diff += (gene_ary[i].to_i - target_ary[i].to_i).abs end
+ diff
+ end
+ end
+
+ def mate partner
+ #split the chromosome at some random point.
+ #create two new chromosomes and return them.
+ # chrom1 gets the first half from itself and the second from the partner
+ # chrom2 gets the first half from the partner and the second from itself
+ pivot = rand( gene_ary.size() - 1)
+ ng1= gene[0..pivot] + partner.gene[pivot+1..-1]
+ ng2= partner.gene[0..pivot] + gene[pivot+1..-1]
+ [ Chromosome.new(ng1) , Chromosome.new(ng2) ]
+ end
+
+ def mutate
+ newstr=@gene.clone
+ newstr[rand(@gene.size)] = ALLOWED_LETTERS[ rand(ALLOWED_LETTERS.size) ]
+ Chromosome.new newstr
+ end
+
+
+ end
+
+ class Population
+ attr_accessor :population
+ Tourney_size = 3
+
+ def each(&block)
+ @population.each do |i|
+ block.call(i)
+ end
+ end
+
+ def initialize(size, crossover, elitism, mutation, seed)
+ @size = size
+ @seed = seed
+ srand @seed
+ @crossover=crossover
+ @elitism=elitism
+ @mutation=mutation
+ buf = []
+ @size.times do |i|
+ buf << Chromosome::gen_random()
+ end
+ # puts @seed.to_s
+ @population = buf.sort!{ |a,b| a.fitness <=> b.fitness }
+ end
+
+ def tournament_selection
+ best = @population[rand(@population.size)]
+ Tourney_size.times do |i|
+ cont = @population[rand(@population.size)]
+ best = cont if cont.fitness < best.fitness
+ end
+ best
+ end
+
+ def evolve
+ # inspect
+ elitism_mark=(@elitism*@population.size).to_i - 1
+ buf = @population[0..elitism_mark]
+ sub_pop=@population[elitism_mark+1..-1]
+ sub_pop.each_with_index do |chrom, ind|
+ if rand <= @crossover
+ parent1=tournament_selection
+ parent2=tournament_selection
+ children = parent1.mate parent2
+ children[0] = children[0].mutate if rand < @mutation
+ children[1] = children[1].mutate if rand < @mutation
+ buf += children
+ else
+ chrom = chrom.mutate if rand < @mutation
+ buf << chrom
+ end
+ break if buf.size >= @size
+ end
+ @population = (buf+@population[elitism_mark+1...@size]).sort!{|a,b| a.fitness <=> b.fitness}
+ # inspect
+ end
+
+ def inspect
+ ind ||= -1
+ @population[0,5].each do |chrome|
+ ind += 1
+ puts "[" + ind.to_s + "] "+chrome.gene + ": fitness => " + chrome.fitness.to_s
+ end
+ end
+ end
+
+end
@@ -0,0 +1,30 @@
+require 'test/unit'
+require File.expand_path("../../lib/gahelloworld",__FILE__ )
+
+class GAHelloWorldTest < Test::Unit::TestCase
+
+ def test_should_accept_command_line_inputs
+ assert_equal 1,0
+ end
+
+ def test_should_accept_command_line_inputs
+ assert_equal 1,0
+ end
+
+end
+
+# tests
+# 100.times do |i|
+# @test_chrom = (GAHelloWorld::Chromosome.gen_random)
+# @test_chrom2 = (GAHelloWorld::Chromosome.gen_random)
+# puts @test_chrom.gene.inspect
+# @test_chrom = @test_chrom.mutate
+# puts @test_chrom.gene.inspect
+# kid=@test_chrom.mate(@test_chrom2)
+# puts @test_chrom2.gene.inspect
+# puts kid.first.gene
+# puts kid.last.gene
+# end
+
+# pop.inspect
+

0 comments on commit 620aee2

Please sign in to comment.