DEV Community

Discussion on: Ruby kernel in Google Colaboratory.

Collapse
 
osobarako profile image
Osobarako

def objective_function(vector)
return vector.inject(0.0) {|sum, x| sum + (x ** 2.0)}
end

def random_vector(minmax)
return Array.new(minmax.size) do |i|
minmax[i][0] + ((minmax[i][1] - minmax[i][0]) * rand())
end
end

def random_gaussian(mean=0.0, stdev=1.0)
u1 = u2 = w = 0
begin
u1 = 2 * rand() - 1
u2 = 2 * rand() - 1
w = u1 * u1 + u2 * u2
end while w >= 1
w = Math.sqrt((-2.0 * Math.log(w)) / w)
return mean + (u2 * w) * stdev
end

def mutate(candidate, search_space)
child = {:vector=>[], :strategy=>[]}
candidate[:vector].each_with_index do |v_old, i|
s_old = candidate[:strategy][i]
v = v_old + s_old * random_gaussian()
v = search_space[i][0] if v < search_space[i][0]
v = search_space[i][1] if v > search_space[i][1]
child[:vector] << v
child[:strategy] << s_old + random_gaussian() * s_old.abs**0.5
end
return child
end

def tournament(candidate, population, bout_size)
candidate[:wins] = 0
bout_size.times do |i|
other = population[rand(population.size)]
candidate[:wins] += 1 if candidate[:fitness] < other[:fitness]
end
end

def init_population(minmax, pop_size)
strategy = Array.new(minmax.size) do |i|
[0, (minmax[i][1]-minmax[i][0]) * 0.05]
end
pop = Array.new(pop_size, {})
pop.each_index do |i|
pop[i][:vector] = random_vector(minmax)
pop[i][:strategy] = random_vector(strategy)
end
pop.each{|c| c[:fitness] = objective_function(c[:vector])}
return pop
end

def search(max_gens, search_space, pop_size, bout_size)
population = init_population(search_space, pop_size)
population.each{|c| c[:fitness] = objective_function(c[:vector])}
best = population.sort{|x,y| x[:fitness] <=> y[:fitness]}.first
max_gens.times do |gen|
children = Array.new(pop_size) {|i| mutate(population[i], search_space)}
children.each{|c| c[:fitness] = objective_function(c[:vector])}
children.sort!{|x,y| x[:fitness] <=> y[:fitness]}
best = children.first if children.first[:fitness] < best[:fitness]
union = children+population
union.each{|c| tournament(c, union, bout_size)}
union.sort!{|x,y| y[:wins] <=> x[:wins]}
population = union.first(pop_size)
puts " > gen #{gen}, fitness=#{best[:fitness]}"
end
return best
end

if FILE == $0
# problem configuration
problem_size = 2
search_space = Array.new(problem_size) {|i| [-5, +5]}
# algorithm configuration
max_gens = 200
pop_size = 100
bout_size = 5
# execute the algorithm
best = search(max_gens, search_space, pop_size, bout_size)
puts "done! Solution: f=#{best[:fitness]}, s=#{best[:vector].inspect}"
end

Collapse
 
kojix2 profile image
kojix2

Thank you for your comment. But I think you're probably mistaking the input field.