All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mgo.evolution.elitism.scala Maven / Gradle / Ivy

The newest version!
package mgo.evolution

import cats.Order
import cats.implicits._
import mgo.evolution.algorithm.HitMap
import mgo.evolution.diversity.crowdingDistance
import mgo.tools._

object elitism {

  type Elitism[S, I] = (S, Vector[I], Vector[I], scala.util.Random) => (S, Vector[I])

  //  object Elitism {
  //    def apply[M[_]: cats.Monad, I](f: (Vector[I], Vector[I]) => M[Vector[I]]): Elitism[M, I] = Kleisli[M, (Vector[I], Vector[I]), Vector[I]](Function.tupled(f))
  //  }

  //  def minimiseO[M[_]: Applicative, I, F](f: I => F, mu: Int)(implicit MM: cats.Monad[M], FO: Order[F]): Elitism[M, I] =
  //    Elitism[M, I](individuals => individuals.sorted(FO.contramap[I](f).toOrdering).take(mu).pure[M])
  //
  //  def maximiseO[M[_]: Applicative, I, F](f: I => F, mu: Int)(implicit MM: cats.Monad[M], FO: Order[F]): Elitism[M, I] =
  //    Elitism(individuals => individuals.sorted(Order.reverse(FO.contramap[I](f)).toOrdering).take(mu).pure[M])
  //
  //  /** Returns n individuals randomly. */
  //  def randomO[M[_]: cats.Monad, I](n: Int)(implicit randomM: Random[M]): Elitism[M, I] =
  //    Elitism(
  //      individuals => Vector.fill(n)(randomM.randomElement(individuals)).sequence)

  def maximiseO[I, F](f: I => F, mu: Int)(implicit FO: Order[F]): Vector[I] => Vector[I] = (individuals: Vector[I]) =>
    individuals.sorted(Order.reverse(FO.contramap[I](f)).toOrdering).take(mu)

  //  def randomO[M[_]: cats.Applicative, I](n: Int)(implicit randomM: Random[M]) =
  //    (individuals: Vector[I]) => Vector.fill(n)(randomM.randomElement(individuals)).sequence

  //  def incrementGeneration[M[_]: Generation] = Generation[M].increment

  def addHits[I](cell: I => Vector[Int], population: Vector[I], hitmap: HitMap): HitMap = {
    def hits(map: HitMap, c: Vector[Int]) = map.updated(c, map.getOrElse(c, 0) + 1)
    population.foldLeft(hitmap)((m, i) => hits(m, cell(i)))
  }

  /** Returns the mu individuals with the highest ranks. */
  def keepHighestRanked[I, K](population: Vector[I], ranks: Vector[K], mu: Int, rng: scala.util.Random)(implicit KO: Order[K]): Vector[I] =
    if (population.size < mu) population
    else {
      val sortedBestToWorst = (population zip ranks).sortBy { _._2 }(Order.reverse(KO).toOrdering).map { _._1 }
      sortedBestToWorst.take(mu)
    }

  def nicheElitism[I, N](population: Vector[I], keep: Vector[I] => Vector[I], niche: I => N): Vector[I] = {
    val niches = population.groupBy(niche).toVector
    niches.flatMap { case (_, individuals) => keep(individuals) }
  }

  def keepFirstFront[I](population: Vector[I], fitness: I => Vector[Double]): Vector[I] =
    if (population.isEmpty) population
    else {
      val dominating = ranking.numberOfDominating(fitness, population)
      val minDominating = dominating.map(_.value).min
      (population zip dominating).filter { case (_, d) => d.value == minDominating }.map(_._1)
    }

  def keepOnFirstFront[I](population: Vector[I], fitness: I => Vector[Double], mu: Int, random: scala.util.Random): Vector[I] = {
    val first = keepFirstFront(population, fitness)
    val crowding = crowdingDistance[I](first, fitness, random)
    keepHighestRanked(first, crowding, mu, random)
  }

  //type UncloneStrategy[M[_], I] = Vector[I] => M[I]

/**** Clone strategies ****/

  //  def applyCloneStrategy[M[_]: cats.Monad, I, G](getGenome: I => G, cloneStrategy: UncloneStrategy[M, I]): Elitism[M, I] = {
  //    import mgo.tools._
  //    def unclone(clones: Vector[I]) =
  //      if (clones.size == 1) clones.head.pure[M]
  //      else cloneStrategy(clones)
  //
  //    Elitism(_.groupByOrdered(getGenome).valuesIterator.map(_.toVector).toVector.traverse(unclone))
  //  }
  //
  //  def keepOldest[M[_]: cats.Monad, I](age: I => Long): UncloneStrategy[M, I] =
  //    (clones: Vector[I]) => clones.maxBy(age).pure[M]
  //
  //  def keepFirst[M[_]: cats.Monad, I]: UncloneStrategy[M, I] =
  //    (clones: Vector[I]) => clones.head.pure[M]

  def keepNiches[I, N](niche: I => N, keep: Vector[I] => Vector[I]): Vector[I] => Vector[I] =
    (individuals: Vector[I]) => {
      val indivsByNiche = individuals.groupByOrdered(niche)
      indivsByNiche.values.toVector.map(_.toVector).flatMap(keep.apply)
    }

  def keepFirst[G, I](genome: I => G)(population: Vector[I], newIndividuals: Vector[I]): Vector[I] = {
    val filteredClone = {
      val existingGenomes = population.map(genome).toSet
      newIndividuals.filter(i => !existingGenomes.contains(genome(i)))
    }

    population ++ filteredClone
  }

  def mergeHistories[G, I, P](genome: I => G, history: monocle.Lens[I, Vector[P]], historyAge: monocle.Lens[I, Long], historySize: Int): (Vector[I], Vector[I]) => Vector[I] =
    (population: Vector[I], newIndividuals: Vector[I]) => {
      val mergedClones = {
        val indexedNI = newIndividuals.groupByOrdered(genome)
        for {
          i <- population
          clones = indexedNI.getOrElse(genome(i), List())
        } yield {
          val additionalHistory = clones.flatMap(history.get)
          history.modify(h => (h ++ additionalHistory).takeRight(historySize)) andThen
            historyAge.modify(_ + additionalHistory.size) apply (i)
        }
      }

      val filteredClone = {
        val filter = population.map(genome).toSet
        newIndividuals.filter(i => !filter.contains(genome(i)))
      }

      mergedClones ++ filteredClone
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy