Я пытаюсь запрограммировать быстрый алгоритм без допорядной сортировки (NDS) Deb, используемый в NSGA2, неизменным способом, используя Scala.
 
Но проблема кажется более сложной, чем я думаю, поэтому я упрощаю здесь проблему создания MWE.
Представьте себе совокупность Seq[A], и каждый элемент A будет decoratedA со списком, который содержит указатели на другие элементы популяции Seq[A].
Функция evalA(a:decoratedA) принимает список linkedA, который содержит и уменьшает значение каждого из них.
Далее я возьму список подмножеств decoratedAPopulation популяции A и вызовет evalA для каждого. У меня проблема, потому что между каждой итерацией по элементу в этом списке подмножеств decoratedAPopulation мне нужно обновить мою популяцию A новым decoratedA и обновленным linkedA содержать...
Более проблематично, каждый элемент популяции нуждается в обновлении "linkedA", чтобы заменить связанный элемент, если он изменится...
 
Hum, как вы можете видеть, кажется сложным поддерживать синхронизированный синхронизируемый список таким образом. Я предлагаю другое решение внизу, которое, вероятно, нуждается в рекурсии, чтобы вернуть после каждого evalA новую группу с замененным элементом.
 
Как я могу сделать это правильно неизменным способом?
Легко закодировать в изменчивом виде, но я не могу найти хороший способ сделать это непреложным способом, у вас есть путь или идея сделать это?
object test extends App{
  case class A(value:Int) {def decrement()= new A(value - 1)}
  case class decoratedA(oneAdecorated:A, listOfLinkedA:Seq[A])
  // We start algorithm loop with A element with value = 0
  val population = Seq(new A(0), new A(0), new A(8), new A(1))
  val decoratedApopulation = Seq(new decoratedA(population(1),Seq(population(2),population(3))),
                                 new decoratedA(population(2),Seq(population(1),population(3))))
  def evalA(a:decoratedA) = {
    val newListOfLinked = a.listOfLinkedA.map{e => e.decrement()
    new decoratedA(a.oneAdecorated,newListOfLinked)}
  }
  def run()= {
    //decoratedApopulation.map{
    // ?
    //}
  }
} 
Обновление 1:
О вводе/выводе исходного алгоритма.
Первая часть алгоритма Deb (Шаг 1 до  Шаг 3) анализирует список Individual и вычисляет для каждого A: (a) кол-во подсчетов, число of A, которые доминируют во мне (атрибут value A) (b) список A я доминирует (listOfLinkedA).
Таким образом, он возвращает полностью заполненную совокупность decoratedA, а для входа в Шаг 4 (моя проблема) я беру первый не доминируемый фронт, ср. подмножество элементов decoratedA с A значением = 0.
  Моя проблема начинается здесь, со списком decoratedA с A значением = 0; и я просматриваю следующий фронт в этом списке, вычисляя каждый listOfLinkedA каждого из этих A
На каждой итерации между шагами с 4 по 6 нужно вычислить новый B список подмножеств decoratedA с A значением = 0. Для каждого, я уменьшаю сначала атрибут count доминирования каждого элемента в listOfLinkedA, затем я фильтрую, чтобы получить элемент равным 0. A конец шага 6, B сохраняется в списке List[Seq[DecoratedA]], затем я перезапускаю до шага 4 с B и вычисляю новый C и т.д..
Что-то вроде этого в моем коде, я вызываю explore() для каждого элемента B, а Q равен концу нового подмножества decoratedA с value (пригодность здесь) = 0:
case class PopulationElement(popElement:Seq[Double]){
  implicit def poptodouble():Seq[Double] = {
    popElement
  }
}
class SolutionElement(values: PopulationElement, fitness:Double, dominates: Seq[SolutionElement])  {
  def decrement()= if (fitness == 0) this else new SolutionElement(values,fitness - 1, dominates)
  def explore(Q:Seq[SolutionElement]):(SolutionElement, Seq[SolutionElement])={
    // return all dominates elements with fitness - 1
    val newSolutionSet = dominates.map{_.decrement()}
    val filteredSolution:Seq[SolutionElement] = newSolutionSet.filter{s => s.fitness == 0.0}.diff{Q}
    filteredSolution
  }
}
A конец алгоритма, у меня есть окончательный список seq decoratedA List[Seq[DecoratedA]], который содержит все мои фронты, вычисленные.
Обновление 2
Образец значения, извлеченный из этого примера. Я беру только фронт парето (красный) и следующий {f, h, l} следующий фронт с преобладанием count = 1.
 
case class p(x: Int, y: Int)
val a = A(p(3.5, 1.0),0) 
val b = A(p(3.0, 1.5),0) 
val c = A(p(2.0, 2.0),0) 
val d = A(p(1.0, 3.0),0) 
val e = A(p(0.5, 4.0),0) 
val f = A(p(0.5, 4.5),1) 
val h = A(p(1.5, 3.5),1) 
val l = A(p(4.5, 1.0),1) 
case class A(XY:p, value:Int) {def decrement()= new A(XY, value - 1)}
case class ARoot(node:A, children:Seq[A])
val population = Seq(
  ARoot(a,Seq(f,h,l),
  ARoot(b,Seq(f,h,l)),
  ARoot(c,Seq(f,h,l)),   
  ARoot(d,Seq(f,h,l)),
  ARoot(e,Seq(f,h,l)),
  ARoot(f,Nil),
  ARoot(h,Nil),
  ARoot(l,Nil))
Возврат алгоритма List(List(a,b,c,d,e), List(f,h,l))
Обновление 3
Через 2 часа и некоторые проблемы с сопоставлением шаблонов (Ahum...) я возвращаюсь с полным примером, который автоматически вычисляет счетчик с преобладанием и дети каждого ARoot.
Но у меня такая же проблема, вычисление списка моих детей не совсем правильно, потому что каждый элемент A, возможно, является общим членом другого дочернего списка ARoot, поэтому мне нужно подумать о вашем ответе, чтобы изменить его:/В это время я только вычисляет список детей Seq[p], и мне нужен список Seq[A]
  case class p(x: Double, y: Double){
  def toSeq():Seq[Double] = Seq(x,y)
}
case class A(XY:p, dominatedCounter:Int) {def decrement()= new A(XY, dominatedCounter - 1)}
case class ARoot(node:A, children:Seq[A])
case class ARootRaw(node:A, children:Seq[p])
object test_stackoverflow extends App {
  val a = new p(3.5, 1.0)
  val b = new p(3.0, 1.5)
  val c = new p(2.0, 2.0)
  val d = new p(1.0, 3.0)
  val e = new p(0.5, 4.0)
  val f = new p(0.5, 4.5)
  val g = new p(1.5, 4.5)
  val h = new p(1.5, 3.5)
  val i = new p(2.0, 3.5)
  val j = new p(2.5, 3.0)
  val k = new p(3.5, 2.0)
  val l = new p(4.5, 1.0)
  val m = new p(4.5, 2.5)
  val n = new p(4.0, 4.0)
  val o = new p(3.0, 4.0)
  val p = new p(5.0, 4.5)
  def isStriclyDominated(p1: p, p2: p): Boolean = {
    (p1.toSeq zip p2.toSeq).exists { case (g1, g2) => g1 < g2 }
  }
  def sortedByRank(population: Seq[p]) = {
    def paretoRanking(values: Set[p]) = {
      //comment from @dk14: I suppose order of values isn't matter here, otherwise use SortedSet
      values.map { v1 =>
        val t = (values - v1).filter(isStriclyDominated(v1, _)).toSeq
        val a = new A(v1, values.size - t.size - 1)
        val root = new ARootRaw(a, t)
        println("Root value ", root)
        root
      }
    }
    val listOfARootRaw = paretoRanking(population.toSet)
    //From @dk14: Here is convertion from Seq[p] to Seq[A]
    val dominations: Map[p, Int] = listOfARootRaw.map(a => a.node.XY -> a.node.dominatedCounter) //From @dk14: It a map with dominatedCounter for each point
    val listOfARoot = listOfARootRaw.map(raw =>  ARoot(raw.node, raw.children.map(p => A(p, dominations.getOrElse(p, 0)))))
    listOfARoot.groupBy(_.node.dominatedCounter)
  }
  //Get the first front, a subset of ARoot, and start the step 4
  println(sortedByRank(Seq(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)).head)
}
