Ruby 遗传算法从未达到顶峰

标签 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

示例输出

* 一代阿尔法:1*

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

* 一代阿尔法:2*

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

* 一代阿尔法:3*

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

最佳答案

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

原始代码没有使用NUM_OFFSPRING。即使它这样做了,它也会将 10 只动物拉回来作为 alpha(或尝试无论如何)所以 NUM_OFFSPRING 真的应该更大才能看到 alpha 选择显示任何影响。

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

交配需要产生新的Animal,否则在交配阶段可能会一遍又一遍地选择相同的动物。原始代码仅保留最后一次交配尝试的结果存储在交配对中的第一只动物中。这最终将动物池消除为在动物列表中多次出现的单个动物,并且仅反射(reflect)该迭代的最后一次交配尝试的基因。

最后,include_spartans? 检查要么需要像示例中那样映射基因,要么调用每只动物并在那里执行检查。旧代码是根据一个数组检查一个动物实例。

关于Ruby 遗传算法从未达到顶峰,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22572313/

相关文章:

ruby-on-rails - ruby /rails : how can I create multiple records in salesforce with one API call via the rforce gem?

ruby - 使用 Sinatra 和 Rack Logger 记录时如何过滤敏感信息

c++ - 遗传算法和神经网络 : taking address of temporary [-fpermissive]

genetic-algorithm - 遗传算法: evolving behaviour

genetic-algorithm - 什么是ni方案?

c++ - [仅等于运算符]在集合中查找重复元素并将它们分组的快速算法是什么?

ruby - 使用 rspec 进行 Puppet 代码覆盖率测试

ruby - attr_encrypted gem 无法在 Rails 6 中工作

ruby-on-rails - Rails 和 Rake 命令挂起并且什么都不做

algorithm - 为遗传算法创建 "crossover"函数以改进网络路径