See the wikipedia page on Genetic Algorithms

## Example

Imports

``````import util.Random.nextDouble
import util.Random.nextInt
import shapeless._
import syntax.singleton._
import record._
import cats.implicits._
import axle.ml._
``````

Define a random rabbit generator and fitness function

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

val gen = Generic[Rabbit]
// gen: shapeless.Generic[Rabbit]{type Repr = shapeless.::[Int,shapeless.::[Double,shapeless.::[Double,shapeless.::[Double,shapeless.::[Double,shapeless.::[Double,shapeless.::[Double,shapeless.::[Double,shapeless.HNil]]]]]]]]} = anon\$macro\$9\$1@79773b6e

// val pMutation = 0.003

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

def random() = {
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: axle.ml.Species[gen.Repr] = \$anon\$1@dcce071
``````

Run the genetic algorithm

``````import spire.implicits._
// import spire.implicits._

val ga = GeneticAlgorithm(populationSize = 100, numGenerations = 100)
// ga: axle.ml.GeneticAlgorithm[gen.Repr,this.Out] = GeneticAlgorithm(100,100)

val log = ga.run()
// log: axle.ml.GeneticAlgorithmLog[gen.Repr] = GeneticAlgorithmLog(Vector(2 :: 24.980161350031135 :: 4.858622253941833 :: 11.665040144987167 :: 14.795637448999656 :: 2.1492945509626757 :: 7.99003730462035 :: 2.0175569325883673 :: HNil, 2 :: 24.980161350031135 :: 4.858622253941833 :: 11.665040144987167 :: 10.748435466027786 :: 2.1492945509626757 :: 7.99003730462035 :: 2.0175569325883673 :: HNil, 2 :: 24.980161350031135 :: 4.858622253941833 :: 11.665040144987167 :: 14.795637448999656 :: 2.1492945509626757 :: 7.99003730462035 :: 2.0175569325883673 :: HNil, 2 :: 24.980161350031135 :: 4.858622253941833 :: 6.3630747144225985 :: 14.795637448999656 :: 2.1492945509626757 :: 7.99003730462035 :: 2.0175569325883673 :: HNil, 2 :: 24.980161350031135 :: 4.858622253941833 :: 12.126979166700131 :: 12.4548...

val winner = log.winners.last
// winner: gen.Repr = 2 :: 24.980161350031135 :: 4.858622253941833 :: 12.75210545285702 :: 14.67406413664153 :: 2.1492945509626757 :: 7.99003730462035 :: 2.0175569325883673 :: HNil
``````

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

``````import scala.collection.immutable.TreeMap
// import scala.collection.immutable.TreeMap

import axle.eqTreeMap
// import axle.eqTreeMap

import axle.visualize._
// import axle.visualize._

val plot = Plot(
() => 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: axle.visualize.Plot[String,Int,Double,scala.collection.immutable.TreeMap[Int,Double]] = Plot(<function0>,true,true,700,600,50,4,20,50,80,Courier New,12,false,Palatino,20,<function1>,Some(GA Demo),None,Some(0.0),Some(generation),Some(0),Some(fitness))

import axle.web._
// import axle.web._

svg(plot, "ga.svg")
``````