Photo by D koi on Unsplash

Adding Mutation

An excerpt from Genetic Algorithms in Elixir by Sean Moriarity

The Pragmatic Programmers
3 min readSep 25, 2023

--

Check out Sean’s Author Spotlight, where he talks about Elixir, Nx, functional programming, and machine learning.

https://pragprog.com/newsletter/
https://pragprog.com/newsletter/

Despite initializing your population to a seemingly random distribution, eventually the parents got too genetically similar to make any improvements during crossover. This illustrates the importance of including the mutation step in your algorithm and how vital exploration is to informed search techniques.

After the crossover function in the algorithm, add the following:

​ |> mutation.()

Now, the structure of the algorithm looks like this:

​ population
​ |> fitness.()
​ |> selection.()
​ |> crossover.()
​ |> mutation.()
​ |> algorithm.(algorithm)

Mutation is similar to the other functions in that it accepts a population as a parameter. You only want to mutate a small percentage of your population as well — this is to preserve the progress that’s already been made. Below your crossover definition, add the following:

​ mutation =
​ ​fn​ population ->
​ population
​ |> Enum.map(
​ ​fn​ chromosome ->
​ ​if​ ​:rand​.uniform() < 0.05 ​do​
​ Enum.shuffle(chromosome)
​ ​else​
​ chromosome
​ ​end​
​ ​end​)
​ ​end​

This function iterates over the entire population and randomly shuffles a chromosome with a probability of 5%. The :rand.uniform() < 0.05 condition is a pattern that emerges a lot throughout this book. It’s one way of simulating a random event in Elixir.

Enum.shuffle/1 takes in an enumerable and randomizes the elements in the enumerable. Think of it like shuffling a deck of cards. Doing this actually preserves the fitness of the chromosome; however, it also prevents the parents from becoming too similar before they crossover. You’ll learn more about this technique and others in Chapter 7, Preventing Premature Convergence.

With the mutation function implemented, you’re ready to try running your algorithm again, like this:

​ ​$ ​​elixir​​ ​​one_max.exs​
​ Current Best: 1000
​ Answer is
​ [1,1,1...,1]

Congratulations, you’ve just written your first genetic algorithm.

--

--

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.