<commit_before>/*
 * Copyright (C) 2015 <NAME>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.openmole.plugin.method.evolution

import org.openmole.core.dsl._
import org.openmole.core.workflow.puzzle.{ PuzzleContainer, ToPuzzle }
import org.openmole.core.workflow.tools.DefaultSet
import org.openmole.core.workflow.validation.Validation
import org.openmole.plugin.domain.collection._
import org.scalatest._
import org.openmole.tool.types._
import org.openmole.plugin.domain.bounds._
import org.openmole.core.workflow.tools.Stubs._
import org.openmole.plugin.method.evolution.Genome.GenomeBound
import org.openmole.plugin.method.evolution.PSE.PatternAxe

class WorkflowSpec extends FlatSpec with Matchers {

  def nsga2(wrap: Boolean = true) = {
    val x = Val[Double]
    val y = Val[Double]
    val z = Val[Int]

    val puzzle = EmptyTask() set (
      (inputs, outputs) += (x, y, z),
      z := 9
    )

    // Define a builder to use NSGA2 generational EA algorithm.
    // replicateModel is the fitness function to optimise.
    // lambda is the size of the offspring (and the parallelism level).
    SteadyStateEvolution(
      algorithm =
        NSGA2(
          genome = Seq(x in (0.0, 1.0), y in ("0.0", "1.0")),
          objectives = Seq(x, y),
          stochastic = Stochastic()
        ),
      evaluation = puzzle,
      parallelism = 10,
      termination = 10,
      wrap = wrap
    )
  }

  def conflict = {
    val population = Val[Double]
    val state = Val[Double]

    val puzzle = EmptyTask() set (
      (inputs, outputs) += (population, state)
    )

    // Define a builder to use NSGA2 generational EA algorithm.
    // replicateModel is the fitness function to optimise.
    // lambda is the size of the offspring (and the parallelism level).
    SteadyStateEvolution(
      algorithm =
        PSE(
          genome = Seq(population in (0.0, 1.0), state in ("0.0", "1.0")),
          objectives =
            Seq(
              population in (0.0 to 1.0 by 0.1),
              state in (0.0 to 1.0 by 0.1)
            ),
          stochastic = Stochastic()
        ),
      evaluation = puzzle,
      parallelism = 10,
      termination = 10
    )
  }

  def boundArray = {
    val xArray = Val[Array[Double]]
    val yArray = Val[Array[Int]]

    NSGA2(
      mu = 200,
      genome = Seq(xArray in Vector.fill(5)((0.0, 1.0)), yArray in Vector.fill(5)(("0", "1"))),
      objectives = Seq()
    )
  }

  import org.openmole.core.workflow.tools.Stubs._

  "Bound array" should "compile" in {
    SteadyStateEvolution(
      algorithm = boundArray,
      evaluation = EmptyTask(),
      parallelism = 10,
      termination = 10
    )
  }

  "Island evolution" should "compile" in {
    val steady = SteadyStateEvolution(
      algorithm = boundArray,
      evaluation = EmptyTask(),
      parallelism = 10,
      termination = 10
    )
    IslandEvolution(steady, 10, 10)
  }

  "Steady state workflow" should "have no validation error" in {
    Validation(nsga2().head.toMole).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }

    Validation(conflict.head.toMole).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }
  }

  "Island workflow" should "have no validation error" in {
    val islandEvolutionNSGA2 = IslandEvolution(nsga2(), 10, 50, 100).head.toMole

    Validation(islandEvolutionNSGA2).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }

    Validation(IslandEvolution(conflict, 10, 50, 100).head.toMole).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }
  }

  "Steady state workflow with wrapping" should "have no validation error" in {
    Validation(nsga2(wrap = false).head.toMole).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }
  }

  "Genome bounds" should "compile" in {
    import org.openmole.plugin.domain.collection._
    val ba = Val[Array[Boolean]]
    val b1: GenomeBound = ba in Seq(Vector(true, false), Vector(true, false))
    val b2: GenomeBound = ba in 2
  }

  "Suggestion" should "be possible" in {

    val a = Val[Double]

    NSGA2Evolution(
      evaluation = EmptyTask(),
      objectives = Seq(a),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100,
      suggestion = Seq(Seq(a := 0.5))
    )
  }

  "Aggregation" should "be possible in NSGA" in {

    val a = Val[Double]
    def f(v: Vector[Double]) = v.head

    NSGA2Evolution(
      evaluation = EmptyTask(),
      objectives = Seq(a aggregate f),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100

    )
  }

  "Aggregation" should "be possible in PSE" in {
    val a = Val[Double]
    val b = Val[Double]
    def f(v: Vector[Double]) = v.head

    PSEEvolution(
      evaluation = EmptyTask(),
      objectives = Seq(a aggregate f in (0.0 to 1.0 by 0.1), b in (0.2 to 0.5 by 0.1)),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100

    )
  }

  "Aggregation" should "be possible in OSE" in {
    val o = Val[Double]
    val a = Val[Double]
    val b = Val[Double]
    def f(v: Vector[Double]) = v.head

    OSEEvolution(
      origin = Seq(o in (0.0 to 1.0 by 0.1)),
      evaluation = EmptyTask(),
      objectives = Seq(a aggregate f under 9, b under 3.0),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100
    )
  }

}<commit_msg>[Plugin] enh: add validation tests for nsga2<commit_after>/*
 * Copyright (C) 2015 <NAME>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.openmole.plugin.method.evolution

import org.openmole.core.dsl._
import org.openmole.core.workflow.validation._
import org.openmole.plugin.domain.collection._
import org.scalatest._
import org.openmole.plugin.domain.bounds._
import org.openmole.plugin.method.evolution.Genome.GenomeBound

class WorkflowSpec extends FlatSpec with Matchers {

  def nsga2(wrap: Boolean = true) = {
    val x = Val[Double]
    val y = Val[Double]
    val z = Val[Int]

    val puzzle = EmptyTask() set (
      (inputs, outputs) += (x, y, z),
      z := 9
    )

    // Define a builder to use NSGA2 generational EA algorithm.
    // replicateModel is the fitness function to optimise.
    // lambda is the size of the offspring (and the parallelism level).
    SteadyStateEvolution(
      algorithm =
        NSGA2(
          genome = Seq(x in (0.0, 1.0), y in ("0.0", "1.0")),
          objectives = Seq(x, y),
          stochastic = Stochastic()
        ),
      evaluation = puzzle,
      parallelism = 10,
      termination = 10,
      wrap = wrap
    )
  }

  def conflict = {
    val population = Val[Double]
    val state = Val[Double]

    val puzzle = EmptyTask() set (
      (inputs, outputs) += (population, state)
    )

    // Define a builder to use NSGA2 generational EA algorithm.
    // replicateModel is the fitness function to optimise.
    // lambda is the size of the offspring (and the parallelism level).
    SteadyStateEvolution(
      algorithm =
        PSE(
          genome = Seq(population in (0.0, 1.0), state in ("0.0", "1.0")),
          objectives =
            Seq(
              population in (0.0 to 1.0 by 0.1),
              state in (0.0 to 1.0 by 0.1)
            ),
          stochastic = Stochastic()
        ),
      evaluation = puzzle,
      parallelism = 10,
      termination = 10
    )
  }

  def boundArray = {
    val xArray = Val[Array[Double]]
    val yArray = Val[Array[Int]]

    NSGA2(
      mu = 200,
      genome = Seq(xArray in Vector.fill(5)((0.0, 1.0)), yArray in Vector.fill(5)(("0", "1"))),
      objectives = Seq()
    )
  }

  import org.openmole.core.workflow.tools.Stubs._

  "Bound array" should "compile" in {
    SteadyStateEvolution(
      algorithm = boundArray,
      evaluation = EmptyTask(),
      parallelism = 10,
      termination = 10
    )
  }

  "Island evolution" should "compile" in {
    val steady = SteadyStateEvolution(
      algorithm = boundArray,
      evaluation = EmptyTask(),
      parallelism = 10,
      termination = 10
    )
    IslandEvolution(steady, 10, 10)
  }

  "Steady state workflow" should "have no validation error" in {
    Validation(nsga2().head.toMole).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }

    Validation(conflict.head.toMole).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }
  }

  "Island workflow" should "have no validation error" in {
    val islandEvolutionNSGA2 = IslandEvolution(nsga2(), 10, 50, 100).head.toMole

    Validation(islandEvolutionNSGA2).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }

    Validation(IslandEvolution(conflict, 10, 50, 100).head.toMole).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }
  }

  "Steady state workflow with wrapping" should "have no validation error" in {
    Validation(nsga2(wrap = false).head.toMole).toList match {
      case Nil ⇒
      case l   ⇒ sys.error("Several validation errors have been found: " + l.mkString("\n"))
    }
  }

  "Genome bounds" should "compile" in {
    import org.openmole.plugin.domain.collection._
    val ba = Val[Array[Boolean]]
    val b1: GenomeBound = ba in Seq(Vector(true, false), Vector(true, false))
    val b2: GenomeBound = ba in 2
  }

  "NSGAEvolution" should "be valid" in {
    val a = Val[Double]
    val b = Val[Double]

    val nsga = NSGA2Evolution(
      evaluation = EmptyTask() set (inputs += a, outputs += b),
      objectives = Seq(b),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100
    )

    Validation(nsga.toMole).isEmpty should equal(true)
  }

  "NSGAEvolution with island" should "be valid" in {
    val a = Val[Double]
    val b = Val[Double]

    val nsga = NSGA2Evolution(
      evaluation = EmptyTask() set (inputs += a, outputs += b),
      objectives = Seq(b),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100,
      distribution = Island(1)
    )

    Validation(nsga.toMole).isEmpty should equal(true)
  }

  "Stochastic NSGAEvolution" should "be valid" in {
    val a = Val[Double]
    val b = Val[Double]

    val nsga = NSGA2Evolution(
      evaluation = EmptyTask() set (inputs += a, outputs += b),
      objectives = Seq(b),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100,
      stochastic = Stochastic()
    )

    Validation(nsga.toMole).isEmpty should equal(true)
  }

  "Stochastic NSGAEvolution with island" should "be valid" in {
    val a = Val[Double]
    val b = Val[Double]

    val nsga = NSGA2Evolution(
      evaluation = EmptyTask() set (inputs += a, outputs += b),
      objectives = Seq(b),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100,
      stochastic = Stochastic(),
      distribution = Island(1)
    )

    Validation(nsga.toMole).isEmpty should equal(true)
  }

  "Suggestion" should "be possible" in {
    val a = Val[Double]

    NSGA2Evolution(
      evaluation = EmptyTask(),
      objectives = Seq(a),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100,
      suggestion = Seq(Seq(a := 0.5))
    )
  }

  "Aggregation" should "be possible in NSGA" in {

    val a = Val[Double]
    val b = Val[Double]

    def f(v: Vector[Double]) = v.head

    val nsga = NSGA2Evolution(
      evaluation = EmptyTask() set (inputs += a, outputs += b),
      objectives = Seq(b aggregate f),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100
    )

    Validation(nsga.toMole).isEmpty should equal(true)
  }

  "Aggregation" should "be possible in PSE" in {
    val a = Val[Double]
    val b = Val[Double]
    def f(v: Vector[Double]) = v.head

    PSEEvolution(
      evaluation = EmptyTask(),
      objectives = Seq(a aggregate f in (0.0 to 1.0 by 0.1), b in (0.2 to 0.5 by 0.1)),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100

    )
  }

  "Aggregation" should "be possible in OSE" in {
    val o = Val[Double]
    val a = Val[Double]
    val b = Val[Double]
    def f(v: Vector[Double]) = v.head

    OSEEvolution(
      origin = Seq(o in (0.0 to 1.0 by 0.1)),
      evaluation = EmptyTask(),
      objectives = Seq(a aggregate f under 9, b under 3.0),
      genome = Seq(a in (0.0, 1.0)),
      termination = 100
    )
  }

}
{'fraction_non_alphanumeric': 0.1172279792746114, 'fraction_numerical': 0.023388025331030512, 'mean_word_length': 2.4961006289308174, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7397908', 'n_tokens_mistral': 4809, 'n_tokens_neox': 4477, 'n_words': 1411}