Ruby遗传算法永远不会达到峰值

时间:2014-03-22 01:33:37

标签: ruby genetic-algorithm

我是Ruby的初学者,编写了一个非常简单的程序来模仿遗传学,但输出适应性总是保持在15-24左右。这个程序最终是否应该达到32的适应度然后输出呢?

已编辑的代码:

#!/usr/bin/env ruby

class Animal
  attr_reader :genes

  def initialize (genes=[])
    @genes = genes
  end

  def random_chromosome
    @genes = Array.new(32).collect {|x| rand 2}
    self
  end

  def calc_fitness
    @genes.inject(0){|i, v| next i + v if v == 1; i}
  end

  def mutate
   2.times { @genes[rand 32] = rand 2}
  end

  def mate(other)
    @genes = (@genes[0...16] + other.genes[0...16])
    mutate
    self
  end

  def is_spartan?
    @genes == (Array.new.fill 1)
  end
end

class Generation
  attr_reader :animals

  def initialize (animals=[], gen_size = 10)
    @animals = animals
    @gen_size = gen_size
  end
  def seed
    @animals = Array.new(@gen_size).collect {Animal.new.random_chromosome}
  end
  def mate
    @animals = [].tap {|a|
        @gen_size.times{ 
            a << @animals[rand @gen_size].mate(@animals[rand @gen_size])
          }
        }
  end
  def alphas
    @animals.sort! {|a, b| b.calc_fitness <=> a.calc_fitness}.first(@gen_size)
  end
  def include_spartans?
    @animals.include? Array.new(32).fill 1  #perfect genes
  end
  def output
    @animals.each {|an| print "#{an.genes.join}: #{an.calc_fitness}\n"}
  end
end

NUM_OFFSPRING = 10
gen = Generation.new
gen.seed

i = 0
loop do
  i += 1
  if gen.include_spartans? #end if there are any perfect genes
    puts "Members have reached spartan status!"
    break
  end

  puts "*** ALPHAS FROM GENERATION: #{i}***" 
  gen.mate
  gen.alphas
  gen.output
  sleep(0.2)
    end

示例输出

* ALPHAS FROM GENERATION:1 *

11101101011111101001010110101101:21 10111111111100000110000101011001:18 11101111110110111100001100000001:18 11000101101111010110000111011001:18 11101111110110111100001100000001:18 10111111111100000110000101011001:18 11000101101111010110000111011001:18 11000011010000011001101111101101:17 01100001110110011000101111110000:16 10001010111110001100001101000001:14

* ALPHAS FROM GENERATION:2 *

11101111110110101110111111010011:24 01100001110110011110111111011110:21 11000101101111011100001101000001:16 10001010111110000110000111011001:16 11000101101111011100001101000001:16 10111111010100001000001101100001:15 10111111010100001000001101100001:15 10111111010100001000001101100001:15 10111111010100001000001101100001:15 10111111010100001000001101100001:15

* ALPHAS FROM GENERATION:3 *

11101111111110101011111111000000:22 11101111111110101011111111000000:22 10111111110000001110011111011010:20 10111111110000001110011111011010:20 10111111110000001110011111011010:20 11000101101111011000101011111000:18 11000101101111011000101011111000:18 11000101101111011000101011111000:18 11000101101111011000101011111000:18 01100001110100011011111101010000:16

1 个答案:

答案 0 :(得分:2)

Patru让你走上正轨。这里解决了一些问题:https://gist.github.com/matt-glover/9700810

原始代码不使用NUM_OFFSPRING。即使它确实这样做也会将10只动物拉回为alphas(或尝试无论如何),所以NUM_OFFSPRING确实应该更大,以便看到alpha选择显示出任何影响。

原始代码对动物进行排序以找到alphas但实际上并不保留前10名。相反,它返回方法调用中的前10名,但存储完整排序的@animals数组。

交配需要产生新的Animal,否则可以在交配阶段一次又一次地选择相同的动物。原始代码仅保留结果对中存储在第一只动物中的最后交配尝试的结果。这最终消灭了动物库中的单个动物在动物列表中出现多次,并且只反映了最后交配尝试迭代的基因。

最后,include_spartans?检查需要按照示例中的方式绘制基因图,或者调用每只动物并在那里进行检查。旧代码正在检查动物实例与一组数据。