Skip to content

Instantly share code, notes, and snippets.

@lopopolo
Created April 3, 2012 08:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lopopolo/2290546 to your computer and use it in GitHub Desktop.
Save lopopolo/2290546 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
POPSIZE = 2048
MAXITER = 16384
ELITRATE = 0.10
MUTATIONRATE = 0.25
TARGET = "Hello world!"
class Ga
attr_accessor :str, :fitness
end
def init_pop
pop = Array.new
POPSIZE.times do |i|
citizen = Ga.new
citizen.fitness = 0
citizen.str = ""
TARGET.length.times do |j|
citizen.str += (32 + Random.rand(90)).chr
end
pop.push citizen
end
return pop
end
def calc_fitness(pop)
pop.each do |citizen|
citizen.fitness = 0
TARGET.length.times do |i|
citizen.fitness += (TARGET[i].ord - citizen.str[i].ord).abs
end
end
end
def sort_by_fitness(pop)
pop.sort { |a,b| a.fitness <=> b.fitness }
end
def elitism(pop)
return pop[0, (ELITRATE*POPSIZE).to_i]
end
def mutate(citizen)
ipos = Random.rand(TARGET.length)
delta = Random.rand(90) + 32
citizen.str[ipos] = ((citizen.str[ipos].ord + delta) % 122).chr
end
def mate(pop)
buf = elitism(pop)
(pop.length - buf.length).times do |i|
one = Random.rand(POPSIZE / 2)
two = Random.rand(POPSIZE / 2)
spos = Random.rand(TARGET.length)
citizen = Ga.new
citizen.fitness = 0
citizen.str = pop[one].str[0, spos] + pop[two].str[spos, TARGET.length - spos]
mutate(citizen) if rand() < MUTATIONRATE
buf.push citizen
end
buf
end
# main
pop = init_pop
MAXITER.times do |i|
calc_fitness pop
pop = sort_by_fitness(pop)
puts "Best: #{pop[0].str} (#{pop[0].fitness})"
break if pop[0].fitness == 0
pop = mate(pop)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment