Creating Children
Genetic Algorithms in Elixir — by Sean Moriarity (15 / 101)
👈 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…