Running Your Solution

Genetic Algorithms in Elixir — by Sean Moriarity (16 / 101)

The Pragmatic Programmers
The Pragmatic Programmers

--

👈 Creating Children | TOC | Adding Mutation 👉

Your genetic algorithm will now look something like this:

​ population = for _ <- 1..100, ​do​: for _ <- 1..1000, ​do​: Enum.random(0..1)

​ evaluate =
​ ​fn​ population ->
​ Enum.sort_by(population, &Enum.sum/1, &>=/2)
​ ​end​

​ selection =
​ ​fn​ population ->
​ population
​ |> Enum.chunk_every(2)
​ |> Enum.map(&List.to_tuple(&1))
​ ​end​

​ crossover =
​ ​fn​ population ->
​ Enum.reduce(population, [],
​ ​fn​ {p1, p2}, acc ->
​ cx_point = ​:rand​.uniform(1000)
​ {{h1, t1}, {h2, t2}} =
​ {Enum.split(p1, cx_point),
​ Enum.split(p2, cx_point)}
​ [h1 ++ t2, h2 ++ t1 | acc]
​ ​end​
​ )
​ ​end​

​ algorithm =
​ ​fn​ population, algorithm ->
​ best = Enum.max_by(population, &Enum.sum/1)
​ IO.write(​"​​\rCurrent Best: "​ <> Integer.to_string(Enum.sum(best)))
​ ​if​ Enum.sum(best) == 1000 ​do​
​ best
​ ​else​
​ population
​ |> evaluate.()
​ |> selection.()
​ |> crossover.()
​ |> algorithm.(algorithm)
​ ​end​
​ ​end​

Your algorithm now has all of the necessary components it needs to produce a solution; however, you might be wondering why the mutation step was left out. You’ll find out in a minute — before then, try running your algorithm to ensure that everything works…

--

--

The Pragmatic Programmers
The Pragmatic Programmers

We create timely, practical books and learning resources on classic and cutting-edge topics to help you practice your craft and accelerate your career.