Creating Children

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

The Pragmatic Programmers
The Pragmatic Programmers

--

👈 Selecting Parents | TOC | Running Your Solution 👉

With a population of parents prepared for crossover, it’s time to implement the crossover function.

Crossover is analogous to reproduction. It’s a genetic operator that takes two or more parent chromosomes and produces two or more child chromosomes. Thus far, the transformations have produced a list of tuples consisting of two 1000-length bitstrings. You want to produce a population you can pass back into the algorithm function. Implement the crossover function like this:

​ 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​

First, take note of the first argument passed to the anonymous function in Enum.reduce/3. Elixir has a rich set of pattern-matching features. In the selection step, the list of chromosomes was turned into a list of tuples of adjacent pairs. Because of this, you can use pattern-matching to extract the individual chromosomes — denoted p1 and p2 for Parent 1 and Parent 2 — and perform some operation on them.

Enum.reduce/3 requires the anonymous function to also accept an accumulator — denoted acc — which takes an initial…

--

--

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.