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

时间:2012-01-18 22:43:18

标签: java scala artificial-intelligence genetic-algorithm mathematical-optimization

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

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

我写了一些代码,但是我需要我们的建议或者你对Java库中定义的SBX的验证,因为源代码(src in svn)看起来不像这里写的原始等式:{{3在第30页,在附件A

BetaEquation

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

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

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

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

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

enter image description here

修改

开始翻译成scala

  class SBXBoundedCrossover[G <: GAGenome, F <: GAGenomeFactory[G]](rate: Random => 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 < crossoverRate) {      
        (variableToMutate zip (g1.wrappedValues zip g2.wrappedValues)) map {
          case (b, (g1e, g2e)) =>
            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 < yL) c1 = yL
                if (c1 > yu) c1 = yu

                if (c2 < yL) c2 = yL
                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

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

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

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

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

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

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