spacepaste

  1.  
  2. def objective_function(vector)
  3. return vector.inject(0.0) {|sum, x| sum + (x ** 2.0)}
  4. end
  5. def random_vector(minmax)
  6. return Array.new(minmax.size) do |i|
  7. minmax[i][0] + ((minmax[i][1] - minmax[i][0]) * rand())
  8. end
  9. end
  10. def random_gaussian(mean=0.0, stdev=1.0)
  11. u1 = u2 = w = 0
  12. begin
  13. u1 = 2 * rand() - 1
  14. u2 = 2 * rand() - 1
  15. w = u1 * u1 + u2 * u2
  16. end while w >= 1
  17. w = Math.sqrt((-2.0 * Math.log(w)) / w)
  18. return mean + (u2 * w) * stdev
  19. end
  20. def mutate(candidate, search_space)
  21. child = {:vector=>[], :strategy=>[]}
  22. candidate[:vector].each_with_index do |v_old, i|
  23. s_old = candidate[:strategy][i]
  24. v = v_old + s_old * random_gaussian()
  25. v = search_space[i][0] if v < search_space[i][0]
  26. v = search_space[i][1] if v > search_space[i][1]
  27. child[:vector] << v
  28. child[:strategy] << s_old + random_gaussian() * s_old.abs**0.5
  29. end
  30. return child
  31. end
  32. def tournament(candidate, population, bout_size)
  33. candidate[:wins] = 0
  34. bout_size.times do |i|
  35. other = population[rand(population.size)]
  36. candidate[:wins] += 1 if candidate[:fitness] < other[:fitness]
  37. end
  38. end
  39. def init_population(minmax, pop_size)
  40. strategy = Array.new(minmax.size) do |i|
  41. [0, (minmax[i][1]-minmax[i][0]) * 0.05]
  42. end
  43. pop = Array.new(pop_size, {})
  44. pop.each_index do |i|
  45. pop[i][:vector] = random_vector(minmax)
  46. pop[i][:strategy] = random_vector(strategy)
  47. end
  48. pop.each{|c| c[:fitness] = objective_function(c[:vector])}
  49. return pop
  50. end
  51. def search(max_gens, search_space, pop_size, bout_size)
  52. population = init_population(search_space, pop_size)
  53. population.each{|c| c[:fitness] = objective_function(c[:vector])}
  54. best = population.sort{|x,y| x[:fitness] <=> y[:fitness]}.first
  55. max_gens.times do |gen|
  56. children = Array.new(pop_size) {|i| mutate(population[i], search_space)}
  57. children.each{|c| c[:fitness] = objective_function(c[:vector])}
  58. children.sort!{|x,y| x[:fitness] <=> y[:fitness]}
  59. best = children.first if children.first[:fitness] < best[:fitness]
  60. union = children+population
  61. union.each{|c| tournament(c, union, bout_size)}
  62. union.sort!{|x,y| y[:wins] <=> x[:wins]}
  63. population = union.first(pop_size)
  64. puts " > gen #{gen}, fitness=#{best[:fitness]}"
  65. end
  66. return best
  67. end
  68. if __FILE__ == $0
  69. # problem configuration
  70. problem_size = 2
  71. search_space = Array.new(problem_size) {|i| [-5, +5]}
  72. # algorithm configuration
  73. max_gens = 200
  74. pop_size = 100
  75. bout_size = 5
  76. # execute the algorithm
  77. best = search(max_gens, search_space, pop_size, bout_size)
  78. puts "done! Solution: f=#{best[:fitness]}, s=#{best[:vector].inspect}"
  79. end
  80.