Оператор кроссовера Simulated Binary Crossover (SBX) в библиотеке Scala генетического алгоритма (GA) - PullRequest
4 голосов
/ 19 января 2012

Я работаю в очень маленькой исследовательской группе над созданием / адаптацией библиотеки генетических алгоритмов в Scala для распределенных вычислений с системой Scientific Worklow, в нашем случае мы используем программное обеспечение OpenMole с открытым исходным кодом (http://www.openmole.org/).

В последнее время я пытаюсь понять и заново реализовать оператор кроссовера SBX, написанный в библиотеке метаэвристики JMetal (http://jmetal.sourceforge.net/), чтобы адаптировать его в функциональной версии в нашей библиотеке Scala.

Я пишу некоторый код, но мне нужен наш совет или ваша проверка о SBX, определенном в библиотеке Java, потому что исходный код ( src в svn ) не совпадает с исходным уравнением, написанным здесь : http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.33.7291&rep=rep1&type=pdf на стр. 30, в приложении A

BetaEquation

Первый вопрос, я не понимаю java-версию JMetal, почему они используют два разных бета-значения?!

  • beta1 , которые используют в уравнении первый аргумент min [(y1 - yL), ...] и
  • beta2 , которые используют второй аргумент min [..., (yu - y2)])

Beta 1 и 2 используются для вычисления значения alpha и двух (поэтому здесь и в jmetal у нас также есть два альфа-значения, отличающиеся alpha1 и 2) ...

Та же проблема / вопрос, мы имеем в jmetal два вычисления для betaq (java-код) или в уравнении Deb, результат: betaoverlined

Второй вопрос: что означает символ betaoverlined, используемый в (2) и (3) процедуре в псевдоалгоритме SBX, и чем отличается простой beta ? Особенно, когда мы хотим вычислить детей / потомков родителей-кроссоверов, как здесь:

enter image description here

Редактировать

  • Исправить блокировку no-op if / else

  • Автор кода в jmetal дает мне ссылку на оригинальный исходный код алгоритма Nsga-II, и он объясняет мне, что описание SBX Deb отличается от его реализации: /

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

    Я не понимаю разницы между описанием и реализацией в jmetal и оригинальном исходном коде, у вас есть объяснение?

  • Исправьте, если / иначе возвратите для карты

Начало перевода на 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)))
    } 
  }

Большое спасибо за совет или помощь в решении этой проблемы.

* +1073 * SR

Ответы [ 2 ]

2 голосов
/ 17 октября 2016

Reyman64, твой вопрос - это ответ, который я искал. Спасибо.

Я взял документ, который вы связали, и код реализации Деба и попытался понять оба. Для этого я прокомментировал почти каждую строку кода. Они отличаются только в расчете бета.

Поскольку Деб использовал этот код в своей реализации NSGA-II, я буду придерживаться этой версии алгоритма.

Если кто-то находился в той же ситуации, что и я (не понимая, как реализовать SBX), я оставил свои комментарии в следующем разделе, посмотрите.

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

2 голосов
/ 20 января 2012

Я сделал реализацию SBX (она называется Имитация Binary Crossover кстати) для HeuristicLab (C #). Вы можете взглянуть на реализацию нашего SimulatedBinaryCrossover . Однако я взял описание из другой ссылки (название статьи: «Имитация двоичного кроссовера для непрерывного пространства поиска» с 1995 года). Полная цитата приведена в исходном коде.

...