Scala遗传算法(GA)库中的模拟二进制交叉(SBX)交叉算子

我在一个很小的研究团队工作,用Scala创建/改编遗传算法库,用于使用Scientific Worklow System进行分布式计算,在我们的例子中,我们使用开源OpenMole软件( http://www.openmole.org/ )。

最近,我尝试理解并重新实现在JMetal Metaheuristics库( http://jmetal.sourceforge.net/ )中编写的SBX交叉运算符,以使其在我们的Scala库中的function版本中进行调整。

我写了一些代码,但是我需要我们的建议或者你对在Java库中定义的SBX的validation,因为源代码( svn中的src )看起来不像这里写的原始等式: http : //citeseerx.ist。 psu.edu/viewdoc/download?doi=10.1.1.33.7291&rep=rep1&type=pdf ,第30页,附件A

BetaEquation

第一个问题,我不了解JMetal的java版本,为什么他们使用两个不同的beta值?

  • beta1在方程中使用min [(y1-yL),…]和的第一个arg
  • 使用min […,(yu – y2)]的第二个arg的beta2

Beta 1和2用于计算alpha值和2(所以这里和jmetal我们还有两个alpha不同的值alpha1和2)…

同样的问题/问题,我们在jmetal两个计算betaq (java代码)或Deb方程,结果: betaoverlined

第二个问题,符号的含义是什么 betaoverlined 用于(2)和(3)程序中的SBX伪算法,与简单β的区别? 特别是当我们想要计算交叉父母的孩子/后代时,就像这里:

在此处输入图像描述

编辑

  • 更正no-op if / else块

  • jmetal中的代码作者给了我Nsga-II算法原始源代码的链接,他解释我Deb的SBX描述与他的实现不同:/

    http://www.iitk.ac.in/kangal/codes.shtml

    我不明白jmetal和原始源代码中的描述和实现之间的区别,你有解释吗?

  • 正确if / else返回map

开始翻译成scala

class SBXBoundedCrossover[G <: GAGenome, F  Double = _.nextDouble) extends CrossOver [G, F] { def this(rate: Double) = this( _ => rate) def crossOver (genomes : IndexedSeq [G], factory: F) (implicit aprng : Random) = { val g1 = genomes.random val g2 = genomes.random val crossoverRate = rate(aprng) val EPS = 1.0e-14 val numberOfVariables = g1.wrappedValues.size val distributionIndex = 2 val variableToMutate = (0 until g1.wrappedValues.size).map{x => !(aprng.nextDouble < 0.5)} //crossover probability val offspring = { if (aprng.nextDouble  if(b) { if (abs(g1e - g2e) > EPS){ val y1 = min(g1e, g2e) val y2 = max(g2e, g1e) var yL = 0.0 //g1e.getLowerBound var yu = 1.0 //g1e.getUpperBound var rand = aprng.nextDouble // ui var beta1 = 1.0 + (2.0 * (y1 - yL)/(y2 - y1)) var alpha1 = 2.0 - pow(beta1,-(distributionIndex+1.0)) var betaq1 = computebetaQ(alpha1,distributionIndex,rand) //calcul offspring 1 en utilisant betaq1, correspond au β barre var c1 = 0.5 * ((y1 + y2) - betaq1 * (y2 - y1)) // ----------------------------------------------- var beta2 = 1.0 + (2.0 * (yu - y2) / (y2 - y1)) var alpha2 = 2.0 - pow(beta2, -(distributionIndex + 1.0)) var betaq2 = computebetaQ(alpha2,distributionIndex,rand) //calcul offspring2 en utilisant betaq2 var c2 = 0.5 * ((y1 + y2) + betaq2 * (y2 - y1)) if (c1  yu) c1 = yu if (c2  yu) c2 = yu if (aprng.nextDouble <= 0.5) { (c2,c1) } else { (c1, c2) } }else{ (g1e, g2e) } }else{ (g2e, g1e) } } }else{ // not so good here ... (g1.wrappedValues zip g2.wrappedValues) } } (factory.buildGenome(offspring.map{_._1}), factory.buildGenome(offspring.map{_._2})) } def computebetaQ(alpha:Double, distributionIndex:Double, rand:Double):Double = { if (rand <= (1.0/alpha)){ pow ((rand * alpha),(1.0 / (distributionIndex + 1.0))) } else { pow ((1.0 / (2.0 - rand * alpha)),(1.0 / (distributionIndex + 1.0))) } } 

非常感谢您的建议或帮助解决这个问题。

SR

Reyman64,你的问题是我正在寻找的答案。 谢谢。

我拿了你链接的文件和Deb的实现代码,试图理解两者。 为此,我几乎评论了代码的每一行。 它们的区别仅在于β的计算。

由于Deb在他的NSGA-II实现中使用了这个代码,我将坚持使用这个版本的算法。

如果有人处于相同的情况我(不了解如何实施SBX),我将评论留在下面的要点,看一看。

https://gist.github.com/Tiagoperes/1779d5f1c89bae0cfdb87b1960bba36d

我为HeuristicLab(C#)实现了SBX(它被称为Simulated Binary Crossover btw)的实现。 您可以查看我们的SimulatedBinaryCrossover的实现。 我从不同的参考文献中得到了描述(论文题目:“1995年连续搜索空间的模拟二进制交叉”)。 完整的引用在源代码中给出。