## Example

Consider a `Rabbit` class

``````case class Rabbit(a: Int, b: Double, c: Double, d: Double, e: Double, f: Double, g: Double, h: Double)
``````

Define the `Species` for a Genetic Algorithm, which requires a random generator and a fitness function.

``````import shapeless._

val gen = Generic[Rabbit]
// gen: Generic[Rabbit]{type Repr = Int :: Double :: Double :: Double :: Double :: Double :: Double :: Double :: shapeless.HNil} = shapeless.Generic\$\$anon\$1@172f9322

import axle.ml._

import scala.util.Random.nextDouble
import scala.util.Random.nextInt

implicit val rabbitSpecies = new Species[gen.Repr] {

def random(rg: spire.random.Generator): gen.Repr = {

val rabbit = Rabbit(
1 + nextInt(2),
5 + 20 * nextDouble(),
1 + 4 * nextDouble(),
3 + 10 * nextDouble(),
10 + 5 * nextDouble(),
2 + 2 * nextDouble(),
3 + 5 * nextDouble(),
2 + 10 * nextDouble())
gen.to(rabbit)
}

def fitness(rg: gen.Repr): Double = {
val rabbit = gen.from(rg)
import rabbit._
a * 100 + 100.0 * b + 2.2 * (1.1 * c + 0.3 * d) + 1.3 * (1.4 * e - 3.1 * f + 1.3 * g) - 1.4 * h
}

}
// rabbitSpecies: AnyRef with Species[gen.Repr] = repl.MdocSession\$App\$\$anon\$1@7e95f5
``````

Run the genetic algorithm

``````import cats.implicits._

val ga = GeneticAlgorithm(populationSize = 100, numGenerations = 100)
// ga: GeneticAlgorithm[gen.Repr, ops.hlist.Mapper.<refinement>.this.type.Out] = GeneticAlgorithm(
//   populationSize = 100,
//   numGenerations = 100
// )

val log = ga.run(spire.random.Generator.rng)
// log: GeneticAlgorithmLog[gen.Repr] = GeneticAlgorithmLog(
//   winners = Vector(
//     2 :: 20.385950887947182 :: 4.910445709809158 :: 12.12435887675269 :: 14.651432690293163 :: 2.168451656811953 :: 3.916827807968075 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.12435887675269 :: 13.010357296919523 :: 2.168451656811953 :: 7.9024554192576995 :: 2.085801574125962 :: HNil,
//     1 :: 21.899194313153792 :: 4.910445709809158 :: 12.12435887675269 :: 14.651432690293163 :: 2.0646753968534672 :: 7.972108590202686 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.58669084198368 :: 14.651432690293163 :: 2.168451656811953 :: 7.809450200958542 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 4.374838179208588 :: 14.651432690293163 :: 2.168451656811953 :: 7.972108590202686 :: 6.654040836410464 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.12435887675269 :: 14.651432690293163 :: 2.65526205457222 :: 7.9024554192576995 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.76974023564594 :: 12.58669084198368 :: 14.363331586910709 :: 2.0646753968534672 :: 7.809450200958542 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.12435887675269 :: 14.651432690293163 :: 2.168451656811953 :: 7.9024554192576995 :: 6.551081255904378 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.58669084198368 :: 14.651432690293163 :: 3.0427644953241417 :: 7.9024554192576995 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.12435887675269 :: 14.651432690293163 :: 2.168451656811953 :: 6.710663971974638 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.12435887675269 :: 14.651432690293163 :: 2.168451656811953 :: 5.539143365145807 :: 6.8955369948822085 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.58669084198368 :: 14.651432690293163 :: 2.168451656811953 :: 7.972108590202686 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.58669084198368 :: 14.651432690293163 :: 2.168451656811953 :: 4.065425957777272 :: 3.59208157122551 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 11.873914810978517 :: 14.651432690293163 :: 2.168451656811953 :: 7.972108590202686 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 12.12435887675269 :: 13.644740142467557 :: 2.168451656811953 :: 7.972108590202686 :: 2.085801574125962 :: HNil,
//     2 :: 24.71394131419272 :: 4.910445709809158 :: 11.873914810978517 :: 14.651432690293163 :: 2.168451656811953 :: 7.181637294738287 :: 7.64743918318245 :: HNil...

val winner = log.winners.last
// winner: gen.Repr = 2 :: 24.71394131419272 :: 4.910445709809158 :: 12.58669084198368 :: 14.651432690293163 :: 2.168451656811953 :: 7.9024554192576995 :: 2.085801574125962 :: HNil
``````

Plot the min, average, and max fitness function by generation

``````import scala.collection.immutable.TreeMap
import axle.visualize._

val plot = Plot[String, Int, Double, TreeMap[Int,Double]](
() => List("min" -> log.mins, "ave" -> log.aves, "max" -> log.maxs),
connect = true,
colorOf = (label: String) => label match {
case "min" => Color.black
case "ave" => Color.blue
case "max" => Color.green },
title = Some("GA Demo"),
xAxis = Some(0d),
xAxisLabel = Some("generation"),
yAxis = Some(0),
yAxisLabel = Some("fitness"))
// plot: Plot[String, Int, Double, TreeMap[Int, Double]] = Plot(
//   dataFn = <function0>,
//   connect = true,
//   drawKey = true,
//   width = 700,
//   height = 600,
//   border = 50,
//   pointDiameter = 4,
//   keyWidth = 80,
//   fontName = "Courier New",
//   fontSize = 12,
//   bold = false,
//   titleFontName = "Palatino",
//   titleFontSize = 20,
//   colorOf = <function1>,
//   title = Some(value = "GA Demo"),
//   keyTitle = None,
//   xAxis = Some(value = 0.0),
//   xAxisLabel = Some(value = "generation"),
//   yAxis = Some(value = 0),
//   yAxisLabel = Some(value = "fitness")
// )
``````

Render to an SVG file

``````import axle.web._
import cats.effect._

plot.svg[IO]("ga.svg").unsafeRunSync()
``````