avatarThe Pragmatic Programmers

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

1821

Abstract

</span>(p1, cx_point), ​ Enum.<span class="hljs-built_in">split</span>(p2, cx_point)}</pre></div><div id="6e2c"><pre>​ [h1 ++ t2, h2 ++ t1 | <span class="hljs-type">acc</span>] ​ ​<span class="hljs-keyword">end</span>​ ​ ) ​ ​<span class="hljs-keyword">end</span>​ ​ ​ algorithm = ​ ​fn​ population, algorithm -> ​ best = Enum.max_by(population, &Enum.<span class="hljs-built_in">sum</span>/<span class="hljs-number">1</span>) ​ IO.write(​<span class="hljs-string">"​​\rCurrent Best: "</span>​ <> Integer.to_string(Enum.<span class="hljs-built_in">sum</span>(best))) ​ ​<span class="hljs-keyword">if</span>​ Enum.<span class="hljs-built_in">sum</span>(best) == <span class="hljs-number">1000</span><span class="hljs-built_in">do</span>​ ​ best ​ ​<span class="hljs-keyword">else</span>​ ​ population ​ |<span class="hljs-type">> evaluate</span>.() ​ |<span class="hljs-type">> selection</span>.() ​ |<span class="hljs-type">> crossover</span>.() ​ |<span class="hljs-type">> algorithm</span>.(algorithm) ​ ​<span class="hljs-keyword">end</span>​ ​ ​<span class="hljs-keyword">end</span></pre></div><p id="fb1d">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 correctly.</p><p id="9cd9">Remember, the algorithm function takes a population and a reference to itself as input. Additionally, remember that it returns a solution when a maximum sum of 1000 is achieved. Add the following lines to the end of the one_max.exs file:</p><div id="bf3a"><pre>​ solution = algorithm.(population, algorithm)

Options

​ ​ IO.<span class="hljs-keyword">write</span>(​<span class="hljs-string">"​​\n Answer is \n"</span>​) ​ IO.<span class="hljs-keyword">inspect</span> solution</pre></div><p id="a870">Here, you assign the result of the completed algorithm (that is, the solution) to a variable named solution. You then output some text to the screen to show what your algorithm has come up with.</p><p id="c67d">Next, go back to your terminal and navigate to the scripts folder. Then run the following command:</p><div id="762e"><pre>​ ​<span class="hljs-variable">$ </span>​​elixir​​ ​​one_max.exs​ ​ Current <span class="hljs-symbol">Best:</span> <span class="hljs-number">982</span></pre></div><p id="3bdc">But wait, what’s going on here? Why is the algorithm stopping on a best fitness below 1000? It’s likely that, no matter how many times you run it, the algorithm’s improvement will almost certainly slow near 1000. You may even find it difficult for the problem to ever reach 1000. The problem is premature convergence.</p><p id="e56d"><i>👈 <a href="https://readmedium.com/creating-children-e4c3d51a1465">Creating Children</a> | <a href="https://readmedium.com/table-of-contents-879fc8614df">TOC</a> | <a href="https://readmedium.com/adding-mutation-1644030ad55d">Adding Mutation</a> 👉</i></p><p id="b5bf"><i>Genetic Algorithms in Elixir by Sean Moriarity can be purchased in other book formats <a href="https://pragprog.com/titles/smgaelixir">directly from the Pragmatic Programmers</a>. If you notice a code error or formatting mistake, please let us know <a href="https://readmedium.com/how-to-report-errata-4e164674347a">here</a> so that we can fix it.</i></p><figure id="5240"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*U2E2a23SuM4520w9CUXSWw.jpeg"><figcaption></figcaption></figure></article></body>

Running Your Solution

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

👈 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) == 1000do​
​       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 correctly.

Remember, the algorithm function takes a population and a reference to itself as input. Additionally, remember that it returns a solution when a maximum sum of 1000 is achieved. Add the following lines to the end of the one_max.exs file:

​ solution = algorithm.(population, algorithm)
​ 
​ IO.write(​"​​\n Answer is \n"​)
​ IO.inspect solution

Here, you assign the result of the completed algorithm (that is, the solution) to a variable named solution. You then output some text to the screen to show what your algorithm has come up with.

Next, go back to your terminal and navigate to the scripts folder. Then run the following command:

​ ​$ ​​elixir​​ ​​one_max.exs​
​ Current Best: 982

But wait, what’s going on here? Why is the algorithm stopping on a best fitness below 1000? It’s likely that, no matter how many times you run it, the algorithm’s improvement will almost certainly slow near 1000. You may even find it difficult for the problem to ever reach 1000. The problem is premature convergence.

👈 Creating Children | TOC | Adding Mutation 👉

Genetic Algorithms in Elixir by Sean Moriarity can be purchased in other book formats directly from the Pragmatic Programmers. If you notice a code error or formatting mistake, please let us know here so that we can fix it.

Smgaelixir
Recommended from ReadMedium