首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >智能算法工程中的遗传算法

智能算法工程中的遗传算法
EN

Code Review用户
提问于 2011-01-28 05:33:47
回答 2查看 1.3K关注 0票数 18

我为我刚刚完成的一个图书项目编写了一堆Ruby代码。一个批评是,这是很好的代码,但不是很“红宝石喜欢”。我同意我的风格因为沟通的原因而简化了,虽然它是程序代码,但对我来说仍然是“红宝石般的”。

对于下面这个有代表性的例子,有什么想法可以让它更像Ruby吗?

代码语言:javascript
复制
# Genetic Algorithm in the Ruby Programming Language

# The Clever Algorithms Project: http://www.CleverAlgorithms.com
# (c) Copyright 2010 Jason Brownlee. Some Rights Reserved. 
# This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 2.5 Australia License.

def onemax(bitstring)
  sum = 0
  bitstring.size.times {|i| sum+=1 if bitstring[i].chr=='1'}
  return sum
end

def random_bitstring(num_bits)
  return (0...num_bits).inject(""){|s,i| s<<((rand<0.5) ? "1" : "0")}
end

def binary_tournament(pop)
  i, j = rand(pop.size), rand(pop.size)
  j = rand(pop.size) while j==i
  return (pop[i][:fitness] > pop[j][:fitness]) ? pop[i] : pop[j]
end

def point_mutation(bitstring, rate=1.0/bitstring.size)
  child = ""
   bitstring.size.times do |i|
     bit = bitstring[i].chr
     child << ((rand()<rate) ? ((bit=='1') ? "0" : "1") : bit)
  end
  return child
end

def crossover(parent1, parent2, rate)
  return ""+parent1 if rand()>=rate
  point = 1 + rand(parent1.size-2)
  return parent1[0...point]+parent2[point...(parent1.size)]
end

def reproduce(selected, pop_size, p_cross, p_mutation)
  children = []  
  selected.each_with_index do |p1, i|
    p2 = (i.modulo(2)==0) ? selected[i+1] : selected[i-1]
    p2 = selected[0] if i == selected.size-1
    child = {}
    child[:bitstring] = crossover(p1[:bitstring], p2[:bitstring], p_cross)
    child[:bitstring] = point_mutation(child[:bitstring], p_mutation)
    children << child
    break if children.size >= pop_size
  end
  return children
end

def search(max_gens, num_bits, pop_size, p_crossover, p_mutation)
  population = Array.new(pop_size) do |i|
    {:bitstring=>random_bitstring(num_bits)}
  end
  population.each{|c| c[:fitness] = onemax(c[:bitstring])}
  best = population.sort{|x,y| y[:fitness] <=> x[:fitness]}.first  
  max_gens.times do |gen|
    selected = Array.new(pop_size){|i| binary_tournament(population)}
    children = reproduce(selected, pop_size, p_crossover, p_mutation)    
    children.each{|c| c[:fitness] = onemax(c[:bitstring])}
    children.sort!{|x,y| y[:fitness] <=> x[:fitness]}
    best = children.first if children.first[:fitness] >= best[:fitness]
    population = children
    puts " > gen #{gen}, best: #{best[:fitness]}, #{best[:bitstring]}"
    break if best[:fitness] == num_bits
  end
  return best
end

if __FILE__ == $0
  # problem configuration
  num_bits = 64
  # algorithm configuration
  max_gens = 100
  pop_size = 100
  p_crossover = 0.98
  p_mutation = 1.0/num_bits
  # execute the algorithm
  best = search(max_gens, num_bits, pop_size, p_crossover, p_mutation)
  puts "done! Solution: f=#{best[:fitness]}, s=#{best[:bitstring]}"
end
EN

回答 2

Code Review用户

发布于 2011-01-28 07:03:32

Ruby库非常强大:

onemax(bitstring)可以是简单的bitstring.count('1')

random_bitstring(num_bits)可能更好地实现为rand(2**num_bits).to_s(2)

首先要检查的是这个http://ruby-doc.org/core-2.0/Enumerable.html

票数 7
EN

Code Review用户

发布于 2011-01-30 04:51:47

我目前正在阅读这本书,是的,我承认这不是我见过的最具Ruby风格的代码,但我认为它确实实现了它设定要完成的主要目标,而且我不认为Ruby会妨碍它的实现。

当我试图跟踪、运行甚至增加一些方法时,我注意到的是一般流程。有几件事我不能说:“你应该这样做,这样就说明了RUBY”,但如果:

  • 配置是在哈希文件的开头完成的。至于使用Hash,您可以看到Hash在Ruby中有很多特性,很多时候是因为使用和读取.yml配置文件,所以我想我只是希望在Hash中进行吐露。(如果这是一个应用程序,我会说将信任信息放在一个.yml文件中,但是我理解将完整的解决方案封装在一个文件中的愿望。)
  • "search“方法定义位于文件的开头,就在哈希下面,概述了配置。(搜索方法的调用仍然发生在if文件部分的底部。)

好的,一开始的事情肯定是有争议的,但我发现我自己来到这些文件的每一个,滚动到底部,阅读配置,滚动一点点,阅读“搜索”方法,以获得一个高层次的视图,然后再滚动到顶部去挖掘支持方法。

我在阅读和编写Ruby时喜欢的另一个有争议的风格是使用一个空间来填充内联块的开头和结尾。

所以

代码语言:javascript
复制
children.sort!{|x,y| y[:fitness] <=> x[:fitness]}

变成了

代码语言:javascript
复制
children.sort!{ |x,y| y[:fitness] <=> x[:fitness] }

是的,这是一件小事,有些人会说,任何增加额外击键的东西都是不好的,但我发现它的可读性更强。

此外,正如您可能猜到的那样,在使用operators...and时注意到一些不一致的间距,在大多数情况下,我选择更多的间距。;)

代码语言:javascript
复制
def crossover(parent1, parent2, rate)
  return ""+parent1 if rand()>=rate
  point = 1 + rand(parent1.size-2)
  return parent1[0...point]+parent2[point...(parent1.size)]
end

变成了

代码语言:javascript
复制
def crossover(parent1, parent2, rate)
  return "" + parent1 if rand() >= rate
  point = 1 + rand(parent1.size-2)
  return parent1[0...point] + parent2[point...(parent1.size)]
end

现在我要做的是picky...so,我现在已经完成了。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/354

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档