<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Bas Jacobs</title>
<link>https://www.basjacobs.com/</link>
<atom:link href="https://www.basjacobs.com/index.xml" rel="self" type="application/rss+xml"/>
<description>My blog about math, programming and data science</description>
<generator>quarto-1.7.33</generator>
<lastBuildDate>Wed, 06 May 2026 22:00:00 GMT</lastBuildDate>
<item>
  <title>Roelf (in Dutch)</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2026-05-07-roelf/</link>
  <description><![CDATA[ 





<p>In de podcast “We Love Nederlands” vertelt Yannick waaorm hij de naam <em>Roelf</em> zo mooi vindt. Volgens hem kan je elke letter weghalen en blijft er telkens weer een bestaande naam over. Haal je de <em>f</em> weg, krijg je <em>Roel</em>, haal je de <em>l</em> weg, krijg je <em>Roef</em>, et cetera. Haal je de <em>R</em> weg, krijg je <em>Oelf</em>, weer een naam. Helaas is volgens de Nederlandse Voornamenbank van het Meertens Instituut <a href="https://nvb.meertens.knaw.nl/naam/is/Oelf">Oelf</a> geen Nederlandse voornaam.</p>
<p>Benieuwd naar of er wel dat soort namen bestaan waarbij je na het weglaten van elke letter weer een naam krijgt, zocht ik naar een dataset van de voornamen van het Meertens Instituut. Ik vond <a href="https://raw.githubusercontent.com/bartbroere/namenlijsten/refs/heads/master/voornamen.json">deze lijst</a> die gemaakt is in 2013.</p>
<p>Er zijn veel namen waarvoor de <em>Roelf-eigenschap</em> geldt, maar de meeste komen weinig voor. Als het niet uitmaakt hoe vaak een naam voorkomt, zijn</p>
<pre><code>fionne: ionne, fonne, finne, fione, fione, fionn
rianna: ianna, ranna, rinna, riana, riana, riann
rienko: ienko, renko, rinko, rieko, rieno, rienk</code></pre>
<p>voorbeelden van gevallen met 6 letters.</p>
<p>Namen met minstens 4 letters waarvan alle varianten minstens 10 keer voorkomen, zijn de volgende.</p>
<pre><code>dayo: ayo, dyo, dao, day
dian: ian, dan, din, dia
jian: ian, jan, jin, jia
kayan: ayan, kyan, kaan, kayn, kaya
lian: ian, lan, lin, lia
mian: ian, man, min, mia
rian: ian, ran, rin, ria
shai: hai, sai, shi, sha
shui: hui, sui, shi, shu
wian: ian, wan, win, wia
yuri: uri, yri, yui, yur</code></pre>
<p>Als ze minstens 100 keer moeten zijn gegeven, blijven</p>
<pre><code>dian: ian, dan, din, dia
jian: ian, jan, jin, jia
lian: ian, lan, lin, lia</code></pre>
<p>over.</p>
<p>Overigens zijn er enorm veel 2- en 1-letterige namen, maar dat is valsspelen. Blijkbaar zijn JM, M én J allemaal namen die minstens 500 keer voorkomen in Nederland …</p>



 ]]></description>
  <guid>https://www.basjacobs.com/post/2026-05-07-roelf/</guid>
  <pubDate>Wed, 06 May 2026 22:00:00 GMT</pubDate>
</item>
<item>
  <title>WK-NHK</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2025-10-23-wk-nhk/</link>
  <description><![CDATA[ 





<p>I created a website <a href="https://www.wk-nhk.com/">www.wk-nhk.com</a> that shows <a href="https://news.web.nhk/news/easy/">NHK Web Easy</a> articles with custom furigana based on WaniKani level.</p>
<p>I try to read a couple of NHK Easy articles each day, but I found that even though I know some of the kanji, my eyes read the furigana anyways. That feels like cheating and it does not force me to practice the kanji.</p>
<p>In this new website, you can select your WaniKani level with the slider and watch the furigana you know disappear. That way, you are forced to read the kanji you are supposed know, and only see furigana for kanji you do not know.</p>
<p>The site updates each day via GitHub actions to show the latest articles. Find the code <a href="https://github.com/basjacobs93/wk-nhk/">here</a>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2025-10-23-wk-nhk/screenshot.png" class="img-fluid figure-img"></p>
<figcaption>Screenshot of the front page</figcaption>
</figure>
</div>



 ]]></description>
  <guid>https://www.basjacobs.com/post/2025-10-23-wk-nhk/</guid>
  <pubDate>Wed, 22 Oct 2025 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Japanese Learning Helper for Safari</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2025-09-05-japanese-learning-helper-for-safari/</link>
  <description><![CDATA[ 





<p>I vibe-coded a Safari extension that helps me practice Japanese while I am browsing the web. Find it <a href="https://github.com/basjacobs93/japanese-learning-helper">here</a>.</p>
<p>It connects to WaniKani to translate words of your level. It can translate a fixed set of nouns, all your WaniKani words, or full sentences. You can select the percentage of sentences it should translate. It is still a bit buggy, but it works for me. It is fun how easy it now is to create something like this!</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2025-09-05-japanese-learning-helper-for-safari/screenshot.png" class="img-fluid figure-img"></p>
<figcaption>Screenshot of the extension in action</figcaption>
</figure>
</div>



 ]]></description>
  <guid>https://www.basjacobs.com/post/2025-09-05-japanese-learning-helper-for-safari/</guid>
  <pubDate>Thu, 04 Sep 2025 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Short-toed Treecreepers Article</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2025-09-04-short-toed-treecreepers-article/</link>
  <description><![CDATA[ 





<p>The paper called <em>Factors influencing roost use by Short-toed Treecreepers Certhia brachydactyla at urban sites</em>, has been <a href="https://bioone.org/journals/ardea/volume-113/issue-1/arde.2024.a19/Factors-influencing-roost-use-by-Short-toed-Treecreepers-Certhia-brachydactyla/10.5253/arde.2024.a19.short">published</a>.</p>
<p>The most work was done by Dook who put in a lot of effort to create this great dataset, and Paul who did research and wrote the article. I am really happy and proud that I was able to assist with the statistics and graphs.</p>
<p><img src="https://www.basjacobs.com/post/2025-09-04-short-toed-treecreepers-article/img.png" class="img-fluid"></p>



 ]]></description>
  <guid>https://www.basjacobs.com/post/2025-09-04-short-toed-treecreepers-article/</guid>
  <pubDate>Wed, 03 Sep 2025 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Neurogram</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2025-08-15-neurogram/</link>
  <description><![CDATA[ 





<p>Find in <a href="https://github.com/basjacobs93/neurogram">this repository</a> an implementation of the <a href="https://en.wikipedia.org/wiki/Compositional_pattern-producing_network">CPPN-NEAT algorithm</a> to create networks that represent images. I tried to keep things simple and lightweight, using only <code>matplotlib</code> as a dependency for drawing the images. The dependency <code>networkx</code> was added for drawing the networks for debugging purposes. The networks themselves are simple Python objects. 6 networks (and hence images) are generated at random, and from then on two images can crossover in various ways into 6 new images, and so on.</p>
<p>I was heavily inspired by <a href="https://blog.otoro.net/2015/07/31/neurogram/">this blogpost</a>. They are able to generate way prettier images and explain how they did it in the post. I did not bother to fine-tune my parameters, this was merely a fun exercise to try and implement a neural network that evolves using a genetic algorithm. The topological sorting of the nodes was an interesting sub-problem to solve, because the nodes are not arranged in layers like in “normal” neural networks. According <a href="https://en.wikipedia.org/wiki/Depth-first_search">to Wikipedia</a>, listing the nodes in the opposite order of their last visit of a depth-first search produces a topological sorting. So that is what I did.</p>
<p>Also, I used <code>uv</code> for the first time (late to the party, I know), was impressed by the speed and convenience. I especially enjoyed the inline metadata format which allows the dependencies to be declared in the <code>.py</code> file itself. I will definitely use this more often for small scripts like this. Some output screenshots:</p>
<p><img src="https://www.basjacobs.com/post/2025-08-15-neurogram/neurogram-1.png" class="img-fluid"> <img src="https://www.basjacobs.com/post/2025-08-15-neurogram/neurogram-2.png" class="img-fluid"> <img src="https://www.basjacobs.com/post/2025-08-15-neurogram/neurogram-3.png" class="img-fluid"> <img src="https://www.basjacobs.com/post/2025-08-15-neurogram/neurogram-4.png" class="img-fluid"></p>



 ]]></description>
  <guid>https://www.basjacobs.com/post/2025-08-15-neurogram/</guid>
  <pubDate>Fri, 15 Aug 2025 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Dutch placename mapper</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2024-04-28-dutch-placename-mapper/</link>
  <description><![CDATA[ 





<p>Inspired by <a href="https://placenames.rtwilson.com">British Placename Mapper</a>, I thought I’d try to make such place name visualizations of the Netherlands myself.</p>
<p>The Dutch platform <a href="https://www.pdok.nl">PDOK</a> provides open geo-information datasets through webservices and downloads. Here, we use the <a href="https://api.pdok.nl/bzk/locatieserver/search/v3_1/ui/">location API</a> to search for residence locations using <a href="https://solr.apache.org/guide/6_6/the-standard-query-parser.html#the-standard-query-parser">Solr-syntax</a>. We also use the gray background map from PDOK, and use leaflet to create interactive maps.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(leaflet)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(sf)</span>
<span id="cb1-4"></span>
<span id="cb1-5">pdok_query_url <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://api.pdok.nl/bzk/locatieserver/search/v3_1/free?q={location}&amp;fq=type:woonplaats&amp;fq=bron:BAG&amp;fl=id woonplaatsnaam weergavenaam centroide_ll&amp;df=woonplaatsnaam&amp;rows=100"</span></span>
<span id="cb1-6">pdok_map_url <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://service.pdok.nl/brt/achtergrondkaart/wmts/v2_0/grijs/EPSG:3857/{z}/{x}/{y}.png"</span></span>
<span id="cb1-7"></span>
<span id="cb1-8">addLocationMarkers <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(map, location, fillColor) {</span>
<span id="cb1-9">  url <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">URLencode</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str_glue</span>(pdok_query_url))</span>
<span id="cb1-10">  res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> jsonlite<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_json</span>(url, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">simplifyVector =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb1-11"></span>
<span id="cb1-12">  df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">bind_rows</span>(res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>response<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>docs) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb1-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lng =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str_extract</span>(centroide_ll, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">d</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">.]+</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">s"</span>)),</span>
<span id="cb1-14">           <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lat =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str_extract</span>(centroide_ll, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">s[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">d</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">.]+"</span>)))</span>
<span id="cb1-15"></span>
<span id="cb1-16">  map <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addCircleMarkers</span>(map, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lng=</span>df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lng, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lat=</span>df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lat, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">popup =</span> df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>woonplaatsnaam,</span>
<span id="cb1-17">                          <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stroke =</span> F, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">radius =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fillOpacity =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fillColor =</span> fillColor, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> fillColor)</span>
<span id="cb1-18"></span>
<span id="cb1-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(map)</span>
<span id="cb1-20">}</span>
<span id="cb1-21"></span>
<span id="cb1-22">create_map <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(markers) {</span>
<span id="cb1-23"></span>
<span id="cb1-24">  map <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">leaflet</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb1-25">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setView</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">zoom=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lng=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5.4</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lat=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">52.2</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb1-26">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addTiles</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">urlTemplate =</span> pdok_map_url,</span>
<span id="cb1-27">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">attribution =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;a href='https://www.pdok.nl/'&gt;PDOK&lt;/a&gt;"</span>,</span>
<span id="cb1-28">             <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">options =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tileOptions</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">minZoom =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">maxZoom =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>)</span>
<span id="cb1-29">    )</span>
<span id="cb1-30"></span>
<span id="cb1-31">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (location <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(markers)) {</span>
<span id="cb1-32">    map <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addLocationMarkers</span>(map, location, markers[[location]])</span>
<span id="cb1-33">  }</span>
<span id="cb1-34">  map <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addLegend</span>(map, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">position =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottomright"</span>,</span>
<span id="cb1-35">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colors =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unname</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unlist</span>(markers)),</span>
<span id="cb1-36">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">names</span>(markers),</span>
<span id="cb1-37">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">opacity =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-38">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(map)</span>
<span id="cb1-39">}</span></code></pre></div>
</div>
<p>This allows us to create maps of common <a href="https://nl.wikipedia.org/wiki/Toponiem">Dutch toponym patterns</a>, such as “loo” (Germanic), “recht” (Roman) or “ga” (Frisian).</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">create_map</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb2-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*loo OR *lo OR *le"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"blue"</span>,</span>
<span id="cb2-3">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*recht OR *richt"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"green"</span>,</span>
<span id="cb2-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*ga"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span>,</span>
<span id="cb2-5">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*wolde"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"orange"</span>,</span>
<span id="cb2-6">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*schot"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"black"</span>,</span>
<span id="cb2-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*wijk"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"magenta"</span></span>
<span id="cb2-8">))</span></code></pre></div>
<div class="cell-output-display">
<div class="leaflet html-widget html-fill-item" id="htmlwidget-fda316a7081467a71a1f" style="width:100%;height:464px;"></div>
<script type="application/json" data-for="htmlwidget-fda316a7081467a71a1f">{"x":{"options":{"crs":{"crsClass":"L.CRS.EPSG3857","code":null,"proj4def":null,"projectedBounds":null,"options":{}}},"setView":[[52.2,5.4],7,[]],"calls":[{"method":"addTiles","args":["https://service.pdok.nl/brt/achtergrondkaart/wmts/v2_0/grijs/EPSG:3857/{z}/{x}/{y}.png",null,null,{"minZoom":6,"maxZoom":18,"tileSize":256,"subdomains":"abc","errorTileUrl":"","tms":false,"noWrap":false,"zoomOffset":0,"zoomReverse":false,"opacity":1,"zIndex":1,"detectRetina":false,"attribution":"<a href='https://www.pdok.nl/'>PDOK<\/a>"}]},{"method":"addCircleMarkers","args":[[52.43181299,51.51385272,52.38772556,52.35771367,51.98354752,53.04257485,51.43583268,51.33202606,52.73914231,53.35738676,53.00140342,52.21794138,53.2382153,52.10612921,51.41975911,51.90665514,51.934929,52.4277221,51.86511076,52.83458183,52.96276485,52.94138792,50.94914909,52.28824931,52.88437871,52.99382948,50.92311772,51.50888838,52.03806534,52.93051319,52.35296921,52.40673026,52.10773155,51.99994952,53.03958759,51.51684551,52.59985335,52.05399571,52.25490615,52.12550259,52.11272996,52.00572484,51.47872656,53.22085508,52.84077782,53.09515481,52.45774423,52.27752426,51.93006302,51.9332714,52.2353596,52.41471656,51.51131653,51.46384215,51.53160925,51.43923072,52.04923557,52.63870126,51.72164632,51.50921389,51.57363309,51.59490591,52.07916737,52.93960972,52.81029273,52.91897543,53.14485095,52.06557218,52.89475673,52.48711385,52.48834455,53.10276015,51.68868184,53.03613503,51.31169521,53.01639884,52.93784607,52.23959591,53.07904732,51.37905246,53.07767633,52.34437561,51.53129315,51.96633181,52.80908384,52.51868565],[5.96008498,5.64940863,6.89089503,6.65988219,6.11851032,6.70006602,4.92216568,6.08543934,5.95193733,6.50847594,6.62796226,6.68746277,5.71577641,6.51348302,3.75119036,4.16678789,4.58013769,6.53791752,6.48617146,6.38794776,6.61532724,6.24310638,5.75866486,5.66616511,6.8655502,6.35563226,5.74680109,5.0528502,6.63879682,6.66992726,6.3861551,6.83651722,6.57057763,6.42927301,6.30827026,4.36513749,4.70857318,6.33429763,6.77819416,5.90857642,5.85679117,6.24760908,3.95907702,6.09306122,5.84383179,6.45062301,6.41370511,6.27670797,5.98610562,5.96668531,6.51336678,6.12351423,6.08763315,6.08989398,5.92118054,5.61066415,4.58623075,5.71517383,3.79323062,6.0369467,3.55001548,5.84135852,5.79425079,5.81258845,6.00227407,5.85535862,6.09627846,6.46485551,6.70722315,6.62666463,6.65599933,6.00373659,5.00136906,6.62589097,4.04596701,5.78962163,5.70281875,6.10040614,6.61879175,6.1488133,7.14020608,6.86661838,3.4552999,6.65850533,6.74703116,6.11836361],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"blue","weight":5,"opacity":0.5,"fill":true,"fillColor":"blue","fillOpacity":1},null,null,["'t Loo Oldebroek","Aarle-Rixtel","Agelo","Almelo","Angerlo","Anloo","Baarle-Nassau","Baarlo","Baarlo","Baflo","Balloo","Bentelo","Bitgummole","Borculo","Borssele","Brielle","Capelle aan den IJssel","Daarle","Dinxperlo","Dwingeloo","Eldersloo","Elsloo","Elsloo","Ermelo","Exloo","Fochteloo","Geulle","Goirle","Groenlo","Grolloo","Haarle","Haarle","Haarlo","Halle","Haule","Heerle","Heiloo","Hengelo (Gld)","Hengelo","Hoenderloo","Hoenderloo","Hummelo","Kapelle","Kootstertille","Langelille","Langelo","Lemele","Lettele","Loo Gld","Loo Gld","Markelo","Marle","Meerlo","Melderslo","Merselo","Mierlo","Moerkapelle","Nagele","Noordwelle","Oirlo","Oostkapelle","Oploo","Otterlo","Ouwsterhaule","Paasloo","Rotsterhaule","Rottevalle","Ruurlo","Schoonloo","Sibculo","Sibculo","Smalle Ee","Sprang-Capelle","Taarlo","Terhole","Terkaple","Teroele","Twello","Tynaarlo","Venlo","Vriescheloo","Weerselo","Westkapelle","Winterswijk Corle","Zweeloo","Zwolle"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[52.32295314,51.85106556,51.7815073,52.33035118,52.00362477,51.01821032,52.20051406,50.85296715,50.91571411,52.21200875,51.99808618,52.74334497,51.39506366,51.83323777,51.83068699,51.90769571,52.0886922,51.41908999,51.81852255],[4.92651544,4.52543794,4.7088743,4.93992756,4.79144484,5.84019739,5.085112,5.6995303,5.77754563,4.85391385,4.65236823,6.96212001,4.33529985,4.703344,4.7729476,5.25906477,5.09520363,4.28590253,4.61841496],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"green","weight":5,"opacity":0.5,"fill":true,"fillColor":"green","fillOpacity":1},null,null,["Amsterdam-Duivendrecht","Barendrecht","Dordrecht","Duivendrecht","Haastrecht","Limbricht","Loosdrecht","Maastricht","Maastricht-Airport","Mijdrecht","Moordrecht","Nieuw-Dordrecht","Ossendrecht","Papendrecht","Sliedrecht","Tricht","Utrecht","Woensdrecht","Zwijndrecht"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[53.0185602,53.21972537,52.83522118,52.90253184,52.86782737,52.8839775,53.05352768,52.97759137,52.97927833,53.05297973,52.97714206,53.24806907,53.12789508,52.90950223,53.11701305,52.99243797,52.93094711,53.01359948,52.85404652,52.92322883,52.93273321,52.86449509,52.81478907,53.00119258,52.87223004,52.87225741,52.92910893],[5.57229823,6.16267197,5.7950242,5.74550791,5.71345635,5.72084212,5.70114044,5.56114739,6.11939682,5.66880984,6.22576268,5.59194555,6.02758544,5.5156008,5.9673522,5.55328026,5.80708562,5.46902385,6.04563859,5.75425151,5.8698856,5.97339755,5.87209326,5.71583367,6.12017707,6.00689309,5.61031964],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"red","weight":5,"opacity":0.5,"fill":true,"fillColor":"red","fillOpacity":1},null,null,["Abbega","Augustinusga","Bantega","Doniaga","Eesterga","Follega","Goënga","Idzega","Jubbega","Loënga","Makkinga","Minnertsga","Nijega","Oudega","Oudega","Oudega","Ouwster-Nijega","Parrega","Peperga","Sint Nicolaasga","Sintjohannesga","Sonnega","Spanga","Uitwellingerga","Vinkega","Wolvega","Ypecolsga"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[53.11174223,53.17887364,53.23507588,53.1577844,53.25101337,52.89567764,53.14137027,53.16010084,53.18319174,53.19402675,52.90232539,53.27836058,52.88992416,52.91606981,52.47563968,53.00185836,53.15312292,53.17491524,52.77136781,53.23721436,52.27163988,52.34436139,52.66254184,53.2622713],[7.16055389,6.53558492,7.11207575,6.4587789,6.66001568,5.49782054,6.71359576,6.42760082,6.29687216,6.38732021,5.9696952,6.57849552,6.13885763,5.98713333,5.89408003,6.30548217,6.55910297,6.47104767,6.0176132,6.8061624,6.08120669,5.45524194,6.4192588,6.60082208],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"orange","weight":5,"opacity":0.5,"fill":true,"fillColor":"orange","fillOpacity":1},null,null,["Bellingwolde","Eelderwolde","Finsterwolde","Foxwolde","Garmerwolde","Kolderwolde","Kropswolde","Leutingewolde","Lucaswolde","Midwolde","Nijeholtwolde","Noordwolde","Noordwolde","Oldeholtwolde","Oosterwolde Gld","Oosterwolde","Paterswolde","Roderwolde","Scheerwolde","Schildwolde","Terwolde","Zeewolde","Zuidwolde","Zuidwolde"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[51.57700949,51.56357172,51.51045603],[5.13891347,4.88510824,5.31456001],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"black","weight":5,"opacity":0.5,"fill":true,"fillColor":"black","fillOpacity":1},null,null,["Berkel-Enschot","Molenschot","Oirschot"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[52.482063,52.02250063,51.88972341,52.67043765,51.86169467,52.3374905,53.05823063,51.65794566,51.75099321,52.19780288,51.77981919,52.17254252,51.99348498,52.27100002,53.16666025,51.56651612,51.87902256,52.5693275,52.17466539,51.94722014,52.04599159,51.95086901,51.80045173,52.03619628,51.98564209,51.814926,51.88812223,52.78903877,51.96904484,51.78819007,51.69429969,52.4531131,52.49161771,51.97430523,51.75811739,51.95360108,51.96633181,51.98172442,52.00277936,51.93883163,52.0134912,51.94098722,51.97912843,51.92612776,51.97191709],[4.66794877,4.53452193,4.8122003,6.31507953,5.72631479,5.63588418,6.33946212,5.48787568,5.86097789,4.40210035,5.2098652,5.75967774,4.20932923,4.462659,6.25775685,5.21633567,5.06956862,6.71474858,5.83417867,5.69436068,4.73688151,5.35998391,5.01085722,4.32603246,5.19534649,4.94103394,5.77895702,6.12631757,4.75462053,4.9990355,5.06886048,6.62670557,4.60226579,5.32422269,5.09870582,6.75037134,6.65850533,6.75972092,6.76192715,6.77155673,6.7033531,6.66543614,6.80431094,6.71490707,6.71168135],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"magenta","weight":5,"opacity":0.5,"fill":true,"fillColor":"magenta","fillOpacity":1},null,null,["Beverwijk","Bleiswijk","Brandwijk","de Wijk","Ewijk","Harderwijk","Haulerwijk","Heeswijk-Dinther","Katwijk NB","Katwijk","Kerkwijk","Kootwijk","Naaldwijk","Noordwijk","Noordwijk","Oisterwijk","Oosterwijk","Radewijk","Radio Kootwijk","Randwijk","Reeuwijk","Rijswijk (GLD)","Rijswijk (NB)","Rijswijk","Schalkwijk","Sleeuwijk","Slijk-Ewijk","Steenwijk","Stolwijk","Uitwijk","Waalwijk","Westerhaar-Vriezenveensewijk","Wijk aan Zee","Wijk bij Duurstede","Wijk en Aalburg","Winterswijk Brinkheurne","Winterswijk Corle","Winterswijk Henxel","Winterswijk Huppel","Winterswijk Kotten","Winterswijk Meddo","Winterswijk Miste","Winterswijk Ratum","Winterswijk Woold","Winterswijk"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addLegend","args":[{"colors":["blue","green","red","orange","black","magenta"],"labels":["*loo OR *lo OR *le","*recht OR *richt","*ga","*wolde","*schot","*wijk"],"na_color":null,"na_label":"NA","opacity":1,"position":"bottomright","type":"unknown","title":null,"extra":null,"layerId":null,"className":"info legend","group":null}]}],"limits":{"lat":[50.85296715,53.35738676],"lng":[3.4552999,7.16055389]}},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>Or places which contain river names:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">create_map</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb3-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*rijn*"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span>,</span>
<span id="cb3-3">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*maas*"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"green"</span>,</span>
<span id="cb3-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*lek*"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"orange"</span>,</span>
<span id="cb3-5">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*ijssel*"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"blue"</span>,</span>
<span id="cb3-6">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*zaan*"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"black"</span>,</span>
<span id="cb3-7">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*waal*"</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"magenta"</span></span>
<span id="cb3-8">))</span></code></pre></div>
<div class="cell-output-display">
<div class="leaflet html-widget html-fill-item" id="htmlwidget-0812bbe4d3f3e6fbcab4" style="width:100%;height:464px;"></div>
<script type="application/json" data-for="htmlwidget-0812bbe4d3f3e6fbcab4">{"x":{"options":{"crs":{"crsClass":"L.CRS.EPSG3857","code":null,"proj4def":null,"projectedBounds":null,"options":{}}},"setView":[[52.2,5.4],7,[]],"calls":[{"method":"addTiles","args":["https://service.pdok.nl/brt/achtergrondkaart/wmts/v2_0/grijs/EPSG:3857/{z}/{x}/{y}.png",null,null,{"minZoom":6,"maxZoom":18,"tileSize":256,"subdomains":"abc","errorTileUrl":"","tms":false,"noWrap":false,"zoomOffset":0,"zoomReverse":false,"opacity":1,"zIndex":1,"detectRetina":false,"attribution":"<a href='https://www.pdok.nl/'>PDOK<\/a>"}]},{"method":"addCircleMarkers","args":[[52.13021386,52.12535594,52.14210004,51.86218518,51.84354448,52.08307453,52.83712851,52.85266972,52.19858648,52.19603136],[4.66520561,4.5941276,4.59543591,6.02883651,5.28285905,4.80623376,5.91148639,5.94638838,4.67182134,4.44834742],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"red","weight":5,"opacity":0.5,"fill":true,"fillColor":"red","fillOpacity":1},null,null,["Alphen aan den Rijn","Hazerswoude-Rijndijk","Koudekerk aan den Rijn","Millingen aan de Rijn","Neerijnen","Nieuwerbrug aan den Rijn","Nijetrijne","Oldetrijne","Rijnsaterwoude","Rijnsburg"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[51.8354783,51.14769024,51.36521207,51.78711937,51.95697852,51.57146084,51.94486314,51.92519893,50.85296715,50.91571411,51.95631371,51.78807378],[5.52505953,5.89871792,6.04628136,4.54834708,4.21248681,6.02877381,4.28020682,4.24886654,5.6995303,5.77754563,4.013754,4.46570178],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"green","weight":5,"opacity":0.5,"fill":true,"fillColor":"green","fillOpacity":1},null,null,["Maasbommel","Maasbracht","Maasbree","Maasdam","Maasdijk","Maashees","Maasland","Maassluis","Maastricht","Maastricht-Airport","Maasvlakte Rotterdam","Westmaas"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[51.88271921,51.89993725,51.9107317,53.22488872,51.88604518,51.95029293],[4.27745862,4.61812794,4.69499699,5.83091095,4.69738243,4.94255468],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"orange","weight":5,"opacity":0.5,"fill":true,"fillColor":"orange","fillOpacity":1},null,null,["Botlek Rotterdam","Krimpen aan de Lek","Lekkerkerk","Lekkum","Nieuw-Lekkerland","Tienhoven aan de Lek"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[51.934929,52.80670656,52.5659651,52.02771247,51.91469695,51.96639864,51.94095205,51.48509954],[4.58013769,5.96268261,5.94844712,5.02879098,4.60210186,4.61844396,4.65499857,5.89425571],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"blue","weight":5,"opacity":0.5,"fill":true,"fillColor":"blue","fillOpacity":1},null,null,["Capelle aan den IJssel","IJsselham","IJsselmuiden","IJsselstein","Krimpen aan den IJssel","Nieuwerkerk aan den IJssel","Ouderkerk aan den IJssel","Ysselsteyn"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[52.46190001,52.45196353,52.45122275,52.4454116,52.47407686],[4.79987222,4.87610965,4.77334703,4.82520183,4.79999744],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"black","weight":5,"opacity":0.5,"fill":true,"fillColor":"black","fillOpacity":1},null,null,["Koog aan de Zaan","Oostzaan","Westzaan","Zaandam","Zaandijk"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addCircleMarkers","args":[[53.07675366,51.76834514,51.80874428,51.99918805,51.93823393,51.38729123,51.69429969,51.87280555],[4.82499749,4.45477655,5.1705763,5.1436267,4.89964502,5.46486947,5.06886048,4.20786322],5,null,null,{"interactive":true,"className":"","stroke":false,"color":"magenta","weight":5,"opacity":0.5,"fill":true,"fillColor":"magenta","fillOpacity":1},null,null,["De Waal","Klaaswaal","Nieuwaal","Tull en 't Waal","Waal","Waalre","Waalwijk","Zwartewaal"],null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]},{"method":"addLegend","args":[{"colors":["red","green","orange","blue","black","magenta"],"labels":["*rijn*","*maas*","*lek*","*ijssel*","*zaan*","*waal*"],"na_color":null,"na_label":"NA","opacity":1,"position":"bottomright","type":"unknown","title":null,"extra":null,"layerId":null,"className":"info legend","group":null}]}],"limits":{"lat":[50.85296715,53.22488872],"lng":[4.013754,6.04628136]}},"evals":[],"jsHooks":[]}</script>
</div>
</div>



 ]]></description>
  <guid>https://www.basjacobs.com/post/2024-04-28-dutch-placename-mapper/</guid>
  <pubDate>Sat, 27 Apr 2024 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Physics-informed neural network for population dynamics</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/</link>
  <description><![CDATA[ 





<p>A Physics-Informed Neural Network (PINN) is a neural network that incorporates knowledge about physical laws alongside data. These physical (or chemical, or biological) laws can be incorporated into the network in the form of differential equations. Among other things, PINNs can be used to estimate parameters of a differential equation based on observational data.</p>
<p>Last week, Dr.&nbsp;Riccardo Taormina gave a guest lecture in my organization in which he explained the workings and advantages of PINNs. In the accompanying workshop he used synthetic data to show that it is possible to estimate the parameters of differential equations of a harmonic oscillator and an advection–diffusion process.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.leesonphoto.com/img-get/I0000kPSyrcMzSLs/s/600/600/TK115901.jpg" class="img-fluid figure-img"></p>
<figcaption>Lynx and snowshoe hare (photo by Tom and Pat Leeson)</figcaption>
</figure>
</div>
<p>I once read <a href="https://mc-stan.org/users/documentation/case-studies/lotka-volterra-predator-prey.html">an article by Bob Carpenter</a> about predator-prey population dynamics of hares and lynxes in Canada. The interesting thing of this article is that it uses actual observations rather than synthetical data. The author uses data for the number of pelts of these hares and lynxes obtained by Hudson’s Bay Company in the years 1900-1920 to estimate the parameters of a <a href="https://en.wikipedia.org/wiki/Lotka–Volterra_equations">Lotka-Volterra model</a>. He uses the statistical modeling software <a href="https://mc-stan.org">Stan</a> to generate these estimates based on Markov-Chain Monte-Carlo. This gives posterior estimates (distributions), which elegantly account for measurement and estimation uncertainty. In the <a href="https://jmahaffy.sdsu.edu/courses/f09/math636/lectures/lotka/qualde2.html">Joseph M. Mahaffy course Mathematical Modeling</a>, the author uses an optimization routine to estimate the parameters of the Lotka-Volterra equations using the same dataset.</p>
<p>In this post, I will show that PINNs can also be used to estimate those parameters. Let’s get started!</p>
<section id="packages" class="level2">
<h2 class="anchored" data-anchor-id="packages">Packages</h2>
<p>We will use the Python language with packages Pandas to load the data, Torch to train the neural network and M:w plotlib for plotting.</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>matplotlib inline</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb1-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torch <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> nn</span>
<span id="cb1-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> matplotlib <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span></code></pre></div>
</section>
<section id="the-data" class="level2">
<h2 class="anchored" data-anchor-id="the-data">The data</h2>
<p>The data can be downloaded from various places, all derived from http://www.math.tamu.edu/~phoward/m442/modbasics.pdf. I load it from <a href="https://raw.githubusercontent.com/cas-bioinf/statistical-simulations/master/hudson-bay-lynx-hare.csv">here</a>. The dataset consists of observations of lynxes and Hare pelts (in thousands) across the years 1900 to 1920.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">url <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://raw.githubusercontent.com/cas-bioinf/statistical-simulations/master/hudson-bay-lynx-hare.csv"</span></span>
<span id="cb2-2">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(url, sep<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">",</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">s"</span>, skiprows<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, index_col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb2-3">df</span></code></pre></div>
<div>

<table class="dataframe table table-sm table-striped small">
<thead>
<tr>
<th>
</th>
<th>
Lynx
</th>
<th>
Hare
</th>
</tr>
<tr>
<th>
Year
</th>
<th>
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<th>
1900
</th>
<td>
4.0
</td>
<td>
30.0
</td>
</tr>
<tr>
<th>
1901
</th>
<td>
6.1
</td>
<td>
47.2
</td>
</tr>
<tr>
<th>
1902
</th>
<td>
9.8
</td>
<td>
70.2
</td>
</tr>
<tr>
<th>
1903
</th>
<td>
35.2
</td>
<td>
77.4
</td>
</tr>
<tr>
<th>
1904
</th>
<td>
59.4
</td>
<td>
36.3
</td>
</tr>
<tr>
<th>
1905
</th>
<td>
41.7
</td>
<td>
20.6
</td>
</tr>
<tr>
<th>
1906
</th>
<td>
19.0
</td>
<td>
18.1
</td>
</tr>
<tr>
<th>
1907
</th>
<td>
13.0
</td>
<td>
21.4
</td>
</tr>
<tr>
<th>
1908
</th>
<td>
8.3
</td>
<td>
22.0
</td>
</tr>
<tr>
<th>
1909
</th>
<td>
9.1
</td>
<td>
25.4
</td>
</tr>
<tr>
<th>
1910
</th>
<td>
7.4
</td>
<td>
27.1
</td>
</tr>
<tr>
<th>
1911
</th>
<td>
8.0
</td>
<td>
40.3
</td>
</tr>
<tr>
<th>
1912
</th>
<td>
12.3
</td>
<td>
57.0
</td>
</tr>
<tr>
<th>
1913
</th>
<td>
19.5
</td>
<td>
76.6
</td>
</tr>
<tr>
<th>
1914
</th>
<td>
45.7
</td>
<td>
52.3
</td>
</tr>
<tr>
<th>
1915
</th>
<td>
51.1
</td>
<td>
19.5
</td>
</tr>
<tr>
<th>
1916
</th>
<td>
29.7
</td>
<td>
11.2
</td>
</tr>
<tr>
<th>
1917
</th>
<td>
15.8
</td>
<td>
7.6
</td>
</tr>
<tr>
<th>
1918
</th>
<td>
9.7
</td>
<td>
14.6
</td>
</tr>
<tr>
<th>
1919
</th>
<td>
10.1
</td>
<td>
16.2
</td>
</tr>
<tr>
<th>
1920
</th>
<td>
8.6
</td>
<td>
24.7
</td>
</tr>
</tbody>
</table>
</div>
<p>The data follow a cyclical pattern in which increases in the population of hares are followed by increases in the lynx populations in the subsequent years.</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hare"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lynx"</span>]].plot(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>), grid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, xticks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.index.astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)[::<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], title<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hudson Bay Lynx-Hare Dataset"</span>, ylabel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of pelts (thousands)"</span>)</span></code></pre></div>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_5_1.png" class="img-fluid" width="600"></p>
</section>
<section id="the-lotka-volterra-model" class="level2">
<h2 class="anchored" data-anchor-id="the-lotka-volterra-model">The Lotka-Volterra model</h2>
<p>The Lotka-Volterra population model the change of predator and pray populations over time: - <img src="https://latex.codecogs.com/png.latex?u(t)%5Cge0"> is the population size of the prey species at time t (the hare in our case), and - <img src="https://latex.codecogs.com/png.latex?v(t)%5Cge0"> is the population size of the predator species (the lynx in our case).</p>
<p>By using such a model, some assumptions are made on the dynamics of these populations. We will not go into those here, but they can be found on the <a href="https://en.wikipedia.org/wiki/Lotka–Volterra_equations">Wikipedia page</a>. The population sizes over times of the two species are modelled in terms of four parameters, <img src="https://latex.codecogs.com/png.latex?%5Calpha,%5Cbeta,%5Cgamma,%5Cdelta%5Cge0"> as</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cmathrm%7Bd%7D%7D%7B%5Cmathrm%7Bd%7Dt%7D%20u%20=%20%5Calpha%20u%20-%20%5Cbeta%20u%20v%0A"> <img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cmathrm%7Bd%7D%7D%7B%5Cmathrm%7Bd%7Dt%7D%20v%20=%20%5Cdelta%20uv%20-%20%5Cgamma%20v%0A"></p>
<p>It is these four parameters we will estimate in this post. They have the following interpretations: - <img src="https://latex.codecogs.com/png.latex?%5Calpha"> is the growth rate of the prey population, - <img src="https://latex.codecogs.com/png.latex?%5Cbeta"> is the rate of shrinkage relative to the product of the population sizes, - <img src="https://latex.codecogs.com/png.latex?%5Cgamma"> is the shrinkage rate of the predator population, - <img src="https://latex.codecogs.com/png.latex?%5Cdelta"> is the growth rate of the predator population as a factor of the product of the population sizes.</p>
<p>In the Stan article, the author obtains posterior mean point estimates</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%7B%5Calpha%7D%20=%200.55,%5Cquad%0A%5Chat%7B%5Cbeta%7D%20=%200.028,%5Cquad%0A%5Chat%7B%5Cgamma%7D%20=%200.80,%5Cquad%0A%5Chat%7B%5Cdelta%7D%20=%200.024,%0A"> and in the Mathematical Modeling course, the author obtains <img src="https://latex.codecogs.com/png.latex?%0A%5Calpha%5E*%20=%200.55,%5Cquad%0A%5Cbeta%5E*%20=%200.028,%5Cquad%0A%5Cgamma%5E*%20=%200.84,%5Cquad%0A%5Cdelta%5E*%20=%200.026.%0A"></p>
<p>To begin, we first set up some plotting functionality for keeping track of the training progress.</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_result(i, t, y, yh, loss, xp<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, lossp<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, params<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb4-2">    plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb4-3">    plt.xlim(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>)</span>
<span id="cb4-4">    plt.ylim(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">85</span>)</span>
<span id="cb4-5"></span>
<span id="cb4-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Data</span></span>
<span id="cb4-7">    plt.plot(t, y, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"o-"</span>, linewidth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Exact hare"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Exact lynx"</span>])</span>
<span id="cb4-8">    plt.gca().set_prop_cycle(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># reset the colors</span></span>
<span id="cb4-9">    plt.plot(t, yh, linewidth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Prediction hare"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Prediction lynx"</span>])</span>
<span id="cb4-10"></span>
<span id="cb4-11">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Physics training ticks</span></span>
<span id="cb4-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> xp <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb4-13">        plt.scatter(xp, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>torch.ones_like(xp), s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tab:green"</span>, alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, marker<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"|"</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Physics loss timesteps"</span>)</span>
<span id="cb4-14"></span>
<span id="cb4-15">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Legend</span></span>
<span id="cb4-16">    l <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.legend(loc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.56</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>), frameon<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"large"</span>)</span>
<span id="cb4-17">    plt.setp(l.get_texts(), color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k"</span>)</span>
<span id="cb4-18"></span>
<span id="cb4-19">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Title</span></span>
<span id="cb4-20">    plt.text(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">23</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">73</span>, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Training step: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"xx-large"</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k"</span>)</span>
<span id="cb4-21">    rmse_text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"RMSE data: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(loss))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb4-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> lossp <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb4-23">        rmse_text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f", physics: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(lossp))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb4-24">    plt.text(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">23</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>, rmse_text, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"medium"</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k"</span>)</span>
<span id="cb4-25">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> params <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb4-26">        plt.text(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">23</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</span>, params, fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"medium"</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k"</span>)</span>
<span id="cb4-27"></span>
<span id="cb4-28">    plt.axis(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"off"</span>)</span>
<span id="cb4-29">    plt.show()</span></code></pre></div>
<p>The inputs for the model are the timesteps <img src="https://latex.codecogs.com/png.latex?t=0..20"> corresponding to the years 1900-1920 and the outputs are the numbers of hares and lynxes.</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Timestep"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(df.index)</span>
<span id="cb5-2">t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor(df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Timestep"</span>].values, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.float32).view(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb5-3">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor(df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hare"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lynx"</span>]].values, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.float32)</span></code></pre></div>
<p>First, we define a simple dense feed-forward neural network using Torch.</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NN(nn.Module):</span>
<span id="cb6-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, n_input, n_output, n_hidden, n_layers):</span>
<span id="cb6-3">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb6-4">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.encode <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(nn.Linear(n_input, n_hidden), nn.Tanh())</span>
<span id="cb6-5">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.hidden <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>[nn.Sequential(nn.Linear(n_hidden, n_hidden), nn.Tanh()) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(n_layers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)])</span>
<span id="cb6-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.decode <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Linear(n_hidden, n_output)</span>
<span id="cb6-7"></span>
<span id="cb6-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x):</span>
<span id="cb6-9">        x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.encode(x)</span>
<span id="cb6-10">        x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.hidden(x)</span>
<span id="cb6-11">        x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.decode(x)</span>
<span id="cb6-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> x</span></code></pre></div>
<p>We can train neural network on the dataset (predicting the number of lynx and hares based on timestep <img src="https://latex.codecogs.com/png.latex?t">) and see that it is complex enough to be able to fit the dataset well. This takes a couple of seconds on my machine.</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">torch.manual_seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">123</span>)</span>
<span id="cb7-2">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> NN(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb7-3">optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.optim.Adam(model.parameters(), lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-3</span>)</span>
<span id="cb7-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50000</span>):</span>
<span id="cb7-5">    optimizer.zero_grad()</span>
<span id="cb7-6"></span>
<span id="cb7-7">    yh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(t)</span>
<span id="cb7-8">    loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.mean((yh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> y)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb7-9"></span>
<span id="cb7-10">    loss.backward()</span>
<span id="cb7-11">    optimizer.step()</span>
<span id="cb7-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb7-13">        yh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(t).detach()</span>
<span id="cb7-14"></span>
<span id="cb7-15">        plot_result(i, t, y, yh, loss, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)</span></code></pre></div>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_14_0.png" class="img-fluid"></p>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_14_1.png" class="img-fluid"></p>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_14_2.png" class="img-fluid"></p>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_14_3.png" class="img-fluid"></p>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_14_4.png" class="img-fluid"></p>
<p>Next, we use exactly the same architecture but add parameters <code>alpha</code>, <code>beta</code>, <code>gamma</code> and <code>delta</code> reflecting the parameters in the Lotka-Volterra equations. We initialize them randomly between 0 and 1, and add them to the list of model paramters so that they are updated in the backpropagation steps.</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">torch.manual_seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">123</span>)</span>
<span id="cb8-2">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> NN(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb8-3"></span>
<span id="cb8-4">alpha <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.rand(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, requires_grad<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb8-5">beta <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.rand(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, requires_grad<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb8-6">gamma <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.rand(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, requires_grad<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb8-7">delta <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.rand(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, requires_grad<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb8-8"></span>
<span id="cb8-9">extra_parameters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [alpha, beta, gamma, delta]</span>
<span id="cb8-10">parameters <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(model.parameters()) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> extra_parameters</span>
<span id="cb8-11">optimizer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.optim.Adam(parameters, lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-3</span>)</span></code></pre></div>
<p>We define <code>t_physics</code>; the range of timesteps on which we numerically evaluate the differential equations. In this case, we evaluate them every 0.1 year.</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1">t_physics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.arange(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(t), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>, dtype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>torch.float32).view(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).requires_grad_(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div>
<p>Training the PINN is identical to training the normal neural network, except that the loss function consists of a combination of the data loss and the physics loss. The data loss is identical to the loss of the previous neural network. For the physics loss, note that we can rewrite the Lotka-Volterra equations as <img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cmathrm%7Bd%7D%7D%7B%5Cmathrm%7Bd%7Dt%7D%20u%20-%20(%5Calpha%20u%20-%20%5Cbeta%20u%20v)%20=%200,%0A"> <img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cmathrm%7Bd%7D%7D%7B%5Cmathrm%7Bd%7Dt%7D%20v%20-%20(%5Cdelta%20uv%20-%20%5Cgamma%20v)%20=%200.%0A"> We calculate the mean of the square of the left-hand side across the values of <img src="https://latex.codecogs.com/png.latex?t"> in <code>t_physics</code>, thus punishing the model if the equations are far away from 0. We use <code>torch.autograd</code> to estimate the partial derivatives, which means that these partial derivatives are based on what the neural network has learned so far. We calculate a weighted sum of the physics and data loss, using a weight of <code>lambda1</code> set to 0.01. The value of this weight can matter quite a lot and depends on the relative sizes of the errors. Intuitively, it captures how much you trust the data versus the physical laws.</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">lambda1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-2</span></span>
<span id="cb10-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50000</span>):</span>
<span id="cb10-3">    optimizer.zero_grad()</span>
<span id="cb10-4"></span>
<span id="cb10-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Data loss</span></span>
<span id="cb10-6">    yh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(t)</span>
<span id="cb10-7">    data_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.mean((yh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> y)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb10-8"></span>
<span id="cb10-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Physics loss</span></span>
<span id="cb10-10">    yhp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(t_physics)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># output of the model at the t_physics timesteps</span></span>
<span id="cb10-11">    u, v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> yhp[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], yhp[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># hare and lynx populations according to the neural network</span></span>
<span id="cb10-12">    dudt  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.autograd.grad(u, t_physics, torch.ones_like(u), create_graph<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].flatten() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># time derivative of hare</span></span>
<span id="cb10-13">    dvdt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.autograd.grad(v,  t_physics, torch.ones_like(v),  create_graph<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].flatten() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># time derivative of lynx</span></span>
<span id="cb10-14">    dudt_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.mean((dudt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> beta<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>v))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb10-15">    dvdt_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.mean((dvdt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (delta<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>u<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> gamma<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>v))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb10-16">    physics_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dudt_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> dvdt_loss</span>
<span id="cb10-17"></span>
<span id="cb10-18">    loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lambda1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>physics_loss</span>
<span id="cb10-19">    loss.backward()</span>
<span id="cb10-20">    optimizer.step()</span>
<span id="cb10-21"></span>
<span id="cb10-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb10-23">        yh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(t).detach()</span>
<span id="cb10-24">        tp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> t_physics.detach()</span>
<span id="cb10-25"></span>
<span id="cb10-26">        a, b, c, d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(param.item(), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> param <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> extra_parameters]</span>
<span id="cb10-27">        params <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">rf"</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">$</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\a</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">lpha=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>a<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">, </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">\b</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">eta=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">, </span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">gamma=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>c<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">, </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">\d</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">elta=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">$</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb10-28">        plot_result(i, t, y, yh, loss, tp, physics_loss, params)</span></code></pre></div>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_20_0.png" class="img-fluid"></p>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_20_1.png" class="img-fluid"></p>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_20_2.png" class="img-fluid"></p>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_20_3.png" class="img-fluid"></p>
<p><img src="https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/images/lynx_20_4.png" class="img-fluid"></p>
<p>We see that the model is still able to fit well (albeit a little bit worse), and is able to estimate values for the parameters. Specifically, it estimates</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Chat%7B%5Calpha%7D%20=%200.57,%5Cquad%0A%5Chat%7B%5Cbeta%7D%20=%200.027,%5Cquad%0A%5Chat%7B%5Cgamma%7D%20=%200.94,%5Cquad%0A%5Chat%7B%5Cdelta%7D%20=%200.026,%0A"> which are very close to the results of the other two approaches mentioned above. Only the estimate for <img src="https://latex.codecogs.com/png.latex?%5Cgamma"> deviates significantly from the other estimates.</p>
<p>However, this approach is very simple to implement and requires no knowledge about the differential equations or Bayesian modelling software.</p>
<p>Thanks for reading!</p>


</section>

 ]]></description>
  <guid>https://www.basjacobs.com/post/2024-02-09-physics-informed-neural-networks-for-population-dynamics/</guid>
  <pubDate>Thu, 08 Feb 2024 23:00:00 GMT</pubDate>
</item>
<item>
  <title>Riddler: Nonconformist Dice</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2022-05-18-riddler-nonconformist-dice/</link>
  <description><![CDATA[ 





<p>Last week’s <a href="https://fivethirtyeight.com/features/its-elementary-my-dear-riddler/">Riddler Classic</a> is a question about rolling tetrahedral dice:</p>
<blockquote class="blockquote">
<p>You have four fair tetrahedral dice whose four sides are numbered 1 through 4.<br>
You play a game in which you roll them all and divide them into two groups: those whose values are unique, and those which are duplicates. For example, if you roll a 1, 2, 2 and 4, then the 1 and 4 will go into the “unique” group, while the 2s will go into the “duplicate” group.<br>
Next, you reroll all the dice in the duplicate pool and sort all the dice again. Continuing the previous example, that would mean you reroll the 2s. If the result happens to be 1 and 3, then the “unique” group will now consist of 3 and 4, while the “duplicate” group will have two 1s.<br>
You continue rerolling the duplicate pool and sorting all the dice until all the dice are members of the same group. If all four dice are in the “unique” group, you win. If all four are in the “duplicate” group, you lose. What is your probability of winning the game?</p>
</blockquote>
<p>We will answer this question using a Markov Chain in python. For that, we will use <code>numpy</code> (for matrix multiplication), <code>collections.Counter</code> (for easy counting) and <code>itertools.product</code> (for throwing dice).</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> collections <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Counter</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> itertools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> product</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span></code></pre></div>
</div>
<p>First, let’s calculate the probability of every possible throw with four tetrahedral dice. We will represent a dice throw as an ordered string.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># all possible throws</span></span>
<span id="cb2-2">throws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>.join(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(i) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> state) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> state <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> product([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>], repeat<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)]</span>
<span id="cb2-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># aggregate identical throws and calculate probabilities</span></span>
<span id="cb2-4">all_states <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>.join(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(throw)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> throw <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> throws]</span>
<span id="cb2-5">freqs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Counter(all_states).items()</span>
<span id="cb2-6">throw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {k: v<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> freqs}</span>
<span id="cb2-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>.join([<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>k<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>v<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> throw.items()][:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">..."</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>1111: 0.00390625
1112: 0.015625
1113: 0.015625
1114: 0.015625
1122: 0.0234375
1123: 0.046875
1124: 0.046875
1133: 0.0234375
1134: 0.046875
1144: 0.0234375
1222: 0.015625
1223: 0.046875
...</code></pre>
</div>
</div>
<p>In addition to these throw results, we have two states the chain can be in: <code>"loss"</code> and <code>"win"</code>.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">states <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(throw.keys()) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"loss"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"win"</span>]</span>
<span id="cb4-2">states</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>['1111', '1112', '1113', '1114', '1122', '1123', '1124', '1133', '1134', '1144', '1222', '1223', '1224', '1233', '1234', '1244', '1333', '1334', '1344', '1444', '2222', '2223', '2224', '2233', '2234', '2244', '2333', '2334', '2344', '2444', '3333', '3334', '3344', '3444', '4444', 'loss', 'win']</code></pre>
</div>
</div>
<p>Next, we calculate the probability of going from one state to another. The following function will calculate all transition probabilities starting from state <code>from_state</code>. Remember we can roll every die in the “unique” group, but cannot change the die in the “duplicate” group. The states for <code>"loss"</code> and <code>"win"</code> are absorbing states.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> transition_probs(from_state):</span>
<span id="cb6-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return all transition probabilities from state `from_state`</span></span>
<span id="cb6-3">  </span>
<span id="cb6-4">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># initially fill all probabilities with zero</span></span>
<span id="cb6-5">  probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {state: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> state <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> states}</span>
<span id="cb6-6">  </span>
<span id="cb6-7">  counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Counter(from_state)</span>
<span id="cb6-8">  uniques <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [k <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> counts.items() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb6-9">  </span>
<span id="cb6-10">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(uniques) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> from_state <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"loss"</span>:</span>
<span id="cb6-11">    probs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"loss"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb6-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> probs</span>
<span id="cb6-13">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(uniques) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> from_state <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"win"</span>:</span>
<span id="cb6-14">    probs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"win"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb6-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> probs</span>
<span id="cb6-16">  </span>
<span id="cb6-17">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># number of dice to throw again</span></span>
<span id="cb6-18">  n_dice <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(uniques) </span>
<span id="cb6-19">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># calculate possible new states</span></span>
<span id="cb6-20">  draws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>.join(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(i) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> state) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> state <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> product([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>], repeat<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_dice)]</span>
<span id="cb6-21">  new_states <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>.join(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(draw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>.join(uniques))) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> draw <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> draws]</span>
<span id="cb6-22">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># calculate new states' probabilities</span></span>
<span id="cb6-23">  freqs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Counter(new_states).items()</span>
<span id="cb6-24">  throw_probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {k: v<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>n_dice) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> freqs}</span>
<span id="cb6-25">  </span>
<span id="cb6-26">  probs.update(throw_probs)</span>
<span id="cb6-27">  </span>
<span id="cb6-28">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> probs</span></code></pre></div>
</div>
<p>For example, if we start with <code>"1112"</code>, we throw the three <code>"1"</code> dice again, but keep the die with a <code>"2"</code>. Therefore the probability mass is distributed over throws containing a <code>"2"</code>.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">transition_probs(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1112"</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>{'1111': 0, '1112': 0.015625, '1113': 0, '1114': 0, '1122': 0.046875, '1123': 0.046875, '1124': 0.046875, '1133': 0, '1134': 0, '1144': 0, '1222': 0.046875, '1223': 0.09375, '1224': 0.09375, '1233': 0.046875, '1234': 0.09375, '1244': 0.046875, '1333': 0, '1334': 0, '1344': 0, '1444': 0, '2222': 0.015625, '2223': 0.046875, '2224': 0.046875, '2233': 0.046875, '2234': 0.09375, '2244': 0.046875, '2333': 0.015625, '2334': 0.046875, '2344': 0.046875, '2444': 0.015625, '3333': 0, '3334': 0, '3344': 0, '3444': 0, '4444': 0, 'loss': 0, 'win': 0}</code></pre>
</div>
</div>
<p>Next, we can generate a Markov matrix containing these transition probabilities for every starting state.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1">markov_mat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [[v <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> transition_probs(state).items()] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> state <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> states]</span>
<span id="cb9-2">markov_mat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.asarray(markov_mat) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># turn into numpy array for matrix multiplication</span></span>
<span id="cb9-3">markov_mat.shape</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>(37, 37)</code></pre>
</div>
</div>
<p>Together with an initial throw, we can then simulate a round of the game by multiplying the vector corresponding to the initial throw with the Markov matrix..</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">first_throw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([v <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> throw.items()] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb11-2"></span>
<span id="cb11-3">res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> first_throw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> markov_mat</span>
<span id="cb11-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(states, res))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>{'1111': 0.000732421875, '1112': 0.0087890625, '1113': 0.0087890625, '1114': 0.0087890625, '1122': 0.01611328125, '1123': 0.0380859375, '1124': 0.0380859375, '1133': 0.01611328125, '1134': 0.0380859375, '1144': 0.01611328125, '1222': 0.0087890625, '1223': 0.0380859375, '1224': 0.0380859375, '1233': 0.0380859375, '1234': 0.087890625, '1244': 0.0380859375, '1333': 0.0087890625, '1334': 0.0380859375, '1344': 0.0380859375, '1444': 0.0087890625, '2222': 0.000732421875, '2223': 0.0087890625, '2224': 0.0087890625, '2233': 0.01611328125, '2234': 0.0380859375, '2244': 0.01611328125, '2333': 0.0087890625, '2334': 0.0380859375, '2344': 0.0380859375, '2444': 0.0087890625, '3333': 0.000732421875, '3334': 0.0087890625, '3344': 0.01611328125, '3444': 0.0087890625, '4444': 0.000732421875, 'loss': 0.15625, 'win': 0.09375}</code></pre>
</div>
</div>
<p>We can just as easily simulate multiple rounds of the game by taking the matrix to a certain power.<br>
After 20 rounds, it becomes apparent that the probability of winning seems to be 45%.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> first_throw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> np.linalg.matrix_power(markov_mat, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb13-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(states, res))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>{'1111': 2.2522812066292564e-06, '1112': 3.60364993060681e-05, '1113': 3.60364993060681e-05, '1114': 3.60364993060681e-05, '1122': 6.756843619887768e-05, '1123': 0.00016216424687730643, '1124': 0.00016216424687730645, '1133': 6.756843619887768e-05, '1134': 0.00016216424687730648, '1144': 6.756843619887768e-05, '1222': 3.603649930606811e-05, '1223': 0.00016216424687730648, '1224': 0.00016216424687730648, '1233': 0.00016216424687730648, '1234': 0.0003783832427137152, '1244': 0.00016216424687730645, '1333': 3.603649930606811e-05, '1334': 0.00016216424687730648, '1344': 0.0001621642468773065, '1444': 3.603649930606811e-05, '2222': 2.2522812066292564e-06, '2223': 3.60364993060681e-05, '2224': 3.60364993060681e-05, '2233': 6.756843619887769e-05, '2234': 0.0001621642468773065, '2244': 6.756843619887769e-05, '2333': 3.6036499306068095e-05, '2334': 0.00016216424687730648, '2344': 0.00016216424687730648, '2444': 3.6036499306068095e-05, '3333': 2.2522812066292564e-06, '3334': 3.60364993060681e-05, '3344': 6.756843619887768e-05, '3444': 3.60364993060681e-05, '4444': 2.2522812066292564e-06, 'loss': 0.5483423210319212, 'win': 0.4484864670291449}</code></pre>
</div>
</div>
<p>Simulating the game for 1000 rounds confirms this.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1">res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> first_throw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> np.linalg.matrix_power(markov_mat, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>)</span>
<span id="cb15-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(states, res))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>{'1111': 8.17825667702296e-129, '1112': 1.3085210683236735e-127, '1113': 1.3085210683236735e-127, '1114': 1.3085210683236735e-127, '1122': 2.4534770031068862e-127, '1123': 5.888344807456528e-127, '1124': 5.888344807456528e-127, '1133': 2.4534770031068862e-127, '1134': 5.888344807456528e-127, '1144': 2.4534770031068862e-127, '1222': 1.3085210683236735e-127, '1223': 5.888344807456528e-127, '1224': 5.888344807456528e-127, '1233': 5.888344807456528e-127, '1234': 1.3739471217398578e-126, '1244': 5.888344807456528e-127, '1333': 1.3085210683236735e-127, '1334': 5.888344807456528e-127, '1344': 5.888344807456528e-127, '1444': 1.3085210683236735e-127, '2222': 8.17825667702296e-129, '2223': 1.3085210683236735e-127, '2224': 1.3085210683236735e-127, '2233': 2.4534770031068862e-127, '2234': 5.888344807456528e-127, '2244': 2.4534770031068862e-127, '2333': 1.3085210683236735e-127, '2334': 5.888344807456528e-127, '2344': 5.888344807456528e-127, '2444': 1.3085210683236735e-127, '3333': 8.17825667702296e-129, '3334': 1.3085210683236735e-127, '3344': 2.4534770031068862e-127, '3444': 1.3085210683236735e-127, '4444': 8.17825667702296e-129, 'loss': 0.55, 'win': 0.44999999999999984}</code></pre>
</div>
</div>
<p>What’s interesting is that you have a higher probability of winning (48.3%) if you start with a pair.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(states, np.linalg.matrix_power(markov_mat, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>)[:,<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>{'1111': 0.0, '1112': 0.44999999999999996, '1113': 0.44999999999999996, '1114': 0.44999999999999996, '1122': 0.0, '1123': 0.48333333333333334, '1124': 0.48333333333333334, '1133': 0.0, '1134': 0.48333333333333334, '1144': 0.0, '1222': 0.44999999999999996, '1223': 0.48333333333333334, '1224': 0.48333333333333334, '1233': 0.48333333333333334, '1234': 1.0, '1244': 0.48333333333333334, '1333': 0.44999999999999996, '1334': 0.48333333333333334, '1344': 0.48333333333333334, '1444': 0.44999999999999996, '2222': 0.0, '2223': 0.44999999999999996, '2224': 0.44999999999999996, '2233': 0.0, '2234': 0.48333333333333334, '2244': 0.0, '2333': 0.44999999999999996, '2334': 0.48333333333333334, '2344': 0.48333333333333334, '2444': 0.44999999999999996, '3333': 0.0, '3334': 0.44999999999999996, '3344': 0.0, '3444': 0.44999999999999996, '4444': 0.0, 'loss': 0.0, 'win': 1.0}</code></pre>
</div>
</div>
<p>And that is how easy and elegant it can be to answer such a question using a Markov chain. Until next time!</p>



 ]]></description>
  <guid>https://www.basjacobs.com/post/2022-05-18-riddler-nonconformist-dice/</guid>
  <pubDate>Tue, 17 May 2022 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Riddler: Another Hunt For Mysterious Numbers</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2021-02-06-riddler-another-hunt-for-mysterious-numbers/</link>
  <description><![CDATA[ 





<p>This week’s <a href="https://fivethirtyeight.com/features/can-you-randomly-move-the-tower/">FiveThirtyEight Riddler Express</a> is similar to the Riddler Classic of two weeks ago:</p>
<blockquote class="blockquote">
<p>By all accounts, Riddler Nation had a lot of fun <a href="https://fivethirtyeight.com/features/can-you-hunt-for-the-mysterious-numbers/">hunting for the mysterious numbers</a> a few weeks back. So here’s what we’re going to do: For the next four weeks, the Riddler Express will feature a similar puzzle that combines multiplication and logic. We’ll be calling these CrossProducts. For your first weekly CrossProduct, there are five three-digit numbers — each belongs in a row of the table below, with one digit per cell. The products of the three digits of each number are shown in the rightmost column. Meanwhile, the products of the digits in the hundreds, tens and ones places, respectively, are shown in the bottom row.</p>
</blockquote>
<p><img src="https://www.basjacobs.com/post/2021-02-06-riddler-another-hunt-for-mysterious-numbers/images/puzzle.png" class="img-fluid" width="500"></p>
<p>Two weeks ago, rather than searching for the solution manually, I <a href="../../post/2021-01-22-riddler-can-you-hunt-for-the-mysterious-numbers">solved this problem with linear programming</a> in Julia. The advantage of that approach is that it is easy to apply to this new problem again — it should be a matter of changing the input numbers. Let’s see how it goes! Please refer to the aforementioned post for a more thorough explanation of the code.</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">JuMP</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">GLPK</span></span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Primes</span>: factor, primes</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">DataStructures</span>: DefaultDict</span>
<span id="cb1-4"></span>
<span id="cb1-5">row_prods <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">135</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">280</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">70</span>];</span>
<span id="cb1-6">col_prods <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3_000</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3_969</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">640</span>];</span>
<span id="cb1-7">prms <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">primes</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>);</span>
<span id="cb1-8"></span>
<span id="cb1-9">n_prms <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(prms);</span>
<span id="cb1-10">n_rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(row_prods);</span>
<span id="cb1-11">n_cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(col_prods);</span></code></pre></div>
<p>Note that the only thing changed with respect to the previous post is that we initialized the problem with new <code>row_prods</code> and <code>col_prods</code>. The rest should be automatic.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb2-1">row_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>.(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Dict</span>, row_prods);</span>
<span id="cb2-2">col_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>.(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Dict</span>, col_prods);</span>
<span id="cb2-3"></span>
<span id="cb2-4">row_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DefaultDict</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, row_factors[row])[prms[i]] for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>] for row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows]</span>
<span id="cb2-5">col_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DefaultDict</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, col_factors[col])[prms[i]] for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>] for col <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols]</span></code></pre></div>
<pre><code>5-element Array{Array{Int64,1},1}:
 [0, 3, 1, 0]
 [0, 2, 1, 0]
 [6, 0, 0, 0]
 [3, 0, 1, 1]
 [1, 0, 1, 1]
3-element Array{Array{Int64,1},1}:
 [3, 1, 3, 0]
 [0, 4, 0, 2]
 [7, 0, 1, 0]</code></pre>
<p>Again, onto the actual problem definition.</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb4-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Model</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">with_optimizer</span>(GLPK.Optimizer))</span>
<span id="cb4-2"></span>
<span id="cb4-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@variable</span>(model, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> x[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_prms], integer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span>)</span></code></pre></div>
<p>Make sure row and column prime multiplicities add up to the correct numbers.</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows, p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_prms</span>
<span id="cb5-2">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, p]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> row_factors[i][p])</span>
<span id="cb5-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-4"></span>
<span id="cb5-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols, p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_prms</span>
<span id="cb5-6">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, j, p]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> col_factors[j][p])</span>
<span id="cb5-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Finally, we want every cell to be an integer between 1 and 9, which means <img src="https://latex.codecogs.com/png.latex?2%5E%7Bp_2%7D%5Ccdot%203%5E%7Bp_3%7D%5Ccdot%205%5E%7Bp_5%7D%5Ccdot%207%5E%7Bp_7%7D%20%5Cle%209">, or <img src="https://latex.codecogs.com/png.latex?p_2%5Clog(2)%20+%20p_3%5Clog(3)%20+%20p_5%5Clog(5)+p_7%5Clog(7)%20%5Cle%20%5Clog(9)">, a constraint which is linear in its variables.</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows, j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols</span>
<span id="cb6-2">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[i, j, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>.(prms)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>))</span>
<span id="cb6-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>And that is all! Let JuMP do its magic and come up with a feasible solution. As an example, again we print out the number of times a 2 (the first prime) appears in every cell.</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb7-1">JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optimize!</span>(model)</span>
<span id="cb7-2"></span>
<span id="cb7-3">solution <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span>.(x);</span>
<span id="cb7-4"></span>
<span id="cb7-5">solution[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span></code></pre></div>
<pre><code>5×3 Array{Float64,2}:
 0.0  0.0  0.0
 0.0  0.0  0.0
 3.0  0.0  3.0
 0.0  0.0  3.0
 0.0  0.0  1.0</code></pre>
<p>The final solution to the riddle is then the product of every prime to the power of its multiplicity:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb9-1">[[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Int</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">prod</span>(prms <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.^</span> solution[i, j, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>])) for j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols] for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows]</span></code></pre></div>
<pre><code>5-element Array{Array{Int64,1},1}:
 [3, 9, 5]
 [5, 9, 1]
 [8, 1, 8]
 [5, 7, 8]
 [5, 7, 2]</code></pre>
<p>Well, that was easy! For the first puzzle, the challenge was to come up with a model. From then on, it is just a matter of changing the inputs. It does feel a bit like cheating, though … I don’t think I’ll continue with these <em>CrossProduct</em> puzzles in this way.</p>



 ]]></description>
  <guid>https://www.basjacobs.com/post/2021-02-06-riddler-another-hunt-for-mysterious-numbers/</guid>
  <pubDate>Fri, 05 Feb 2021 23:00:00 GMT</pubDate>
</item>
<item>
  <title>Riddler: Can You Hunt For The Mysterious Numbers?</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2021-01-22-riddler-can-you-hunt-for-the-mysterious-numbers/</link>
  <description><![CDATA[ 





<p>This week’s <a href="https://fivethirtyeight.com/features/can-you-hunt-for-the-mysterious-numbers/">FiveThirtyEight Riddler Classic</a> offers a sudoku-like puzzle:</p>
<blockquote class="blockquote">
<p>There are eight three-digit numbers — each belongs in a row of the table below, with one digit per cell. The products of the three digits of each number are shown in the rightmost column. Meanwhile, the products of the digits in the hundreds, tens, and ones places, respectively, are shown in the bottom row. Can you find all eight three-digit numbers and complete the table? It’s a bit of a mystery, but I’m sure you have it within you to hunt down the answer!</p>
</blockquote>
<p><img src="https://fivethirtyeight.com/wp-content/uploads/2021/01/RIDDLER.011521.png?w=1400" class="img-fluid" width="500"></p>
<section id="linear-programming" class="level2">
<h2 class="anchored" data-anchor-id="linear-programming">Linear programming</h2>
<p>A nice way to solve problems like this is by Integer Linear Programming. Like in my <a href="../../post/2019-04-21-trees-and-tents/">Trees and Tents post</a>, I like to do this in Julia using the JuMP package.</p>
<p>The constraints we have are on the products of the numbers in the rows and the columns. Therefore the problem is not linear if we implement it naively (a variable for every cell denoting the number between 1 and 9 it should contain). We need to do something a little bit more clever. A natural way to look at this problem is via the prime factorizations of the row and the column products. There are four primes between 1 and 9, namely 2, 3, 5 and 7. Given the prime factorization of every row and column, we only need to distribute these primes over the cells. Since <img src="https://latex.codecogs.com/png.latex?294%20=%202%5E1%5Ccdot%203%5E1%5Ccdot%205%5E0%20%5Ccdot%207%5E2">, we know that in the first row there should be a 2, a 3, no 5 and two 7s. Note that a cell can contain multiple primes, or none at all (meaning it is a 1).</p>
<p>We therefore need a variable for every cell and each of the 4 possible primes, the value of which denotes the multiplicity of this prime in this cell.</p>
<p>In Julia, we first import the required packages, and define the row and column products.</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">JuMP</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">GLPK</span></span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Primes</span>: factor, primes</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">DataStructures</span>: DefaultDict</span>
<span id="cb1-4"></span>
<span id="cb1-5">row_prods <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">294</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">216</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">135</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">98</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">112</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">84</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">245</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>];</span>
<span id="cb1-6">col_prods <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">8_890_560</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">156_800</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">55_566</span>];</span>
<span id="cb1-7">prms <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">primes</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>);</span>
<span id="cb1-8"></span>
<span id="cb1-9">n_prms <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(prms);</span>
<span id="cb1-10">n_rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(row_prods);</span>
<span id="cb1-11">n_cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(col_prods);</span></code></pre></div>
<p>Now, we create lists of the multiplicities of the four primes in the rows and the columns. The <code>[1, 1, 0, 2]</code> denotes the multiplicities of 2, 3, 5 and 7 in the first row.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb2-1">row_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>.(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Dict</span>, row_prods);</span>
<span id="cb2-2">col_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">factor</span>.(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Dict</span>, col_prods);</span>
<span id="cb2-3"></span>
<span id="cb2-4">row_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DefaultDict</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, row_factors[row])[prms[i]] for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>] for row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows]</span>
<span id="cb2-5">col_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">DefaultDict</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, col_factors[col])[prms[i]] for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>] for col <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols]</span></code></pre></div>
<pre><code>8-element Array{Array{Int64,1},1}:
 [1, 1, 0, 2]
 [3, 3, 0, 0]
 [0, 3, 1, 0]
 [1, 0, 0, 2]
 [4, 0, 0, 1]
 [2, 1, 0, 1]
 [0, 0, 1, 2]
 [3, 0, 1, 0]
3-element Array{Array{Int64,1},1}:
 [6, 4, 1, 3]
 [7, 0, 2, 2]
 [1, 4, 0, 3]</code></pre>
<p>Now onto the actual problem definition. As stated, we need a variable for every cell and every prime. Every prime can occur 0 or more times, and its multiplicity is an integer.</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb4-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Model</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">with_optimizer</span>(GLPK.Optimizer))</span>
<span id="cb4-2"></span>
<span id="cb4-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@variable</span>(model, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> x[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_prms], integer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span>)</span></code></pre></div>
<p>Rows and column prime multiplicities should add up to the correct numbers.</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows, p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_prms</span>
<span id="cb5-2">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, p]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> row_factors[i][p])</span>
<span id="cb5-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-4"></span>
<span id="cb5-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols, p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_prms</span>
<span id="cb5-6">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, j, p]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> col_factors[j][p])</span>
<span id="cb5-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Finally, we want every cell to be an integer between 1 and 9, which means <img src="https://latex.codecogs.com/png.latex?2%5E%7Bp_2%7D%5Ccdot%203%5E%7Bp_3%7D%5Ccdot%205%5E%7Bp_5%7D%5Ccdot%207%5E%7Bp_7%7D%20%5Cle%209">, or <img src="https://latex.codecogs.com/png.latex?p_2%5Clog(2)%20+%20p_3%5Clog(3)%20+%20p_5%5Clog(5)+p_7%5Clog(7)%20%5Cle%20%5Clog(9)">, a constraint which is linear in its variables.</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows, j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols</span>
<span id="cb6-2">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[i, j, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>.(prms)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>))</span>
<span id="cb6-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>And that is all! We let JuMP do the hard work and come up with a feasible solution. As an example, we print out the number of times a 2 (the first prime) appears in every cell.</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb7-1">JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optimize!</span>(model)</span>
<span id="cb7-2"></span>
<span id="cb7-3">solution <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span>.(x);</span>
<span id="cb7-4"></span>
<span id="cb7-5">solution[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span></code></pre></div>
<pre><code>8×3 Array{Float64,2}:
 0.0  0.0  1.0
 0.0  3.0  0.0
 0.0  0.0  0.0
 0.0  1.0  0.0
 3.0  1.0  0.0
 0.0  2.0  0.0
 0.0  0.0  0.0
 3.0  0.0  0.0</code></pre>
<p>The final solution to the riddle is then the product of every prime to the power of its multiplicity:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb9-1">[[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Int</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">prod</span>(prms <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.^</span> solution[i, j, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>])) for j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_cols] for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_rows]</span></code></pre></div>
<pre><code>8-element Array{Array{Int64,1},1}:
 [7, 7, 6]
 [9, 8, 3]
 [9, 5, 3]
 [7, 2, 7]
 [8, 2, 7]
 [7, 4, 3]
 [5, 7, 7]
 [8, 5, 1]</code></pre>
<p>And there’s the solution! I love how easy it is to have JuMP solve such a problem after coming up with a way to phrase it as a linear program.</p>


</section>

 ]]></description>
  <guid>https://www.basjacobs.com/post/2021-01-22-riddler-can-you-hunt-for-the-mysterious-numbers/</guid>
  <pubDate>Thu, 21 Jan 2021 23:00:00 GMT</pubDate>
</item>
<item>
  <title>EleksDraw pen plotter with R</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/</link>
  <description><![CDATA[ 





<p>The <a href="https://wiki.eleksmaker.com/doku.php?id=eleksdraw">EleksDraw pen plotter</a> is a relatively cheap pen plotter that works like the better-known AxiDraw plotter. Unlike the AxiDraw, it comes as a kit that needs to be assembled, and the only software available is a Windows program. Since I’m using macOS and I wanted more freedom, I decided to fiddle around with it in Python, which resulted in a <a href="../../post/2018-06-28-pen-plotter/">blog post</a> and <a href="https://github.com/basjacobs93/plotter">accompanying code</a>. In this post, I describe how I got to get it working with <code>ggplot2</code> in R.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/eleksdraw.jpg" class="img-fluid figure-img"></p>
<figcaption>The EleksDraw pen plotter</figcaption>
</figure>
</div>
<section id="python" class="level2">
<h2 class="anchored" data-anchor-id="python">Python</h2>
<p>My initial python code was very hacky and unstable, so I decided to take a more structured approach, now that I knew I would be able to get it working. I found a nicely structured <a href="https://github.com/fogleman/xy">project by Michael Fogleman</a> that does the same for the Makeblock XY Plotter. It defines an object that holds the connection to the plotter, and defines methods that send commands to it, like <code>move()</code>, <code>pen_up()</code> and <code>pen_down()</code>. It can render a drawing and store it as an image before sending it to the plotter, which makes it easy to assess an image virtually before physically drawing it. I forked the project, edited the device instructions and restructured it a bit, which resulted in <a href="https://github.com/basjacobs93/EleksDrawPy">EleksDrawPy</a>.</p>
<p>This new code is a lot easier to use and more stable than my previous attempt. It also allows for usage from R via the <a href="https://rstudio.github.io/reticulate/"><code>reticulate</code> R interface to Python</a>.</p>
</section>
<section id="r" class="level2">
<h2 class="anchored" data-anchor-id="r">R</h2>
<p>My pen plotter was collecting dust when I stumbled upon <a href="https://fawkes.data-imaginist.com">fawkes</a>, “an R interface to the AxiDraw plotter” by Thomas Lin Pedersen, who is part of RStudio’s <code>tidyverse</code> team. It uses <code>reticulate</code> to be able to use the AxiDraw python interface from R, and defines a <code>device</code> which one can write <code>ggplot2</code> plots to, similar to R’s built-in <code>png()</code> or <code>pdf()</code> device. How cool would it be to be able to plot ggplot2 graphs on my plotter?</p>
<p>It turned out to be very straightforward to port his code to use my python code. The resulting code can be found <a href="https://github.com/basjacobs93/fawkes">on GitHub</a>. I kept the original code intact, but added the <code>eleks_dev()</code> and the <code>eleks_manual()</code> functions, which are the counterparts of the <code>axi_dev()</code> and <code>axi_manual()</code> functions already present. The former can be used as a device like <code>png()</code>, the latter for interactive mode (i.e.&nbsp;sending individual commands to the device). I did not create a version of the <code>axi_svg()</code> function (that uses the AxiDraw svg plotting capabilities), since my EleksDraw python code does not have this functionality (yet).</p>
<p>The <code>fawkes::ghost_dev()</code> device that is also present in the package, makes it easy to get a feeling of what the resulting plot will look like. It shows not only the lines that will be drawn, but also the paths the device takes while the pen is in the air.</p>
<p>Now, we can plot ggplot2 graphs from R right onto a piece of paper! Below are some examples. All credits go to Thomas Lin Pedersen and Michael Fogleman, whose code I merely adjusted for my specific goal.</p>
</section>
<section id="results" class="level2">
<h2 class="anchored" data-anchor-id="results">Results</h2>
<p>The python module can be installed with <code>pip install -r requirements.txt</code> (after cloning the project), and the R package with <code>remotes::install_github('basjacobs93/fawkes')</code>. The packages we’ll use besides the aforementioned <code>fawkes</code> and <code>ggplot2</code> are <code>dplyr</code> (for data manipulation) and <code>sf</code> (for using spatial data).</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(dplyr)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(fawkes)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(sf)</span></code></pre></div>
</div>
<p>Given a <code>ggplot2</code> plot <code>p</code>, the plot can be previewed with the following,</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">gd <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ghost_dev</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A6'</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">portrait =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">margins =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ignore_color =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb2-2">p</span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">invisible</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dev.off</span>())</span>
<span id="cb2-4">gd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">preview</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot_air =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div>
</div>
<p>and plotted with the EleksDraw using the below.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">gd <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eleks_dev</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'A6'</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">portrait =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">margins =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ignore_color =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb3-2">p</span>
<span id="cb3-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">invisible</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dev.off</span>())</span></code></pre></div>
</div>
<p>For each of the below examples, we show the <code>ggplot2</code> graph as a png, the output of the <code>fawkes::ghost_dev()</code> preview, and finally a picture of the plot on paper.</p>
<section id="facets-with-mtcars" class="level3">
<h3 class="anchored" data-anchor-id="facets-with-mtcars">Facets with mtcars</h3>
<p>The first plot is copied straight from the <a href="https://fawkes.data-imaginist.com/#examples"><code>fawkes</code> examples</a>. It plots the famous <code>mtcars</code> dataset using facets and demonstrates the capabilities of the <code>fawkes</code> library.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(mtcars) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(disp, mpg)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">facet_wrap</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span> gear) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_bw</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span>(</span>
<span id="cb4-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>(),</span>
<span id="cb4-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">panel.background =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">element_blank</span>()</span>
<span id="cb4-8">  )</span></code></pre></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/facets_png.png" class="img-fluid figure-img" width="400"></p>
<figcaption>mtcars, png</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/facets_air.png" class="img-fluid figure-img" width="400"></p>
<figcaption>mtcars, preview</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/facets_plot.png" class="img-fluid figure-img" width="400"></p>
<figcaption>mtcars, pen on paper</figcaption>
</figure>
</div>
</section>
<section id="harmonograph" class="level3">
<h3 class="anchored" data-anchor-id="harmonograph">Harmonograph</h3>
<p>The below code generates a random <a href="https://en.wikipedia.org/wiki/Harmonograph">harmonograph</a>, one instance of which I plotted.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">f1<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">jitter</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>));f2<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">jitter</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>));f3<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">jitter</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>));f4<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">jitter</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span>
<span id="cb5-2">d1<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-02</span>);d2<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-02</span>);d3<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-02</span>);d4<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-02</span>)</span>
<span id="cb5-3">p1<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,pi);p2<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,pi);p3<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,pi);p4<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,pi)</span>
<span id="cb5-4">harmonograph <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">t =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>pi, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>pi<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb5-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transmute</span>(</span>
<span id="cb5-6">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>d1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>t)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(t<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>f1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>p1) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>d2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>t)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(t<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>f2<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>p2),</span>
<span id="cb5-7">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>d3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>t)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(t<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>f3<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>p3) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">exp</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>d4<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>t)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(t<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>f4<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>p4)</span>
<span id="cb5-8">  )</span>
<span id="cb5-9"></span>
<span id="cb5-10">p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> harmonograph <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb5-11">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(x, y)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_path</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_bw</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">base_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb5-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>()</span></code></pre></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/harmonograph_png.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Harmonograph, png</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/harmonograph_air.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Harmonograph, preview</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/harmonograph_plot.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Harmonograph, pen on paper</figcaption>
</figure>
</div>
</section>
<section id="georg-nees---schotter" class="level3">
<h3 class="anchored" data-anchor-id="georg-nees---schotter">Georg Nees - Schotter</h3>
<p>The below generates falling squares like <a href="https://collections.vam.ac.uk/item/O221321/schotter-print-nees-georg/">Schotter</a>, by generative art pioneer Georg Nees. It can be seen that there was some slippage at the belt which resulted in incomplete squares. After this plot I tightened the belt, which made the subsequent plots a lot more accurate.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1">n_cols <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span></span>
<span id="cb6-2">n_rows <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">22</span></span>
<span id="cb6-3"></span>
<span id="cb6-4">p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">expand_grid</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">col =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(n_cols<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>),</span>
<span id="cb6-5">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(n_rows<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>),</span>
<span id="cb6-6">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>,  <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>),</span>
<span id="cb6-7">                   <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>( <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group_by</span>(col, row) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">angle =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd =</span> row<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</span>),</span>
<span id="cb6-10">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xn =</span> x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(angle) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> y<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(angle),</span>
<span id="cb6-11">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sin</span>(angle) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> y<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cos</span>(angle),</span>
<span id="cb6-12">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> xn) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>xn) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-14">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> col,</span>
<span id="cb6-15">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> row,</span>
<span id="cb6-16">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>row<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># jitter</span></span>
<span id="cb6-17">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> y <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>row<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">60</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-18">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xend =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lag</span>(x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">default =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">last</span>(x)),</span>
<span id="cb6-19">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yend =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lag</span>(y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">default =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">last</span>(y))) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-20">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ungroup</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb6-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xend =</span> xend, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yend =</span> yend)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_segment</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-23">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">coord_fixed</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb6-24">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>()</span></code></pre></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/schotter_png.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Schotter, png</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/schotter_air.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Schotter, preview</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/schotter_plot.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Schotter, pen on paper</figcaption>
</figure>
</div>
</section>
</section>
<section id="provinces-of-the-netherlands" class="level1">
<h1>Provinces of The Netherlands</h1>
<p>We can use the excellent <a href="https://r-spatial.github.io/sf/"><code>sf</code> package</a> to load and plot spatial data with <code>ggplot2</code>, like a map of the province boundaries of the Netherlands. Below, we load <a href="https://www.pdok.nl/introductie/-/article/cbs-provincies">provinces data from CBS</a> with <code>sf::st_read()</code>, simplify it to decrease the complexity of the plot, and plot it with <code>ggplot2::geom_sf()</code>.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">provinces <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_read</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://geodata.nationaalgeoregister.nl/bestuurlijkegrenzen/wfs?request=GetFeature&amp;service=WFS&amp;version=1.1.0&amp;typeName=bestuurlijkegrenzen:provincies"</span>)</span>
<span id="cb7-2"></span>
<span id="cb7-3">p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> provinces <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> </span>
<span id="cb7-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_transform</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">54032</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Azimuthal equidistant</span></span>
<span id="cb7-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_simplify</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dTolerance =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">400</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># simplify</span></span>
<span id="cb7-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">st_transform</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4326</span>)  <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># WGS84</span></span>
<span id="cb7-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_sf</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NA</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb7-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>()</span></code></pre></div>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/nl_png.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Provinces of The Netherlands, png</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/nl_air.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Provinces of The Netherlands, preview</figcaption>
</figure>
</div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/nl_plot.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Provinces of The Netherlands, pen on paper</figcaption>
</figure>
</div>


</section>

 ]]></description>
  <guid>https://www.basjacobs.com/post/2021-01-04-eleksdraw-pen-plotter-with-r/</guid>
  <pubDate>Sun, 03 Jan 2021 23:00:00 GMT</pubDate>
</item>
<item>
  <title>Image Triangulation with Julia</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/</link>
  <description><![CDATA[ 





<p>I have always been fascinated by computer generated art. Recently, I came across the paper <a href="https://cgl.ethz.ch/Downloads/Publications/Papers/2018/Law18a/Law18a.pdf">Stylized Image Triangulation</a> by Kai Lawonn and Tobias Günther. In this paper, the authors perform image triangulation (approximating an image by tessellation with triangles) by coming up with an initial grid and performing gradient descent. They achieve beautiful triangulations that capture the original images very well. Their code is a combination of MatLab and C++, and is <a href="https://github.com/tobguent/image-triangulation">available on github</a>.</p>
<p>As a fun exercise in Julia, I implemented part of their method in a Pluto notebook (like a Jupyter notebook but especially for Julia, see <a href="https://github.com/fonsp/Pluto.jl">here</a>). My notebook is <a href="https://github.com/basjacobs93/image_triangulation">available on Github</a>.</p>
<section id="summary-of-method" class="level2">
<h2 class="anchored" data-anchor-id="summary-of-method">Summary of method</h2>
<p>In the paper, the authors start with an initial grid of points that defines a triangulation. This grid can either be a <em>regular layout</em>, in which the points are spaced evenly across the width and height of an image, or it can be made via <em>importance sampling</em>, in which ‘important’ regions of the image are found and points are sampled, weighted by this importance. Every triangle gets a constant color, calculated as the mean of the colors of its interior points in the original image.</p>
<p>As an example, consider this image of a beautiful bird called a <em>Bearded reedling (Panurus biarmicus)</em>, taken from <a href="https://www.youtube.com/watch?v=i8YPjJSuse0">this YouTube video</a>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/baardman_2.png" class="img-fluid figure-img"></p>
<figcaption>Bearded Reedling</figcaption>
</figure>
</div>
<p>The two types of initial triangulation are the regular layout (in this case with 50 triangles),</p>
<p><img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/baardman_2_regular_layout.png" class="img-fluid" alt="Bearded Reedling (Regular Layout)"> and the triangulation based on importance sampling (in this case by sampling 50 points). <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/baardman_2_importance_sampling.png" class="img-fluid" alt="Bearded Reedling (Importance Sampling)"></p>
<p>Starting with such a triangulation, the triangles are improved iteratively by gradient descent. For every point, a small change in the horizontal and vertical direction is tried, and a gradient is calculated by calculating the errors of the point’s adjacent triangles for each such configuration. The error of a triangle is defined as the mean of the differences of its interior points’ colors, compared to the original image. This way, the initial triangulation gets better every step, but it may converge to a local optimum, depending on the initial triangulation.</p>
<p>On top of gradient descent, every couple of steps, every triangle can be split into three by placing an additional point at its centroid. This way, large triangles that have a big error can be split up into smaller triangles with different colors and smaller errors. The triangles eligible for this splitting have to be large enough, should not be too narrow, and should have a large error. These thresholds, together with the number of steps, step size, and other parameters can be tweaked in the code, yielding different results.</p>
<p>An example output is the below, in which the initial grid was a regular layout, and which resulted in an image of 700 triangles. <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/baardman_2_700.png" class="img-fluid" alt="Bearded reedling after optimization (700 triangles)"></p>
<p>For a more mathematically thorough explanation, I refer to the original paper.</p>
</section>
<section id="more-results" class="level2">
<h2 class="anchored" data-anchor-id="more-results">More results</h2>
<p>Another beautiful picture of the same species of bird is the following (<a href="https://commons.wikimedia.org/wiki/File:Bartmeise(Cropped)_by_Wolfram_Riech.jpg">source</a> by <em>Kaeptn chemnitz, <a href="https://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>, via Wikimedia Commons</em>).</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/baardman.png" class="img-fluid figure-img"></p>
<figcaption>Bearded reedling (source: wikimedia)</figcaption>
</figure>
</div>
<p>The resulting triangulations are more abstract than the above, but I think they are beautiful. The results with 100, 500, 1000 and 2000 triangles are below.</p>
<p><img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/baardman_100.png" class="img-fluid" alt="Bearded reedling (100 triangles)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/baardman_500.png" class="img-fluid" alt="Bearded reedling (500 triangles)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/baardman_imp_1000.png" class="img-fluid" alt="Bearded reedling (1000 triangles)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/baardman_2000.png" class="img-fluid" alt="Bearded reedling (2000 triangles)"></p>
<p>Two more examples of triangulations with 2000 triangles are below. They represent a bluethroat and a red-backed shrike.</p>
<p><img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/blauwborst_2000.png" class="img-fluid" alt="Bluethroat (2000 triangles)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/klauwier_2000.png" class="img-fluid" alt="Red-backed shrike (2000 triangles)"></p>
</section>
<section id="more-results-june-2022" class="level2">
<h2 class="anchored" data-anchor-id="more-results-june-2022">More results (June 2022)</h2>
<p>I have updated the code to make the drawing faster and to include more techniques from the paper (edge flips and node collapse).<br>
Below is the new code demonstrated on the Lee Morgan album cover <em>Lee-way</em> after 50, 100, 120 and 250 steps.</p>
<p><img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/leeway.jpg" class="img-fluid" alt="Lee-way Blue Note album cover"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/leeway_58.png" class="img-fluid" alt="Lee-way Blue Note album cover (50 steps)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/leeway_96.png" class="img-fluid" alt="Lee-way Blue Note album cover (100 steps)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/leeway_119.png" class="img-fluid" alt="Lee-way Blue Note album cover (120 steps)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/leeway_249.png" class="img-fluid" alt="Lee-way Blue Note album cover (250 steps)"></p>
<p>And the same on Cannonball Adderley’s album <em>Somethin’ Else</em>. <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/somethinelse.jpg" class="img-fluid" alt="Somethin’ Else Blue Note album cover"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/somethinelse_20.png" class="img-fluid" alt="Somethin’ Else Blue Note album cover (20 steps)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/somethinelse_40.png" class="img-fluid" alt="Somethin’ Else Blue Note album cover (40 steps)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/somethinelse_60.png" class="img-fluid" alt="Somethin’ Else Blue Note album cover (60 steps)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/somethinelse_80.png" class="img-fluid" alt="Somethin’ Else Blue Note album cover (80 steps)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/somethinelse_100.png" class="img-fluid" alt="Somethin’ Else Blue Note album cover (100 steps)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/somethinelse_120.png" class="img-fluid" alt="Somethin’ Else Blue Note album cover (120 steps)"> <img src="https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/somethinelse_140.png" class="img-fluid" alt="Somethin’ Else Blue Note album cover (140 steps)"></p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Implementing part of the methodology of the paper in Julia was fairly straightforward, even though my experience with the language is limited. However, the performance is not as good as I hoped it would be. Generating the above images took a couple of minutes upto half an hour each. This makes it hard to fiddle around with the parameters, since a lot of time is spent waiting for the results. The authors of the paper wrote parts of their code in C++ because of performance, and parallelized and optimized the code such that it was faster. Although Julia code can be fast, my naive implementation still requires lots of loops (over the triangles, points, pixels), so it makes sense for it to be slow. That said, even though my implementation is naive, a pretty triangulation is only a key-press away and can be generated in a couple of minutes.</p>
<p>As stated, the notebook is available <a href="https://github.com/basjacobs93/image_triangulation">on GitHub</a>, so feel free to try it out!</p>


</section>

 ]]></description>
  <guid>https://www.basjacobs.com/post/2020-11-18-image-triangulation-with-julia/</guid>
  <pubDate>Tue, 17 Nov 2020 23:00:00 GMT</pubDate>
</item>
<item>
  <title>Riddler: Can You Eat All The Chocolates?</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2020-10-02-riddler-can-you-eat-all-the-chocolates/</link>
  <description><![CDATA[ 





<p><a href="https://fivethirtyeight.com/features/can-you-eat-all-the-chocolates/">Today’s 538 Riddler Classic</a> is about eating chocolates:</p>
<blockquote class="blockquote">
<p>I have 10 chocolates in a bag: Two are milk chocolate, while the other eight are dark chocolate. One at a time, I randomly pull chocolates from the bag and eat them — that is, until I pick a chocolate of the other kind. When I get to the other type of chocolate, I put it back in the bag and start drawing again with the remaining chocolates. I keep going until I have eaten all 10 chocolates.</p>
<p>For example, if I first pull out a dark chocolate, I will eat it. (I’ll always eat the first chocolate I pull out.) If I pull out a second dark chocolate, I will eat that as well. If the third one is milk chocolate, I will not eat it (yet), and instead place it back in the bag. Then I will start again, eating the first chocolate I pull out.</p>
<p>What are the chances that the <em>last</em> chocolate I eat is milk chocolate?</p>
</blockquote>
<p>Our first approach will be a simple simulation to gauge what the answer should approximately be, before going to an analytical approach.</p>
<p><em>Added later: it turns out I misread the question. I assumed that after taking a chocolate that I could not eat, I would put it back and only eat the next one if it is of the same type. That is, however, not what’s asked: you always eat the following chocolate after you put one back, regardless of its type. I will keep my answer to the (wrong) question below for those who are interested.</em></p>
<section id="simulation-in-r" class="level2">
<h2 class="anchored" data-anchor-id="simulation-in-r">Simulation in R</h2>
<p>The following R function simulates eating one bag of chocolates and outputs what the last chocolate was.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1">chocolates <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"m"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb1-2"></span>
<span id="cb1-3">eat_chocolates <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>() {</span>
<span id="cb1-4">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># shuffle the chocolates around</span></span>
<span id="cb1-5">  chocolates_left <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(chocolates)</span>
<span id="cb1-6"></span>
<span id="cb1-7">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># eat the first chocolate</span></span>
<span id="cb1-8">  last_taken <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> chocolates_left[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb1-9">  chocolates_left <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> chocolates_left[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb1-10"></span>
<span id="cb1-11">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># eat the rest of the chocolates</span></span>
<span id="cb1-12">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(chocolates_left) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) {</span>
<span id="cb1-13">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># take the first chocolate out of the bag</span></span>
<span id="cb1-14">    to_eat <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> chocolates_left[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb1-15">    chocolates_left <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> chocolates_left[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb1-16"></span>
<span id="cb1-17">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># put back and shuffle if differs from previous piece</span></span>
<span id="cb1-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (to_eat <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> last_taken) {</span>
<span id="cb1-19">      chocolates_left <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(to_eat, chocolates_left))</span>
<span id="cb1-20">    }</span>
<span id="cb1-21"></span>
<span id="cb1-22">    last_taken <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> to_eat</span>
<span id="cb1-23">  }</span>
<span id="cb1-24"></span>
<span id="cb1-25">  last_taken</span>
<span id="cb1-26">}</span></code></pre></div>
</div>
<p>We can now easily run, for example, 100,000 simulations and calculate the percentage in which the last chocolate was milk:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">simulations <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">replicate</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e5</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">eat_chocolates</span>())</span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(simulations <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"m"</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.45907</code></pre>
</div>
</div>
<p>In a couple of seconds, this gives an estimate of a 46% probability of ending with a piece of milk chocolate. This is closer to 50% than I initially expected. Intuitively though, it does make sense, given the nature of the problem that the majority chocolate type will be eaten relatively quickly, since it is easier to get a ‘streak’ of those.</p>
<p>Running this (admittedly naive) simulation for more than, say, 1 million replications quickly becomes intractable. For a more accurate result that does run quickly, we can resort to recursion.</p>
</section>
<section id="recursion" class="level2">
<h2 class="anchored" data-anchor-id="recursion">Recursion</h2>
<p>The problem ca be written in a recursive form: given a number of milk and dark chocolates, we can create a set of possible next states and attach probabilities to those states. We can repeat this until we arrive at a bag of only one type of chocolate.</p>
<p>In order to do that, let’s first introduce some notation. Let <img src="https://latex.codecogs.com/png.latex?P(m,%20d,%20x)"> be the probability of ending with a milk chocolate given that we currently have a bag of <img src="https://latex.codecogs.com/png.latex?m"> milk and <img src="https://latex.codecogs.com/png.latex?d"> dark chocolates and that the last chocolate we ate was of type <img src="https://latex.codecogs.com/png.latex?x%5Cin%5C%7B%5Ctext%7Bmilk%7D,%20%5Ctext%7Bdark%7D%5C%7D">. Denote by <img src="https://latex.codecogs.com/png.latex?x%5Ec"> the chocolate type that is not <img src="https://latex.codecogs.com/png.latex?x">. We then know the trivial cases <img src="https://latex.codecogs.com/png.latex?P(m,%200,%20x)%20=%201"> and <img src="https://latex.codecogs.com/png.latex?P(0,d,x)=0">; you can’t “fail” if you only have milk left, and you can’t “succeed” if you only have dark chocolates left.</p>
<p>Moreover, the probability of ending with a milk chocolate given a certain distribution of chocolates and a previous pick equals the probability of ending with a dark chocolate given that we have switched all dark and milk chocolates around. In mathematical terms, <img src="https://latex.codecogs.com/png.latex?P(m,d%7Cx)%20=%201-P(d,m%7Cx%5Ec)">.</p>
<p>Now, given a state <img src="https://latex.codecogs.com/png.latex?(m,d,%20%5Ctext%7Bmilk%7D)">, you will pick a milk chocolate with probability <img src="https://latex.codecogs.com/png.latex?%5Cfrac%7Bm%7D%7Bm+d%7D">, resulting in a state of <img src="https://latex.codecogs.com/png.latex?(m-1,%20d,%20%5Ctext%7Bmilk%7D)">, or you will pick dark with probability <img src="https://latex.codecogs.com/png.latex?%5Cfrac%7Bd%7D%7Bm+d%7D">, resulting in <img src="https://latex.codecogs.com/png.latex?(m,%20d,%20%5Ctext%7Bdark%7D)">. In other words, given <img src="https://latex.codecogs.com/png.latex?m,d%3E0">,<img src="https://latex.codecogs.com/png.latex?%0AP(m,%20d,%20%5Ctext%7Bmilk%7D)%20=%20%5Cfrac%7Bm%7D%7Bm+d%7D%5Ccdot%20P(m-1,d,%5Ctext%7Bmilk%7D)%5C,+%5C,%5Cfrac%7Bd%7D%7Bm+d%7D%5Ccdot%20P(m,d,%5Ctext%7Bdark%7D).%0A"></p>
<p>We can now immediately see a problem with programming this recursion as it is: the second term did not decrease the total number of chocolates. Were we to do another step, we could again arrive at the situation we started with, thus resulting in an endless loop. In other words, theoretically we could keep alternately picking <img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bmilk%7D"> and <img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bdark%7D"> chocolates and never finish the whole bag.</p>
<p>We need to go deeper.</p>
<p>Let’s do another recursion step by expanding the right-most term in the above equation:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(m,d,%5Ctext%7Bdark%7D)%20=%20%5Cfrac%7Bm%7D%7Bm+d%7D%5Ccdot%20P(m,d,%5Ctext%7Bmilk%7D)%5C,+%5C,%5Cfrac%7Bd%7D%7Bm+d%7D%5Ccdot%20P(m,d-1,%5Ctext%7Bdark%7D).%0A"></p>
<p>Filling this into the first equation,</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(m,%20d,%20%5Ctext%7Bmilk%7D)%20=%20%5Cfrac%7Bm%7D%7Bm+d%7D%5Ccdot%20P(m-1,d,%5Ctext%7Bmilk%7D)%5C,+%5C,%5Cfrac%7Bd%7D%7Bm+d%7D%5Ccdot%20%5Cleft(%5Cfrac%7Bm%7D%7Bm+d%7D%5Ccdot%20P(m,d,%5Ctext%7Bmilk%7D)%5C,+%5C,%5Cfrac%7Bd%7D%7Bm+d%7D%5Ccdot%20P(m,d-1,%5Ctext%7Bdark%7D)%5Cright),%0A"></p>
<p>which we can rearrange into</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(m,%20d,%20%5Ctext%7Bmilk%7D)%20-%20%5Cfrac%7Bmd%7D%7B(m+d)%5E2%7D%5Ccdot%20P(m,d,%5Ctext%7Bmilk%7D)%20=%20%5Cfrac%7Bm%7D%7Bm+d%7D%5Ccdot%20P(m-1,d,%5Ctext%7Bmilk%7D)%5C,+%5C,%5Cfrac%7Bd%5E2%7D%7B(m+d)%5E2%7D%5Ccdot%20P(m,d-1,%5Ctext%7Bdark%7D),%0A"></p>
<p>or</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B(m+d)%5E2-md%7D%7B(m+d)%5E2%7D%5Ccdot%20P(m,d,%5Ctext%7Bmilk%7D)%20=%20%5Cfrac%7Bm%7D%7Bm+d%7D%5Ccdot%20P(m-1,d,%5Ctext%7Bmilk%7D)%5C,+%5C,%5Cfrac%7Bd%5E2%7D%7B(m+d)%5E2%7D%5Ccdot%20P(m,d-1,%5Ctext%7Bdark%7D),%0A"></p>
<p>which gives</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(m,d,%5Ctext%7Bmilk%7D)%20=%20%5Cfrac%7Bm%5E2+md%7D%7Bm%5E2+d%5E2+md%7D%5Ccdot%20P(m-1,d,%5Ctext%7Bmilk%7D)%5C,+%5C,%5Cfrac%7Bd%5E2%7D%7Bm%5E2+d%5E2+md%7D%5Ccdot%20P(m,d-1,%5Ctext%7Bdark%7D).%0A"></p>
<p>Now, by magic, this recursion does strictly decrease the total number of chocolates in the bag, thus making a program feasible. Together with the relationship <img src="https://latex.codecogs.com/png.latex?P(m,d,%5Ctext%7Bdark%7D)=1-P(d,m,%5Ctext%7Bmilk%7D)">, we can calculate our quantity of interest, which is the probability of ending with a milk chocolate given a starting bag and no previous chocolates eaten:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AP(m,d)=%5Cfrac%7Bm%7D%7Bm+d%7D%5Ccdot%20P(m-1,d,%5Ctext%7Bmilk%7D)%5C,+%5C,%5Cfrac%7Bd%7D%7Bm+d%7D%5Ccdot%20P(m,d-1,%5Ctext%7Bdark%7D).%0A"></p>
<p>In R code, this recursion can be programmed as follows.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">P <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m, d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">previous =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>) {</span>
<span id="cb4-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (m <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) {</span>
<span id="cb4-3">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb4-4">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (d <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) {</span>
<span id="cb4-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb4-6">  }</span>
<span id="cb4-7"></span>
<span id="cb4-8">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (previous <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>) {</span>
<span id="cb4-9">    m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(m<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"milk"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(m, d<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dark"</span>)</span>
<span id="cb4-10">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (previous <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"milk"</span>) {</span>
<span id="cb4-11">    (m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(m<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"milk"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(m, d<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dark"</span>)</span>
<span id="cb4-12">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (previous <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dark"</span>) {</span>
<span id="cb4-13">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(d, m, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"milk"</span>)</span>
<span id="cb4-14">  }</span>
<span id="cb4-15">}</span></code></pre></div>
</div>
<p>This allows us to calculate some simple examples,</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 1</code></pre>
</div>
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0</code></pre>
</div>
<div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.5</code></pre>
</div>
</div>
<p>but also the actual quantity of interest</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1] 0.4615372</code></pre>
</div>
</div>
<p>within a second. This agrees with the outcome of our simulation: the probability of ending with a milk chocolate is about 46.15%.</p>
</section>
<section id="other-starting-points" class="level2">
<h2 class="anchored" data-anchor-id="other-starting-points">Other starting points</h2>
<p>Now that we have code that runs quickly, we can explore the probabilities for other mixes of chocolates.</p>
<p>Say we start with 2 milk chocolates, but vary the number of dark chocolates.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span></code></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>Warning: package 'dplyr' was built under R version 4.2.3</code></pre>
</div>
<div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb15-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_set</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_light</span>())</span>
<span id="cb15-2"></span>
<span id="cb15-3">simulations <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tibble</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">m =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb15-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowwise</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb15-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P</span>(m, d))</span>
<span id="cb15-6"></span>
<span id="cb15-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(simulations, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(d, p)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_y_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">percent_format</span>()) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb15-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Probability of ending with a milk chocolate"</span>,</span>
<span id="cb15-11">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">subtitle =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Given 2 milk and a varying number of dark chocolates"</span>,</span>
<span id="cb15-12">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of dark chocolates"</span>,</span>
<span id="cb15-13">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Probability"</span>)</span></code></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2020-10-02-riddler-can-you-eat-all-the-chocolates/index_files/figure-html/unnamed-chunk-6-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>At first, the probability of success drops quickly, but at some point the streaks of dark chocolates will be so common that adding more dark chocolates does not decrease this probability significantly.</p>
<p>We can do the same thing in two dimensions by also varying the number of milk chocolates. Now, memoization comes in handy, since otherwise we calculate the same probability many times. The function <code>P_mem</code> calculates <code>P</code> but checks whether a certain probability has already been calculated in the list of matrices <code>mem</code>.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">n_max <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span></span>
<span id="cb16-2">mem <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">milk =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n_max, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncol =</span> n_max),</span>
<span id="cb16-3">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dark =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> n_max, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ncol =</span> n_max))</span>
<span id="cb16-4"></span>
<span id="cb16-5">P_mem <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(m, d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">previous =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>) {</span>
<span id="cb16-6">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (m <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) {</span>
<span id="cb16-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb16-8">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (d <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) {</span>
<span id="cb16-9">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb16-10">  }</span>
<span id="cb16-11"></span>
<span id="cb16-12">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (previous <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.na</span>(mem[[previous]][m, d])) {</span>
<span id="cb16-13">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(mem[[previous]][m, d])</span>
<span id="cb16-14">  }</span>
<span id="cb16-15"></span>
<span id="cb16-16">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (previous <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>) {</span>
<span id="cb16-17">    res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P_mem</span>(m<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"milk"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P_mem</span>(m, d<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dark"</span>)</span>
<span id="cb16-18">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (previous <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"milk"</span>) {</span>
<span id="cb16-19">    res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> (m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P_mem</span>(m<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>, d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"milk"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>(m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>m<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>d)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P_mem</span>(m, d<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">-1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dark"</span>)</span>
<span id="cb16-20">    mem[[previous]][m, d] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;&lt;-</span> res</span>
<span id="cb16-21">  } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (previous <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dark"</span>) {</span>
<span id="cb16-22">    res <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P_mem</span>(d, m, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"milk"</span>)</span>
<span id="cb16-23">    mem[[previous]][m, d] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;&lt;-</span> res</span>
<span id="cb16-24">  }</span>
<span id="cb16-25"></span>
<span id="cb16-26">  res</span>
<span id="cb16-27">}</span>
<span id="cb16-28"></span>
<span id="cb16-29">simulations <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">crossing</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">m =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_max, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">d =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n_max) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb16-30">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rowwise</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb16-31">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mutate</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">P_mem</span>(m, d))</span>
<span id="cb16-32"></span>
<span id="cb16-33"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(simulations, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(m, d, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> p)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-34">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_raster</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-35">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale_fill_continuous</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">labels =</span> scales<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">percent_format</span>()) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb16-36">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">labs</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Probability of ending with a milk chocolate"</span>,</span>
<span id="cb16-37">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of milk chocolates"</span>,</span>
<span id="cb16-38">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Number of dark chocolates"</span>,</span>
<span id="cb16-39">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Probability"</span>)</span></code></pre></div>
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2020-10-02-riddler-can-you-eat-all-the-chocolates/index_files/figure-html/unnamed-chunk-7-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>This graph shows that the more chocolates there are in the bag, the smaller the differences between different mixes become.</p>


</section>

 ]]></description>
  <guid>https://www.basjacobs.com/post/2020-10-02-riddler-can-you-eat-all-the-chocolates/</guid>
  <pubDate>Thu, 01 Oct 2020 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Trees and Tents</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2019-04-21-trees-and-tents/</link>
  <description><![CDATA[ 





<p>Trees and Tents is a logic game in which tents need to be placed in a grid. Every tent must be next to a tree, and tents cannot touch horizontally, vertically or diagonally. For every row and column, the number of tents is given.</p>
<p>The website https://brainbashers.com/tents.asp posts a new puzzle every day, of which a 12x12 example is the following:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2019-04-21-trees-and-tents/example.png" class="img-fluid figure-img" style="width:70.0%"></p>
<figcaption>A 12x12 Trees and Tents puzzle from https://brainbashers.com/tents.asp</figcaption>
</figure>
</div>
<p>In this post, I will implement a solver for this puzzle in Julia using the <a href="https://github.com/JuliaOpt/JuMP.jl">JuMP</a> package for mathematical optimization. The complete code as a jupyter notebook can be found <a href="https://github.com/basjacobs93/trees_and_tents">here</a>.</p>
<section id="problem-definition" class="level2">
<h2 class="anchored" data-anchor-id="problem-definition">Problem definition</h2>
<p>The puzzle can be formulated as a linear programming problem. There are three types of constraints:</p>
<ul>
<li>every tent must be next to a tree,</li>
<li>the number of tents for every row and column is given,</li>
<li>tents are not allowed to touch.</li>
</ul>
<p>Even though we treat this puzzle as an optimization problem, there is no objective to be maximized or minimized in this case; any placements of tents satisfying the constraints is a valid solution. This is similar to the <a href="https://github.com/JuliaOpt/JuMP.jl/blob/master/examples/sudoku.jl">sudoku</a> <a href="https://pythonhosted.org/PuLP/CaseStudies/a_sudoku_problem.html">solutions</a> in which the objective is also unimportant.</p>
<p>Julia’s JuMP package provides a clean interface to defining such a problem, and solving it with various solvers. In this case, we use <a href="https://www.gnu.org/software/glpk/">GLPK</a> since it’s free and works great for this problem. Solving the problem is a matter of writing down the constraints and calling <code>JuMP.optimize</code>.</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">using</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">JuMP</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">GLPK</span></span></code></pre></div>
<p>After loading the necessary packages, we need to define the puzzle displayed above. In the website’s html code, the puzzle is represented by three strings.</p>
<ul>
<li><code>lcpuzzle</code> is a string of numbers, denoting the cells from left to right, top to bottom. The values represent whether the corresponding cell is blank (0), or contains a tree (1) or a tent (2). Note that this string contains the solution to the problem as well, so this allows us to check the solution that JuMP found afterwards.</li>
<li><code>lcrownumbers</code> is a string of numbers which denote the number of tents per row.</li>
<li><code>lcrolnumbers</code> is a string of numbers which denote the number of tents per column.</li>
</ul>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># from html, 0=blank, 1=tree, 2=tent</span></span>
<span id="cb2-2">lcpuzzle <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"001202011200021001020012000120001200020100100000010200200000201000001212102020000000000010021012201000000200102002020102000001010001001201201212"</span></span>
<span id="cb2-3">lcrownumbers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"332123222404"</span></span>
<span id="cb2-4">lccolnumbers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"222322230505"</span></span></code></pre></div>
<p>We rewrite the above representation into something that is more easy to work with:</p>
<ul>
<li><code>trees</code> is a list of <code>(i,j)</code> tuples corresponding to the locations of the trees.</li>
<li><code>row_sums</code> and <code>col_sums</code> are lists of integers denoting the totals per row and column.</li>
<li><code>n</code> is the size of the game, which is in this case 12.</li>
</ul>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb3-1">puzzle <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, i) for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> lcpuzzle]</span>
<span id="cb3-2">n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Int</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(puzzle)))</span>
<span id="cb3-3"></span>
<span id="cb3-4">trees <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [(i, j) for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n, j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n if puzzle[(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> j] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb3-5">row_sums <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, i) for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> lcrownumbers]</span>
<span id="cb3-6">col_sums <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parse</span>(<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Int</span>, i) for i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> lccolnumbers]</span></code></pre></div>
<p>We initialize the solver, telling JuMP that we want to use GLPK. The variable that JuMP optimizes over is an <img src="https://latex.codecogs.com/png.latex?n%5Ctimes%20n"> matrix <code>x</code>, consisting of binary values, where a 0 means no tent for that cell, and a 1 means that the cell contains a tent.</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb4-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Model</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">with_optimizer</span>(GLPK.Optimizer))</span>
<span id="cb4-2"></span>
<span id="cb4-3"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@variable</span>(model, x[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n], Bin)</span></code></pre></div>
</section>
<section id="constraints" class="level2">
<h2 class="anchored" data-anchor-id="constraints">Constraints</h2>
<p>We are now ready to define the constraints. We start with the requirement that a tent be next to a tree.</p>
<p>First, a tent cannot be on top of a tree. Hence, if a tree is on position <code>(row, col)</code>, then <code>x[row, col]</code> must be <img src="https://latex.codecogs.com/png.latex?0">.</p>
<p>Next, for every cell <code>(row, col)</code> we check whether there is a tree next to this cell. If not, then this cell cannot contain a tent, hence <code>x[row, col]</code> should be <img src="https://latex.codecogs.com/png.latex?0">.</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n, col <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n</span>
<span id="cb5-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># is not on a tree</span></span>
<span id="cb5-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (row, col) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> trees</span>
<span id="cb5-4">        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, x[row, col] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb5-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-6"></span>
<span id="cb5-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># should be next to a tree</span></span>
<span id="cb5-8">    found <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">false</span></span>
<span id="cb5-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tree <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> trees</span>
<span id="cb5-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(tree[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> row) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(tree[<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> col) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb5-11">            found <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb5-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> !found</span>
<span id="cb5-15">        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, x[row, col] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb5-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb5-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>The next constraint makes sure that the number of tents in the rows and columns add up to the right values. This can be done simply by summing the columns and rows of the matrix <code>x</code>, since this equals counting the number of ones.</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb6-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n</span>
<span id="cb6-2">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[i, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> row_sums[i])</span>
<span id="cb6-3">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>, i]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> col_sums[i])</span>
<span id="cb6-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<p>Lastly, we need to encode the fact that the tents may not touch horizontally, vertically or diagonally. In other words, every <img src="https://latex.codecogs.com/png.latex?2%5Ctimes2"> square contains at most one tree, which is also easy to establish using the representation we chose.</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb7-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), col <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb7-2">    <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@constraint</span>(model, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sum</span>(x[row<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>row<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb7-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
</section>
<section id="solution" class="level2">
<h2 class="anchored" data-anchor-id="solution">Solution</h2>
<p>Now that we have represented the puzzle as a Linear Program, we can simply tel JuMP to optimize this. Within a second, it spits out a solution. Since Julia supports Unicode characters, we can visualize the solution as a grid of emoji.</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb8-1">JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optimize!</span>(model)</span>
<span id="cb8-2"></span>
<span id="cb8-3">solution <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JuMP.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span>.(x)</span>
<span id="cb8-4"></span>
<span id="cb8-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> row <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n</span>
<span id="cb8-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> col <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>n</span>
<span id="cb8-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> solution[row, col] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb8-8">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"⛺"</span>)</span>
<span id="cb8-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elseif</span> (row, col) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> trees</span>
<span id="cb8-10">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"🌲"</span>)</span>
<span id="cb8-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span></span>
<span id="cb8-12">            <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"◻️"</span>)</span>
<span id="cb8-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb8-14">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" "</span>)</span>
<span id="cb8-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb8-16">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">println</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span>
<span id="cb8-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div>
<pre><code>◻️ ◻️ 🌲 ⛺ ◻️ ⛺ ◻️ 🌲 🌲 ⛺ ◻️ ◻️
◻️ ⛺ 🌲 ◻️ ◻️ 🌲 ◻️ ⛺ ◻️ ◻️ 🌲 ⛺
◻️ ◻️ ◻️ 🌲 ⛺ ◻️ ◻️ ◻️ 🌲 ⛺ ◻️ ◻️
◻️ ⛺ ◻️ 🌲 ◻️ ◻️ 🌲 ◻️ ◻️ ◻️ ◻️ ◻️
◻️ 🌲 ◻️ ⛺ ◻️ ◻️ ⛺ ◻️ ◻️ ◻️ ◻️ ◻️
⛺ ◻️ 🌲 ◻️ ◻️ ◻️ ◻️ ◻️ 🌲 ⛺ 🌲 ⛺
🌲 ◻️ ⛺ ◻️ ⛺ ◻️ ◻️ ◻️ ◻️ ◻️ ◻️ ◻️
◻️ ◻️ ◻️ ◻️ 🌲 ◻️ ◻️ ⛺ 🌲 ◻️ 🌲 ⛺
⛺ ◻️ 🌲 ◻️ ◻️ ◻️ ◻️ ◻️ ◻️ ⛺ ◻️ ◻️
🌲 ◻️ ⛺ ◻️ ◻️ ⛺ ◻️ ⛺ ◻️ 🌲 ◻️ ⛺
◻️ ◻️ ◻️ ◻️ ◻️ 🌲 ◻️ 🌲 ◻️ ◻️ ◻️ 🌲
◻️ ◻️ 🌲 ⛺ ◻️ 🌲 ⛺ ◻️ 🌲 ⛺ 🌲 ⛺</code></pre>
<p>That’s it! I like the JuMP syntax a lot and will definitely use it to solve more puzzles!</p>


</section>

 ]]></description>
  <guid>https://www.basjacobs.com/post/2019-04-21-trees-and-tents/</guid>
  <pubDate>Sat, 20 Apr 2019 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Showing images on hover in Plotly with R</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2018-10-28-showing-images-on-hover-in-plotly-with-r/</link>
  <description><![CDATA[ 





<p>For a project I was working on recently, I wanted to turn a <code>ggplot</code> scatterplot into an interactive visualisation: when hovering over a point, a corresponding image needed to be shown. I did not want to use Shiny, since I required the visualisation to be portable. This is possible by <a href="https://github.com/etpinard/plotly-dashboards/tree/master/hover-images">manually tinkering with html</a>, but using the <code>plotly</code> and <code>htmlwidgets</code> packages, I was able to achieve what I wanted without the need to leave the comfy RStudio environment, and without needing to host the plot on the plot.ly website.</p>
<p>The <a href="https://plot.ly/r/">plotly</a> library provides the useful <code>ggplotly</code> function to make static plots interactive with just one line of code. If we apply it to a <code>ggplot</code> of the famous <code>iris</code> dataset, it looks like this.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(plotly)</span>
<span id="cb1-3"></span>
<span id="cb1-4">g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(iris, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Sepal.Length,</span>
<span id="cb1-5">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Petal.Length,</span>
<span id="cb1-6">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> Species)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>()</span>
<span id="cb1-7">p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplotly</span>(g) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">partial_bundle</span>()</span>
<span id="cb1-8"></span>
<span id="cb1-9">p</span></code></pre></div>
<div class="cell-output-display">
<div class="plotly html-widget html-fill-item" id="htmlwidget-5913f22604a7ff074ad5" style="width:100%;height:464px;"></div>
<script type="application/json" data-for="htmlwidget-5913f22604a7ff074ad5">{"x":{"data":[{"x":[5.0999999999999996,4.9000000000000004,4.7000000000000002,4.5999999999999996,5,5.4000000000000004,4.5999999999999996,5,4.4000000000000004,4.9000000000000004,5.4000000000000004,4.7999999999999998,4.7999999999999998,4.2999999999999998,5.7999999999999998,5.7000000000000002,5.4000000000000004,5.0999999999999996,5.7000000000000002,5.0999999999999996,5.4000000000000004,5.0999999999999996,4.5999999999999996,5.0999999999999996,4.7999999999999998,5,5,5.2000000000000002,5.2000000000000002,4.7000000000000002,4.7999999999999998,5.4000000000000004,5.2000000000000002,5.5,4.9000000000000004,5,5.5,4.9000000000000004,4.4000000000000004,5.0999999999999996,5,4.5,4.4000000000000004,5,5.0999999999999996,4.7999999999999998,5.0999999999999996,4.5999999999999996,5.2999999999999998,5],"y":[1.3999999999999999,1.3999999999999999,1.3,1.5,1.3999999999999999,1.7,1.3999999999999999,1.5,1.3999999999999999,1.5,1.5,1.6000000000000001,1.3999999999999999,1.1000000000000001,1.2,1.5,1.3,1.3999999999999999,1.7,1.5,1.7,1.5,1,1.7,1.8999999999999999,1.6000000000000001,1.6000000000000001,1.5,1.3999999999999999,1.6000000000000001,1.6000000000000001,1.5,1.5,1.3999999999999999,1.5,1.2,1.3,1.3999999999999999,1.3,1.5,1.3,1.3,1.3,1.6000000000000001,1.8999999999999999,1.3999999999999999,1.6000000000000001,1.3999999999999999,1.5,1.3999999999999999],"text":["Sepal.Length: 5.1<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 4.9<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 4.7<br />Petal.Length: 1.3<br />Species: setosa","Sepal.Length: 4.6<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.0<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 5.4<br />Petal.Length: 1.7<br />Species: setosa","Sepal.Length: 4.6<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 5.0<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 4.4<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 4.9<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.4<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 4.8<br />Petal.Length: 1.6<br />Species: setosa","Sepal.Length: 4.8<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 4.3<br />Petal.Length: 1.1<br />Species: setosa","Sepal.Length: 5.8<br />Petal.Length: 1.2<br />Species: setosa","Sepal.Length: 5.7<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.4<br />Petal.Length: 1.3<br />Species: setosa","Sepal.Length: 5.1<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 5.7<br />Petal.Length: 1.7<br />Species: setosa","Sepal.Length: 5.1<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.4<br />Petal.Length: 1.7<br />Species: setosa","Sepal.Length: 5.1<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 4.6<br />Petal.Length: 1.0<br />Species: setosa","Sepal.Length: 5.1<br />Petal.Length: 1.7<br />Species: setosa","Sepal.Length: 4.8<br />Petal.Length: 1.9<br />Species: setosa","Sepal.Length: 5.0<br />Petal.Length: 1.6<br />Species: setosa","Sepal.Length: 5.0<br />Petal.Length: 1.6<br />Species: setosa","Sepal.Length: 5.2<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.2<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 4.7<br />Petal.Length: 1.6<br />Species: setosa","Sepal.Length: 4.8<br />Petal.Length: 1.6<br />Species: setosa","Sepal.Length: 5.4<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.2<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.5<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 4.9<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.0<br />Petal.Length: 1.2<br />Species: setosa","Sepal.Length: 5.5<br />Petal.Length: 1.3<br />Species: setosa","Sepal.Length: 4.9<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 4.4<br />Petal.Length: 1.3<br />Species: setosa","Sepal.Length: 5.1<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.0<br />Petal.Length: 1.3<br />Species: setosa","Sepal.Length: 4.5<br />Petal.Length: 1.3<br />Species: setosa","Sepal.Length: 4.4<br />Petal.Length: 1.3<br />Species: setosa","Sepal.Length: 5.0<br />Petal.Length: 1.6<br />Species: setosa","Sepal.Length: 5.1<br />Petal.Length: 1.9<br />Species: setosa","Sepal.Length: 4.8<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 5.1<br />Petal.Length: 1.6<br />Species: setosa","Sepal.Length: 4.6<br />Petal.Length: 1.4<br />Species: setosa","Sepal.Length: 5.3<br />Petal.Length: 1.5<br />Species: setosa","Sepal.Length: 5.0<br />Petal.Length: 1.4<br />Species: setosa"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(248,118,109,1)","opacity":1,"size":5.6692913385826778,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(248,118,109,1)"}},"hoveron":"points","name":"setosa","legendgroup":"setosa","showlegend":true,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[7,6.4000000000000004,6.9000000000000004,5.5,6.5,5.7000000000000002,6.2999999999999998,4.9000000000000004,6.5999999999999996,5.2000000000000002,5,5.9000000000000004,6,6.0999999999999996,5.5999999999999996,6.7000000000000002,5.5999999999999996,5.7999999999999998,6.2000000000000002,5.5999999999999996,5.9000000000000004,6.0999999999999996,6.2999999999999998,6.0999999999999996,6.4000000000000004,6.5999999999999996,6.7999999999999998,6.7000000000000002,6,5.7000000000000002,5.5,5.5,5.7999999999999998,6,5.4000000000000004,6,6.7000000000000002,6.2999999999999998,5.5999999999999996,5.5,5.5,6.0999999999999996,5.7999999999999998,5,5.5999999999999996,5.7000000000000002,5.7000000000000002,6.2000000000000002,5.0999999999999996,5.7000000000000002],"y":[4.7000000000000002,4.5,4.9000000000000004,4,4.5999999999999996,4.5,4.7000000000000002,3.2999999999999998,4.5999999999999996,3.8999999999999999,3.5,4.2000000000000002,4,4.7000000000000002,3.6000000000000001,4.4000000000000004,4.5,4.0999999999999996,4.5,3.8999999999999999,4.7999999999999998,4,4.9000000000000004,4.7000000000000002,4.2999999999999998,4.4000000000000004,4.7999999999999998,5,4.5,3.5,3.7999999999999998,3.7000000000000002,3.8999999999999999,5.0999999999999996,4.5,4.5,4.7000000000000002,4.4000000000000004,4.0999999999999996,4,4.4000000000000004,4.5999999999999996,4,3.2999999999999998,4.2000000000000002,4.2000000000000002,4.2000000000000002,4.2999999999999998,3,4.0999999999999996],"text":["Sepal.Length: 7.0<br />Petal.Length: 4.7<br />Species: versicolor","Sepal.Length: 6.4<br />Petal.Length: 4.5<br />Species: versicolor","Sepal.Length: 6.9<br />Petal.Length: 4.9<br />Species: versicolor","Sepal.Length: 5.5<br />Petal.Length: 4.0<br />Species: versicolor","Sepal.Length: 6.5<br />Petal.Length: 4.6<br />Species: versicolor","Sepal.Length: 5.7<br />Petal.Length: 4.5<br />Species: versicolor","Sepal.Length: 6.3<br />Petal.Length: 4.7<br />Species: versicolor","Sepal.Length: 4.9<br />Petal.Length: 3.3<br />Species: versicolor","Sepal.Length: 6.6<br />Petal.Length: 4.6<br />Species: versicolor","Sepal.Length: 5.2<br />Petal.Length: 3.9<br />Species: versicolor","Sepal.Length: 5.0<br />Petal.Length: 3.5<br />Species: versicolor","Sepal.Length: 5.9<br />Petal.Length: 4.2<br />Species: versicolor","Sepal.Length: 6.0<br />Petal.Length: 4.0<br />Species: versicolor","Sepal.Length: 6.1<br />Petal.Length: 4.7<br />Species: versicolor","Sepal.Length: 5.6<br />Petal.Length: 3.6<br />Species: versicolor","Sepal.Length: 6.7<br />Petal.Length: 4.4<br />Species: versicolor","Sepal.Length: 5.6<br />Petal.Length: 4.5<br />Species: versicolor","Sepal.Length: 5.8<br />Petal.Length: 4.1<br />Species: versicolor","Sepal.Length: 6.2<br />Petal.Length: 4.5<br />Species: versicolor","Sepal.Length: 5.6<br />Petal.Length: 3.9<br />Species: versicolor","Sepal.Length: 5.9<br />Petal.Length: 4.8<br />Species: versicolor","Sepal.Length: 6.1<br />Petal.Length: 4.0<br />Species: versicolor","Sepal.Length: 6.3<br />Petal.Length: 4.9<br />Species: versicolor","Sepal.Length: 6.1<br />Petal.Length: 4.7<br />Species: versicolor","Sepal.Length: 6.4<br />Petal.Length: 4.3<br />Species: versicolor","Sepal.Length: 6.6<br />Petal.Length: 4.4<br />Species: versicolor","Sepal.Length: 6.8<br />Petal.Length: 4.8<br />Species: versicolor","Sepal.Length: 6.7<br />Petal.Length: 5.0<br />Species: versicolor","Sepal.Length: 6.0<br />Petal.Length: 4.5<br />Species: versicolor","Sepal.Length: 5.7<br />Petal.Length: 3.5<br />Species: versicolor","Sepal.Length: 5.5<br />Petal.Length: 3.8<br />Species: versicolor","Sepal.Length: 5.5<br />Petal.Length: 3.7<br />Species: versicolor","Sepal.Length: 5.8<br />Petal.Length: 3.9<br />Species: versicolor","Sepal.Length: 6.0<br />Petal.Length: 5.1<br />Species: versicolor","Sepal.Length: 5.4<br />Petal.Length: 4.5<br />Species: versicolor","Sepal.Length: 6.0<br />Petal.Length: 4.5<br />Species: versicolor","Sepal.Length: 6.7<br />Petal.Length: 4.7<br />Species: versicolor","Sepal.Length: 6.3<br />Petal.Length: 4.4<br />Species: versicolor","Sepal.Length: 5.6<br />Petal.Length: 4.1<br />Species: versicolor","Sepal.Length: 5.5<br />Petal.Length: 4.0<br />Species: versicolor","Sepal.Length: 5.5<br />Petal.Length: 4.4<br />Species: versicolor","Sepal.Length: 6.1<br />Petal.Length: 4.6<br />Species: versicolor","Sepal.Length: 5.8<br />Petal.Length: 4.0<br />Species: versicolor","Sepal.Length: 5.0<br />Petal.Length: 3.3<br />Species: versicolor","Sepal.Length: 5.6<br />Petal.Length: 4.2<br />Species: versicolor","Sepal.Length: 5.7<br />Petal.Length: 4.2<br />Species: versicolor","Sepal.Length: 5.7<br />Petal.Length: 4.2<br />Species: versicolor","Sepal.Length: 6.2<br />Petal.Length: 4.3<br />Species: versicolor","Sepal.Length: 5.1<br />Petal.Length: 3.0<br />Species: versicolor","Sepal.Length: 5.7<br />Petal.Length: 4.1<br />Species: versicolor"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(0,186,56,1)","opacity":1,"size":5.6692913385826778,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(0,186,56,1)"}},"hoveron":"points","name":"versicolor","legendgroup":"versicolor","showlegend":true,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[6.2999999999999998,5.7999999999999998,7.0999999999999996,6.2999999999999998,6.5,7.5999999999999996,4.9000000000000004,7.2999999999999998,6.7000000000000002,7.2000000000000002,6.5,6.4000000000000004,6.7999999999999998,5.7000000000000002,5.7999999999999998,6.4000000000000004,6.5,7.7000000000000002,7.7000000000000002,6,6.9000000000000004,5.5999999999999996,7.7000000000000002,6.2999999999999998,6.7000000000000002,7.2000000000000002,6.2000000000000002,6.0999999999999996,6.4000000000000004,7.2000000000000002,7.4000000000000004,7.9000000000000004,6.4000000000000004,6.2999999999999998,6.0999999999999996,7.7000000000000002,6.2999999999999998,6.4000000000000004,6,6.9000000000000004,6.7000000000000002,6.9000000000000004,5.7999999999999998,6.7999999999999998,6.7000000000000002,6.7000000000000002,6.2999999999999998,6.5,6.2000000000000002,5.9000000000000004],"y":[6,5.0999999999999996,5.9000000000000004,5.5999999999999996,5.7999999999999998,6.5999999999999996,4.5,6.2999999999999998,5.7999999999999998,6.0999999999999996,5.0999999999999996,5.2999999999999998,5.5,5,5.0999999999999996,5.2999999999999998,5.5,6.7000000000000002,6.9000000000000004,5,5.7000000000000002,4.9000000000000004,6.7000000000000002,4.9000000000000004,5.7000000000000002,6,4.7999999999999998,4.9000000000000004,5.5999999999999996,5.7999999999999998,6.0999999999999996,6.4000000000000004,5.5999999999999996,5.0999999999999996,5.5999999999999996,6.0999999999999996,5.5999999999999996,5.5,4.7999999999999998,5.4000000000000004,5.5999999999999996,5.0999999999999996,5.0999999999999996,5.9000000000000004,5.7000000000000002,5.2000000000000002,5,5.2000000000000002,5.4000000000000004,5.0999999999999996],"text":["Sepal.Length: 6.3<br />Petal.Length: 6.0<br />Species: virginica","Sepal.Length: 5.8<br />Petal.Length: 5.1<br />Species: virginica","Sepal.Length: 7.1<br />Petal.Length: 5.9<br />Species: virginica","Sepal.Length: 6.3<br />Petal.Length: 5.6<br />Species: virginica","Sepal.Length: 6.5<br />Petal.Length: 5.8<br />Species: virginica","Sepal.Length: 7.6<br />Petal.Length: 6.6<br />Species: virginica","Sepal.Length: 4.9<br />Petal.Length: 4.5<br />Species: virginica","Sepal.Length: 7.3<br />Petal.Length: 6.3<br />Species: virginica","Sepal.Length: 6.7<br />Petal.Length: 5.8<br />Species: virginica","Sepal.Length: 7.2<br />Petal.Length: 6.1<br />Species: virginica","Sepal.Length: 6.5<br />Petal.Length: 5.1<br />Species: virginica","Sepal.Length: 6.4<br />Petal.Length: 5.3<br />Species: virginica","Sepal.Length: 6.8<br />Petal.Length: 5.5<br />Species: virginica","Sepal.Length: 5.7<br />Petal.Length: 5.0<br />Species: virginica","Sepal.Length: 5.8<br />Petal.Length: 5.1<br />Species: virginica","Sepal.Length: 6.4<br />Petal.Length: 5.3<br />Species: virginica","Sepal.Length: 6.5<br />Petal.Length: 5.5<br />Species: virginica","Sepal.Length: 7.7<br />Petal.Length: 6.7<br />Species: virginica","Sepal.Length: 7.7<br />Petal.Length: 6.9<br />Species: virginica","Sepal.Length: 6.0<br />Petal.Length: 5.0<br />Species: virginica","Sepal.Length: 6.9<br />Petal.Length: 5.7<br />Species: virginica","Sepal.Length: 5.6<br />Petal.Length: 4.9<br />Species: virginica","Sepal.Length: 7.7<br />Petal.Length: 6.7<br />Species: virginica","Sepal.Length: 6.3<br />Petal.Length: 4.9<br />Species: virginica","Sepal.Length: 6.7<br />Petal.Length: 5.7<br />Species: virginica","Sepal.Length: 7.2<br />Petal.Length: 6.0<br />Species: virginica","Sepal.Length: 6.2<br />Petal.Length: 4.8<br />Species: virginica","Sepal.Length: 6.1<br />Petal.Length: 4.9<br />Species: virginica","Sepal.Length: 6.4<br />Petal.Length: 5.6<br />Species: virginica","Sepal.Length: 7.2<br />Petal.Length: 5.8<br />Species: virginica","Sepal.Length: 7.4<br />Petal.Length: 6.1<br />Species: virginica","Sepal.Length: 7.9<br />Petal.Length: 6.4<br />Species: virginica","Sepal.Length: 6.4<br />Petal.Length: 5.6<br />Species: virginica","Sepal.Length: 6.3<br />Petal.Length: 5.1<br />Species: virginica","Sepal.Length: 6.1<br />Petal.Length: 5.6<br />Species: virginica","Sepal.Length: 7.7<br />Petal.Length: 6.1<br />Species: virginica","Sepal.Length: 6.3<br />Petal.Length: 5.6<br />Species: virginica","Sepal.Length: 6.4<br />Petal.Length: 5.5<br />Species: virginica","Sepal.Length: 6.0<br />Petal.Length: 4.8<br />Species: virginica","Sepal.Length: 6.9<br />Petal.Length: 5.4<br />Species: virginica","Sepal.Length: 6.7<br />Petal.Length: 5.6<br />Species: virginica","Sepal.Length: 6.9<br />Petal.Length: 5.1<br />Species: virginica","Sepal.Length: 5.8<br />Petal.Length: 5.1<br />Species: virginica","Sepal.Length: 6.8<br />Petal.Length: 5.9<br />Species: virginica","Sepal.Length: 6.7<br />Petal.Length: 5.7<br />Species: virginica","Sepal.Length: 6.7<br />Petal.Length: 5.2<br />Species: virginica","Sepal.Length: 6.3<br />Petal.Length: 5.0<br />Species: virginica","Sepal.Length: 6.5<br />Petal.Length: 5.2<br />Species: virginica","Sepal.Length: 6.2<br />Petal.Length: 5.4<br />Species: virginica","Sepal.Length: 5.9<br />Petal.Length: 5.1<br />Species: virginica"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(97,156,255,1)","opacity":1,"size":5.6692913385826778,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(97,156,255,1)"}},"hoveron":"points","name":"virginica","legendgroup":"virginica","showlegend":true,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null}],"layout":{"margin":{"t":26.228310502283108,"r":7.3059360730593621,"b":40.182648401826498,"l":31.415525114155255},"plot_bgcolor":"rgba(235,235,235,1)","paper_bgcolor":"rgba(255,255,255,1)","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724},"xaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[4.1200000000000001,8.0800000000000001],"tickmode":"array","ticktext":["5","6","7","8"],"tickvals":[5,6,7,8],"categoryorder":"array","categoryarray":["5","6","7","8"],"nticks":null,"ticks":"outside","tickcolor":"rgba(51,51,51,1)","ticklen":3.6529680365296811,"tickwidth":0.66417600664176002,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":11.68949771689498},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(255,255,255,1)","gridwidth":0.66417600664176002,"zeroline":false,"anchor":"y","title":{"text":"Sepal.Length","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724}},"hoverformat":".2f"},"yaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[0.70499999999999996,7.1950000000000003],"tickmode":"array","ticktext":["2","4","6"],"tickvals":[2,4,6],"categoryorder":"array","categoryarray":["2","4","6"],"nticks":null,"ticks":"outside","tickcolor":"rgba(51,51,51,1)","ticklen":3.6529680365296811,"tickwidth":0.66417600664176002,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":11.68949771689498},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(255,255,255,1)","gridwidth":0.66417600664176002,"zeroline":false,"anchor":"x","title":{"text":"Petal.Length","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724}},"hoverformat":".2f"},"shapes":[{"type":"rect","fillcolor":null,"line":{"color":null,"width":0,"linetype":[]},"yref":"paper","xref":"paper","x0":0,"x1":1,"y0":0,"y1":1}],"showlegend":true,"legend":{"bgcolor":"rgba(255,255,255,1)","bordercolor":"transparent","borderwidth":1.8897637795275593,"font":{"color":"rgba(0,0,0,1)","family":"","size":11.68949771689498},"title":{"text":"Species","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724}}},"hovermode":"closest","barmode":"relative"},"config":{"doubleClick":"reset","modeBarButtonsToAdd":["hoverclosest","hovercompare"],"showSendToCloud":false},"source":"A","attrs":{"1426937feccba":{"x":{},"y":{},"colour":{},"type":"scatter"}},"cur_data":"1426937feccba","visdat":{"1426937feccba":["function (y) ","x"]},"highlight":{"on":"plotly_click","persistent":false,"dynamic":false,"selectize":false,"opacityDim":0.20000000000000001,"selected":{"opacity":1},"debounce":0},"shinyEvents":["plotly_hover","plotly_click","plotly_selected","plotly_relayout","plotly_brushed","plotly_brushing","plotly_clickannotation","plotly_doubleclick","plotly_deselect","plotly_afterplot","plotly_sunburstclick"],"base_url":"https://plot.ly"},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>Among other things, we can now hover over a point on the graph and in the tooltip receive information about the corresponding data point. By default, the information displayed is exactly the information we define in the <code>aes</code> mapping. If we want other information, we can add it in the <code>text</code> aesthetic, which plotly can read. If we provide <code>ggplotly</code> with the <code>tooltip = "text"</code> option, this aesthetic is the only thing that is shown.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1">g <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(iris, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> Sepal.Length,</span>
<span id="cb2-2">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> Petal.Length,</span>
<span id="cb2-3">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> Species,</span>
<span id="cb2-4">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">text =</span> Species)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_point</span>()</span>
<span id="cb2-5">p <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplotly</span>(g, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tooltip =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">partial_bundle</span>() </span>
<span id="cb2-6"></span>
<span id="cb2-7">p</span></code></pre></div>
<div class="cell-output-display">
<div class="plotly html-widget html-fill-item" id="htmlwidget-371b2fdb2ba2a0f7a69e" style="width:100%;height:464px;"></div>
<script type="application/json" data-for="htmlwidget-371b2fdb2ba2a0f7a69e">{"x":{"data":[{"x":[5.0999999999999996,4.9000000000000004,4.7000000000000002,4.5999999999999996,5,5.4000000000000004,4.5999999999999996,5,4.4000000000000004,4.9000000000000004,5.4000000000000004,4.7999999999999998,4.7999999999999998,4.2999999999999998,5.7999999999999998,5.7000000000000002,5.4000000000000004,5.0999999999999996,5.7000000000000002,5.0999999999999996,5.4000000000000004,5.0999999999999996,4.5999999999999996,5.0999999999999996,4.7999999999999998,5,5,5.2000000000000002,5.2000000000000002,4.7000000000000002,4.7999999999999998,5.4000000000000004,5.2000000000000002,5.5,4.9000000000000004,5,5.5,4.9000000000000004,4.4000000000000004,5.0999999999999996,5,4.5,4.4000000000000004,5,5.0999999999999996,4.7999999999999998,5.0999999999999996,4.5999999999999996,5.2999999999999998,5],"y":[1.3999999999999999,1.3999999999999999,1.3,1.5,1.3999999999999999,1.7,1.3999999999999999,1.5,1.3999999999999999,1.5,1.5,1.6000000000000001,1.3999999999999999,1.1000000000000001,1.2,1.5,1.3,1.3999999999999999,1.7,1.5,1.7,1.5,1,1.7,1.8999999999999999,1.6000000000000001,1.6000000000000001,1.5,1.3999999999999999,1.6000000000000001,1.6000000000000001,1.5,1.5,1.3999999999999999,1.5,1.2,1.3,1.3999999999999999,1.3,1.5,1.3,1.3,1.3,1.6000000000000001,1.8999999999999999,1.3999999999999999,1.6000000000000001,1.3999999999999999,1.5,1.3999999999999999],"text":"setosa","type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(248,118,109,1)","opacity":1,"size":5.6692913385826778,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(248,118,109,1)"}},"hoveron":"points","name":"setosa","legendgroup":"setosa","showlegend":true,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[7,6.4000000000000004,6.9000000000000004,5.5,6.5,5.7000000000000002,6.2999999999999998,4.9000000000000004,6.5999999999999996,5.2000000000000002,5,5.9000000000000004,6,6.0999999999999996,5.5999999999999996,6.7000000000000002,5.5999999999999996,5.7999999999999998,6.2000000000000002,5.5999999999999996,5.9000000000000004,6.0999999999999996,6.2999999999999998,6.0999999999999996,6.4000000000000004,6.5999999999999996,6.7999999999999998,6.7000000000000002,6,5.7000000000000002,5.5,5.5,5.7999999999999998,6,5.4000000000000004,6,6.7000000000000002,6.2999999999999998,5.5999999999999996,5.5,5.5,6.0999999999999996,5.7999999999999998,5,5.5999999999999996,5.7000000000000002,5.7000000000000002,6.2000000000000002,5.0999999999999996,5.7000000000000002],"y":[4.7000000000000002,4.5,4.9000000000000004,4,4.5999999999999996,4.5,4.7000000000000002,3.2999999999999998,4.5999999999999996,3.8999999999999999,3.5,4.2000000000000002,4,4.7000000000000002,3.6000000000000001,4.4000000000000004,4.5,4.0999999999999996,4.5,3.8999999999999999,4.7999999999999998,4,4.9000000000000004,4.7000000000000002,4.2999999999999998,4.4000000000000004,4.7999999999999998,5,4.5,3.5,3.7999999999999998,3.7000000000000002,3.8999999999999999,5.0999999999999996,4.5,4.5,4.7000000000000002,4.4000000000000004,4.0999999999999996,4,4.4000000000000004,4.5999999999999996,4,3.2999999999999998,4.2000000000000002,4.2000000000000002,4.2000000000000002,4.2999999999999998,3,4.0999999999999996],"text":"versicolor","type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(0,186,56,1)","opacity":1,"size":5.6692913385826778,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(0,186,56,1)"}},"hoveron":"points","name":"versicolor","legendgroup":"versicolor","showlegend":true,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[6.2999999999999998,5.7999999999999998,7.0999999999999996,6.2999999999999998,6.5,7.5999999999999996,4.9000000000000004,7.2999999999999998,6.7000000000000002,7.2000000000000002,6.5,6.4000000000000004,6.7999999999999998,5.7000000000000002,5.7999999999999998,6.4000000000000004,6.5,7.7000000000000002,7.7000000000000002,6,6.9000000000000004,5.5999999999999996,7.7000000000000002,6.2999999999999998,6.7000000000000002,7.2000000000000002,6.2000000000000002,6.0999999999999996,6.4000000000000004,7.2000000000000002,7.4000000000000004,7.9000000000000004,6.4000000000000004,6.2999999999999998,6.0999999999999996,7.7000000000000002,6.2999999999999998,6.4000000000000004,6,6.9000000000000004,6.7000000000000002,6.9000000000000004,5.7999999999999998,6.7999999999999998,6.7000000000000002,6.7000000000000002,6.2999999999999998,6.5,6.2000000000000002,5.9000000000000004],"y":[6,5.0999999999999996,5.9000000000000004,5.5999999999999996,5.7999999999999998,6.5999999999999996,4.5,6.2999999999999998,5.7999999999999998,6.0999999999999996,5.0999999999999996,5.2999999999999998,5.5,5,5.0999999999999996,5.2999999999999998,5.5,6.7000000000000002,6.9000000000000004,5,5.7000000000000002,4.9000000000000004,6.7000000000000002,4.9000000000000004,5.7000000000000002,6,4.7999999999999998,4.9000000000000004,5.5999999999999996,5.7999999999999998,6.0999999999999996,6.4000000000000004,5.5999999999999996,5.0999999999999996,5.5999999999999996,6.0999999999999996,5.5999999999999996,5.5,4.7999999999999998,5.4000000000000004,5.5999999999999996,5.0999999999999996,5.0999999999999996,5.9000000000000004,5.7000000000000002,5.2000000000000002,5,5.2000000000000002,5.4000000000000004,5.0999999999999996],"text":"virginica","type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(97,156,255,1)","opacity":1,"size":5.6692913385826778,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(97,156,255,1)"}},"hoveron":"points","name":"virginica","legendgroup":"virginica","showlegend":true,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null}],"layout":{"margin":{"t":26.228310502283108,"r":7.3059360730593621,"b":40.182648401826498,"l":31.415525114155255},"plot_bgcolor":"rgba(235,235,235,1)","paper_bgcolor":"rgba(255,255,255,1)","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724},"xaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[4.1200000000000001,8.0800000000000001],"tickmode":"array","ticktext":["5","6","7","8"],"tickvals":[5,6,7,8],"categoryorder":"array","categoryarray":["5","6","7","8"],"nticks":null,"ticks":"outside","tickcolor":"rgba(51,51,51,1)","ticklen":3.6529680365296811,"tickwidth":0.66417600664176002,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":11.68949771689498},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(255,255,255,1)","gridwidth":0.66417600664176002,"zeroline":false,"anchor":"y","title":{"text":"Sepal.Length","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724}},"hoverformat":".2f"},"yaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[0.70499999999999996,7.1950000000000003],"tickmode":"array","ticktext":["2","4","6"],"tickvals":[2,4,6],"categoryorder":"array","categoryarray":["2","4","6"],"nticks":null,"ticks":"outside","tickcolor":"rgba(51,51,51,1)","ticklen":3.6529680365296811,"tickwidth":0.66417600664176002,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":11.68949771689498},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(255,255,255,1)","gridwidth":0.66417600664176002,"zeroline":false,"anchor":"x","title":{"text":"Petal.Length","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724}},"hoverformat":".2f"},"shapes":[{"type":"rect","fillcolor":null,"line":{"color":null,"width":0,"linetype":[]},"yref":"paper","xref":"paper","x0":0,"x1":1,"y0":0,"y1":1}],"showlegend":true,"legend":{"bgcolor":"rgba(255,255,255,1)","bordercolor":"transparent","borderwidth":1.8897637795275593,"font":{"color":"rgba(0,0,0,1)","family":"","size":11.68949771689498},"title":{"text":"Species","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724}}},"hovermode":"closest","barmode":"relative"},"config":{"doubleClick":"reset","modeBarButtonsToAdd":["hoverclosest","hovercompare"],"showSendToCloud":false},"source":"A","attrs":{"142691e96f6e8":{"x":{},"y":{},"colour":{},"text":{},"type":"scatter"}},"cur_data":"142691e96f6e8","visdat":{"142691e96f6e8":["function (y) ","x"]},"highlight":{"on":"plotly_click","persistent":false,"dynamic":false,"selectize":false,"opacityDim":0.20000000000000001,"selected":{"opacity":1},"debounce":0},"shinyEvents":["plotly_hover","plotly_click","plotly_selected","plotly_relayout","plotly_brushed","plotly_brushing","plotly_clickannotation","plotly_doubleclick","plotly_deselect","plotly_afterplot","plotly_sunburstclick"],"base_url":"https://plot.ly"},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>This already looks nice and clean. As can be seen <a href="https://plot.ly/r/hover-events/">in the plotly documentation</a>, a custom JavaScript function can be called when hovering over a point, and the tooltip text can be retrieved in this function. However, other than in the documentation, we do not need to change any html code or write long JavaScript code; using the <code>htmltools::onRender</code> function we can inject a custom JavaScript function into the generated plot.<br>
In this example, I chose to store the images locally, but one can also use base64 objects like in the documentation to make it even more portable.</p>
<p>We define a function that takes a plotly element and calls another function when hovering over this element. The point’s tooltip can be retrieved with <code>d.points[0].data.text</code>. Since we made this nice and clean, this is the corresponding plant’s species as a string. Locally, I have stored the images in the folder corresponding to this blogpost, with filenames <code>setosa.jpg</code>, <code>virginica.jpg</code> and <code>versicolor.jpg</code>. The path to the correct image is constructed and assigned to the <code>image_location</code> variable.<br>
Next, we define an object which points to the correct image and defines the position and the size we want the image to take.<br>
Finally, by calling <code>Plotly.relayout</code> the new layout is applied in which we attach this image object in the layout’s <code>images</code> attribute.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">p <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> htmlwidgets<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">onRender</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb3-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    function(el, x) {</span></span>
<span id="cb3-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">      // when hovering over an element, do something</span></span>
<span id="cb3-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">      el.on('plotly_hover', function(d) {</span></span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        // extract tooltip text</span></span>
<span id="cb3-7"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        txt = d.points[0].data.text;</span></span>
<span id="cb3-8"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        // image is stored locally</span></span>
<span id="cb3-9"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        image_location = '../2018-10-28-showing-images-on-hover-in-plotly-with-r/' + txt + '.jpg';</span></span>
<span id="cb3-10"></span>
<span id="cb3-11"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        // define image to be shown</span></span>
<span id="cb3-12"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        var img = {</span></span>
<span id="cb3-13"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">          // location of image</span></span>
<span id="cb3-14"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">          source: image_location,</span></span>
<span id="cb3-15"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">          // top-left corner</span></span>
<span id="cb3-16"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">          x: 0,</span></span>
<span id="cb3-17"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">          y: 1,</span></span>
<span id="cb3-18"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">          sizex: 0.2,</span></span>
<span id="cb3-19"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">          sizey: 0.2,</span></span>
<span id="cb3-20"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">          xref: 'paper',</span></span>
<span id="cb3-21"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">          yref: 'paper'</span></span>
<span id="cb3-22"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        };</span></span>
<span id="cb3-23"></span>
<span id="cb3-24"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        // show image and annotation </span></span>
<span id="cb3-25"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        Plotly.relayout(el.id, {</span></span>
<span id="cb3-26"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            images: [img] </span></span>
<span id="cb3-27"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">        });</span></span>
<span id="cb3-28"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">      })</span></span>
<span id="cb3-29"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    }</span></span>
<span id="cb3-30"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">    "</span>)</span></code></pre></div>
<div class="cell-output-display">
<div class="plotly html-widget html-fill-item" id="htmlwidget-2e93481df4560ab215f9" style="width:100%;height:464px;"></div>
<script type="application/json" data-for="htmlwidget-2e93481df4560ab215f9">{"x":{"data":[{"x":[5.0999999999999996,4.9000000000000004,4.7000000000000002,4.5999999999999996,5,5.4000000000000004,4.5999999999999996,5,4.4000000000000004,4.9000000000000004,5.4000000000000004,4.7999999999999998,4.7999999999999998,4.2999999999999998,5.7999999999999998,5.7000000000000002,5.4000000000000004,5.0999999999999996,5.7000000000000002,5.0999999999999996,5.4000000000000004,5.0999999999999996,4.5999999999999996,5.0999999999999996,4.7999999999999998,5,5,5.2000000000000002,5.2000000000000002,4.7000000000000002,4.7999999999999998,5.4000000000000004,5.2000000000000002,5.5,4.9000000000000004,5,5.5,4.9000000000000004,4.4000000000000004,5.0999999999999996,5,4.5,4.4000000000000004,5,5.0999999999999996,4.7999999999999998,5.0999999999999996,4.5999999999999996,5.2999999999999998,5],"y":[1.3999999999999999,1.3999999999999999,1.3,1.5,1.3999999999999999,1.7,1.3999999999999999,1.5,1.3999999999999999,1.5,1.5,1.6000000000000001,1.3999999999999999,1.1000000000000001,1.2,1.5,1.3,1.3999999999999999,1.7,1.5,1.7,1.5,1,1.7,1.8999999999999999,1.6000000000000001,1.6000000000000001,1.5,1.3999999999999999,1.6000000000000001,1.6000000000000001,1.5,1.5,1.3999999999999999,1.5,1.2,1.3,1.3999999999999999,1.3,1.5,1.3,1.3,1.3,1.6000000000000001,1.8999999999999999,1.3999999999999999,1.6000000000000001,1.3999999999999999,1.5,1.3999999999999999],"text":"setosa","type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(248,118,109,1)","opacity":1,"size":5.6692913385826778,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(248,118,109,1)"}},"hoveron":"points","name":"setosa","legendgroup":"setosa","showlegend":true,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[7,6.4000000000000004,6.9000000000000004,5.5,6.5,5.7000000000000002,6.2999999999999998,4.9000000000000004,6.5999999999999996,5.2000000000000002,5,5.9000000000000004,6,6.0999999999999996,5.5999999999999996,6.7000000000000002,5.5999999999999996,5.7999999999999998,6.2000000000000002,5.5999999999999996,5.9000000000000004,6.0999999999999996,6.2999999999999998,6.0999999999999996,6.4000000000000004,6.5999999999999996,6.7999999999999998,6.7000000000000002,6,5.7000000000000002,5.5,5.5,5.7999999999999998,6,5.4000000000000004,6,6.7000000000000002,6.2999999999999998,5.5999999999999996,5.5,5.5,6.0999999999999996,5.7999999999999998,5,5.5999999999999996,5.7000000000000002,5.7000000000000002,6.2000000000000002,5.0999999999999996,5.7000000000000002],"y":[4.7000000000000002,4.5,4.9000000000000004,4,4.5999999999999996,4.5,4.7000000000000002,3.2999999999999998,4.5999999999999996,3.8999999999999999,3.5,4.2000000000000002,4,4.7000000000000002,3.6000000000000001,4.4000000000000004,4.5,4.0999999999999996,4.5,3.8999999999999999,4.7999999999999998,4,4.9000000000000004,4.7000000000000002,4.2999999999999998,4.4000000000000004,4.7999999999999998,5,4.5,3.5,3.7999999999999998,3.7000000000000002,3.8999999999999999,5.0999999999999996,4.5,4.5,4.7000000000000002,4.4000000000000004,4.0999999999999996,4,4.4000000000000004,4.5999999999999996,4,3.2999999999999998,4.2000000000000002,4.2000000000000002,4.2000000000000002,4.2999999999999998,3,4.0999999999999996],"text":"versicolor","type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(0,186,56,1)","opacity":1,"size":5.6692913385826778,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(0,186,56,1)"}},"hoveron":"points","name":"versicolor","legendgroup":"versicolor","showlegend":true,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[6.2999999999999998,5.7999999999999998,7.0999999999999996,6.2999999999999998,6.5,7.5999999999999996,4.9000000000000004,7.2999999999999998,6.7000000000000002,7.2000000000000002,6.5,6.4000000000000004,6.7999999999999998,5.7000000000000002,5.7999999999999998,6.4000000000000004,6.5,7.7000000000000002,7.7000000000000002,6,6.9000000000000004,5.5999999999999996,7.7000000000000002,6.2999999999999998,6.7000000000000002,7.2000000000000002,6.2000000000000002,6.0999999999999996,6.4000000000000004,7.2000000000000002,7.4000000000000004,7.9000000000000004,6.4000000000000004,6.2999999999999998,6.0999999999999996,7.7000000000000002,6.2999999999999998,6.4000000000000004,6,6.9000000000000004,6.7000000000000002,6.9000000000000004,5.7999999999999998,6.7999999999999998,6.7000000000000002,6.7000000000000002,6.2999999999999998,6.5,6.2000000000000002,5.9000000000000004],"y":[6,5.0999999999999996,5.9000000000000004,5.5999999999999996,5.7999999999999998,6.5999999999999996,4.5,6.2999999999999998,5.7999999999999998,6.0999999999999996,5.0999999999999996,5.2999999999999998,5.5,5,5.0999999999999996,5.2999999999999998,5.5,6.7000000000000002,6.9000000000000004,5,5.7000000000000002,4.9000000000000004,6.7000000000000002,4.9000000000000004,5.7000000000000002,6,4.7999999999999998,4.9000000000000004,5.5999999999999996,5.7999999999999998,6.0999999999999996,6.4000000000000004,5.5999999999999996,5.0999999999999996,5.5999999999999996,6.0999999999999996,5.5999999999999996,5.5,4.7999999999999998,5.4000000000000004,5.5999999999999996,5.0999999999999996,5.0999999999999996,5.9000000000000004,5.7000000000000002,5.2000000000000002,5,5.2000000000000002,5.4000000000000004,5.0999999999999996],"text":"virginica","type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(97,156,255,1)","opacity":1,"size":5.6692913385826778,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(97,156,255,1)"}},"hoveron":"points","name":"virginica","legendgroup":"virginica","showlegend":true,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null}],"layout":{"margin":{"t":26.228310502283108,"r":7.3059360730593621,"b":40.182648401826498,"l":31.415525114155255},"plot_bgcolor":"rgba(235,235,235,1)","paper_bgcolor":"rgba(255,255,255,1)","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724},"xaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[4.1200000000000001,8.0800000000000001],"tickmode":"array","ticktext":["5","6","7","8"],"tickvals":[5,6,7,8],"categoryorder":"array","categoryarray":["5","6","7","8"],"nticks":null,"ticks":"outside","tickcolor":"rgba(51,51,51,1)","ticklen":3.6529680365296811,"tickwidth":0.66417600664176002,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":11.68949771689498},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(255,255,255,1)","gridwidth":0.66417600664176002,"zeroline":false,"anchor":"y","title":{"text":"Sepal.Length","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724}},"hoverformat":".2f"},"yaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[0.70499999999999996,7.1950000000000003],"tickmode":"array","ticktext":["2","4","6"],"tickvals":[2,4,6],"categoryorder":"array","categoryarray":["2","4","6"],"nticks":null,"ticks":"outside","tickcolor":"rgba(51,51,51,1)","ticklen":3.6529680365296811,"tickwidth":0.66417600664176002,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":11.68949771689498},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(255,255,255,1)","gridwidth":0.66417600664176002,"zeroline":false,"anchor":"x","title":{"text":"Petal.Length","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724}},"hoverformat":".2f"},"shapes":[{"type":"rect","fillcolor":null,"line":{"color":null,"width":0,"linetype":[]},"yref":"paper","xref":"paper","x0":0,"x1":1,"y0":0,"y1":1}],"showlegend":true,"legend":{"bgcolor":"rgba(255,255,255,1)","bordercolor":"transparent","borderwidth":1.8897637795275593,"font":{"color":"rgba(0,0,0,1)","family":"","size":11.68949771689498},"title":{"text":"Species","font":{"color":"rgba(0,0,0,1)","family":"","size":14.611872146118724}}},"hovermode":"closest","barmode":"relative"},"config":{"doubleClick":"reset","modeBarButtonsToAdd":["hoverclosest","hovercompare"],"showSendToCloud":false},"source":"A","attrs":{"142691e96f6e8":{"x":{},"y":{},"colour":{},"text":{},"type":"scatter"}},"cur_data":"142691e96f6e8","visdat":{"142691e96f6e8":["function (y) ","x"]},"highlight":{"on":"plotly_click","persistent":false,"dynamic":false,"selectize":false,"opacityDim":0.20000000000000001,"selected":{"opacity":1},"debounce":0},"shinyEvents":["plotly_hover","plotly_click","plotly_selected","plotly_relayout","plotly_brushed","plotly_brushing","plotly_clickannotation","plotly_doubleclick","plotly_deselect","plotly_afterplot","plotly_sunburstclick"],"base_url":"https://plot.ly"},"evals":[],"jsHooks":{"render":[{"code":"\n    function(el, x) {\n      // when hovering over an element, do something\n      el.on('plotly_hover', function(d) {\n\n        // extract tooltip text\n        txt = d.points[0].data.text;\n        // image is stored locally\n        image_location = '../2018-10-28-showing-images-on-hover-in-plotly-with-r/' + txt + '.jpg';\n\n        // define image to be shown\n        var img = {\n          // location of image\n          source: image_location,\n          // top-left corner\n          x: 0,\n          y: 1,\n          sizex: 0.2,\n          sizey: 0.2,\n          xref: 'paper',\n          yref: 'paper'\n        };\n\n        // show image and annotation \n        Plotly.relayout(el.id, {\n            images: [img] \n        });\n      })\n    }\n    ","data":null}]}}</script>
</div>
</div>
<p>Tada! Hovering over a point now shows an image of the corresponding species in the top-left corner. Instead of an image, text can also be shown by adding a <code>text</code> attribute to the <code>var img</code> definition and adding <code>annotations: [img]</code> to the <code>Plotly.relayout</code> function.</p>
<p>This visualisation can now be exported to html with <code>htmltools::saveWidget()</code> and shared with anyone, the recipient does not need not have <code>R</code> installed. Do make sure to also share the folder with the images though, since these are not embedded.</p>



 ]]></description>
  <guid>https://www.basjacobs.com/post/2018-10-28-showing-images-on-hover-in-plotly-with-r/</guid>
  <pubDate>Sat, 27 Oct 2018 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Learning image representation with Keras in R</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2018-09-20-image-approximation-with-keras-in-r/</link>
  <description><![CDATA[ 





<p>An image can be viewed as a function mapping pixel locations <img src="https://latex.codecogs.com/png.latex?x,y"> to color values <img src="https://latex.codecogs.com/png.latex?R,G,B">. Since neural networks are function approximators, we can train such a network to approximate an image. The network is then a representation of the image as a function and its contents can be displayed by evaluating the network for all pixel pairs <img src="https://latex.codecogs.com/png.latex?x,y">.</p>
<p>The <code>Keras</code> package for <code>R</code> is now approximately <a href="https://blog.rstudio.com/2017/09/05/keras-for-r/">1 year old</a> but I have to admit that I usually go to Python to implement neural networks. Since I wanted to try the <code>imager</code> package for <code>R</code> for a while, let’s hit two birds with one stone and do this exercise in <code>R</code>.</p>
<p>First, we need the right packages.</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(keras)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(imager)</span></code></pre></div>
<p>To honour the name of this blog, let’s pick an image of the bird species godwit (scientific name: <em>limosa</em>) and load it using <code>imager</code>’s <code>load.image</code>.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Image from Pixabay</span></span>
<span id="cb2-2">im_url <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.pixabay.com/photo/2015/09/18/00/13/bar-tailed-godwit-944883_640.jpg"</span></span>
<span id="cb2-3">im <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load.image</span>(im_url)</span>
<span id="cb2-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(im)</span></code></pre></div>
<pre><code>## [1] 640 480   1   3</code></pre>
<p>The image is 640x480 pixels in size, consists of 1 frame (it is not a video) and 3 color channels. Plotting the image is easy. We choose to show the image without axes and make the margins small for aestetic reasons.</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(im, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axes =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span></code></pre></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-09-20-image-approximation-with-keras-in-r/image.png" class="img-fluid figure-img" width="600"></p>
<figcaption>A godwit. Source: pixabay.com</figcaption>
</figure>
</div>
<p>We convert the image to a data frame by calling <code>as.data.frame</code> on the image object. This data frame by default has 4 columns: an <em>x</em> and <em>y</em> column to identify each pixel’s location, a color channel column <em>cc</em>, and the <em>value</em> this channel takes at this pixel. We spread the key-value pairs in the <em>cc</em> and <em>value</em> columns into columns <em>cc_1</em>, <em>cc_2</em>, <em>cc_3</em> representing the three color values.</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> im <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> as.data.frame <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spread</span>(cc, value)</span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(df)</span></code></pre></div>
<pre><code>##   x y         1         2         3
## 1 1 1 0.8117647 0.8941176 0.9607843
## 2 1 2 0.8117647 0.8941176 0.9607843
## 3 1 3 0.8117647 0.8941176 0.9607843
## 4 1 4 0.8117647 0.8980392 0.9529412
## 5 1 5 0.8196078 0.8941176 0.9529412
## 6 1 6 0.8117647 0.8862745 0.9450980</code></pre>
<p>The color values are between 0 (absent) and 1 (present). We create input and output matrices which can be fed into keras.</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">X <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(df, x, y))</span>
<span id="cb7-2">Y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">select</span>(df, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>x, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>y))</span></code></pre></div>
<p>Creating a neural network with keras is very easy. We tell it that we want an ‘ordinary’ feed forward neural network with <code>keras_model_sequential()</code>. For starters, we create a one-layer network with 2 input nodes (<em>x</em> and <em>y</em> coordinates) and 3 output nodes (<em>R</em>, <em>G</em>, <em>B</em> values). We choose a ‘sigmoid’ activation function because we want the output values to be between 0 and 1.</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1">model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">keras_model_sequential</span>()</span>
<span id="cb8-2">model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb8-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_shape =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigmoid"</span>)</span>
<span id="cb8-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">summary</span>(model)</span></code></pre></div>
<pre><code>## ___________________________________________________________________________
## Layer (type)                     Output Shape                  Param #
## ===========================================================================
## dense_1 (Dense)                  (None, 3)                     9
## ===========================================================================
## Total params: 9
## Trainable params: 9
## Non-trainable params: 0
## ___________________________________________________________________________</code></pre>
<p>When compiling the model, we tell it what loss function we need, what optimizer and what kind of metrics we want it to display while training. We choose a <em>mean_squared_error</em> loss, which means that we penalize every color channel equally, taking the square of the error for every channel and every pixel. We optimize the network using the widely used Adam optimizer and we want to see its accuracy while training.</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1">model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compile</span>(</span>
<span id="cb10-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">loss =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean_squared_error"</span>,</span>
<span id="cb10-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">optimizer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optimizer_adam</span>(),</span>
<span id="cb10-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metrics =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"accuracy"</span></span>
<span id="cb10-5">)</span></code></pre></div>
<p>Next, we actually fit the model, giving it the expected input and output matrices <em>X</em> and <em>Y</em>. We set the batch size to 128 such that training is faster than the default 32. We train the network for 20 epochs.</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fit</span>(</span>
<span id="cb11-2">  X, Y,</span>
<span id="cb11-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>,</span>
<span id="cb11-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">epochs =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span></span>
<span id="cb11-5">)</span></code></pre></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-09-20-image-approximation-with-keras-in-r/trainplot.png" class="img-fluid figure-img"></p>
<figcaption>Training progress</figcaption>
</figure>
</div>
<p>Training takes about 1 minute, and as can be seen from the training plot, it seems that both the loss and the accuracy have saturated. An accuracy of 0.9 sounds good, but let’s take a look at the output image before we get too happy. First, we need to recreate the original dataframe with the predicted pixel values. For every <img src="https://latex.codecogs.com/png.latex?(x,y)"> pair in our matrix <em>X</em> we need to make a prediction. We duplicate the original dataframe fill the color channel columns with the network’s output values. We then call <code>gather</code> on this dataframe to create the <em>cc</em> and <em>value</em> columns necessary for the <code>imager</code> library.</p>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1">df_out <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df</span>
<span id="cb12-2">df_out[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(X)</span>
<span id="cb12-3">df_out <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df_out <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb12-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gather</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">key =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cc"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>x, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">convert =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div>
<p>With the data frame in the right form, we can display the result next to the original image very easily. We convert the data frame to an image with the <code>as.cimg</code> function and paste it next to the original image by wrapping them inside a list and calling <code>imappend</code> on it, specifying we want them appended on the horizontal axis.</p>
<div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb13-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.cimg</span>(df_out) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(im, .) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb13-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">imappend</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axes =</span> F)</span></code></pre></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-09-20-image-approximation-with-keras-in-r/model1.png" class="img-fluid figure-img" width="600"></p>
<figcaption>The network learned a gradient</figcaption>
</figure>
</div>
<p>The result is a vertical gradient, which can also be seen when looking at the model weights.</p>
<div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1">model<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">get_weights</span>()</span></code></pre></div>
<pre><code>## [[1]]
##              [,1]         [,2]         [,3]
## [1,]  0.000755751  0.001207316  0.001467007
## [2,] -0.002216082 -0.004577803 -0.006758745
##
## [[2]]
## [1] 1.460977 2.029516 2.619324</code></pre>
<p>The values corresponding to the <em>x</em> column are positive, while the <em>y</em> values are negative and about one order of magnitute larger.</p>
<section id="more-layers" class="level1">
<h1>More layers</h1>
<p>Now let’s try a network with more layers. More specifically, let’s add two layers with both 10 nodes followed by sigmoid activations.</p>
<div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb16-1">model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">keras_model_sequential</span>()</span>
<span id="cb16-2">model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb16-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_shape =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigmoid"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb16-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigmoid"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb16-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigmoid"</span>)</span>
<span id="cb16-6"></span>
<span id="cb16-7">model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compile</span>(</span>
<span id="cb16-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">loss =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean_squared_error"</span>,</span>
<span id="cb16-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">optimizer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optimizer_adam</span>(),</span>
<span id="cb16-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metrics =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"accuracy"</span></span>
<span id="cb16-11">)</span>
<span id="cb16-12"></span>
<span id="cb16-13">model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fit</span>(</span>
<span id="cb16-14">  X, Y,</span>
<span id="cb16-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>,</span>
<span id="cb16-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">epochs =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span></span>
<span id="cb16-17">)</span>
<span id="cb16-18"></span>
<span id="cb16-19">df_out <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df</span>
<span id="cb16-20">df_out[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(X)</span>
<span id="cb16-21">df_out <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df_out <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb16-22">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gather</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">key =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cc"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>x, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">convert =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb16-23"></span>
<span id="cb16-24"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.cimg</span>(df_out) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(im, .) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb16-25">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">imappend</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axes =</span> F)</span></code></pre></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-09-20-image-approximation-with-keras-in-r/model2.png" class="img-fluid figure-img" width="600"></p>
<figcaption>Some features of the bird appear</figcaption>
</figure>
</div>
<p>As can be seen, the image is already picking up some countours of the bird, together with some ‘rays’ coming from the top-left corner. If we go for an even deeper network, more of the bird’s features can be recognized from the image.</p>
<div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1">model <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">keras_model_sequential</span>()</span>
<span id="cb17-2">model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb17-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">input_shape =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tanh"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb17-4">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"relu"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb17-5">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"relu"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb17-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"relu"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb17-7">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">activation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"relu"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb17-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_dense</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb17-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">layer_activation_relu</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">max_value=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb17-10"></span>
<span id="cb17-11">model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">compile</span>(</span>
<span id="cb17-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">loss =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean_squared_error"</span>,</span>
<span id="cb17-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">optimizer =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">optimizer_adam</span>(),</span>
<span id="cb17-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">metrics =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"accuracy"</span></span>
<span id="cb17-15">)</span>
<span id="cb17-16"></span>
<span id="cb17-17">model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fit</span>(</span>
<span id="cb17-18">  X, Y,</span>
<span id="cb17-19">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">batch_size =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>,</span>
<span id="cb17-20">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">epochs =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb17-21">)</span>
<span id="cb17-22"></span>
<span id="cb17-23">df_out <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df</span>
<span id="cb17-24">df_out[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> model <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">predict</span>(X)</span>
<span id="cb17-25">df_out <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> df_out <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb17-26">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gather</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">key =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cc"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>x, <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">convert =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb17-27"></span>
<span id="cb17-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.cimg</span>(df_out) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(im, .) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span></span>
<span id="cb17-29">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">imappend</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">axes=</span>F)</span></code></pre></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-09-20-image-approximation-with-keras-in-r/model3.png" class="img-fluid figure-img" width="600"></p>
<figcaption>The image is nicely recovered</figcaption>
</figure>
</div>
<p>Ways to improve this might include more layers, more epochs, different activation functions, different loss function. For now, I’m really happy with the result!</p>


</section>

 ]]></description>
  <guid>https://www.basjacobs.com/post/2018-09-20-image-approximation-with-keras-in-r/</guid>
  <pubDate>Wed, 19 Sep 2018 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Generating the logo for this site</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2018-07-15-generating-the-logo-for-this-site/</link>
  <description><![CDATA[ 





<p>I wanted a logo for my blog. Something kind of personal, but abstract; preferably something that could be drawn with a single path. I decided to download an elevation map of the Netherlands (where I live) to somehow use a plot of that data as my logo. I thought it would be nice to generate a side view and smooth it. In this short post I will discuss how I did it.</p>
<section id="the-data" class="level1">
<h1>The data</h1>
<p>The Netherlands have an open database containing elevation data for the whole country. It is called <em>Actueel Hoogtebestand Nederland</em> (Current Elevation database Netherlands) and can be <a href="http://www.ahn.nl/common-nlm/viewer.html">viewed online</a>. On average, it contains eight height measurements per square meter. The measurements are made using aircraft with LiDAR technology. Measuring the entire country takes sevaral years. In particular, I used the database called AHN2, which contains measurements made from 2007 to 2012. According to the website, 99.7% of the measured points are accurate up to 20 cm.<br>
In the database, the country is divided into a grid of around 1300 cells, each having dimensions of 5x6.25 kilometers. For every cell, the measurements can be downloaded as a zipped GeoTIFF file of around 500 KB. Links to these files can be found in an <a href="http://geodata.nationaalgeoregister.nl/ahn2/atom/ahn2_5m.xml">Atom feed</a>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-07-15-generating-the-logo-for-this-site/ahn.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Dividing the Netherlands into around 1100 cells</figcaption>
</figure>
</div>
</section>
<section id="the-code" class="level1">
<h1>The code</h1>
<p>Obtaining the links to all cells is as easy as reading the contents of the Atom feed and extracting all URLs from it. I chose to extract the URLs using a simple regular expression. Note that in <code>R</code> you need to escape the backslash with another backslash.</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(tidyverse)</span>
<span id="cb1-2">feed <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read_file</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"http://geodata.nationaalgeoregister.nl/ahn2/atom/ahn2_5m.xml"</span>)</span>
<span id="cb1-3">links <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">str_extract_all</span>(feed, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"http[:/.</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">w]+</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">.zip"</span>)[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%&gt;%</span> unique</span></code></pre></div>
<p>This results in a vector of 1373 URLs.<br>
For every <code>url</code> in this <code>links</code> vector, I download its contents into a temporary file, unzip it, read it into memory as a GDAL object, take its maximum over an axis and remove the temporary file again.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(rgdal)</span>
<span id="cb2-2"></span>
<span id="cb2-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create temporary folder to store the files in  </span></span>
<span id="cb2-4">temp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tempfile</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fileext =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".zip"</span>)</span>
<span id="cb2-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Download the file and unzip it</span></span>
<span id="cb2-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">download.file</span>(url, temp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quiet =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb2-7"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unzip</span>(temp)</span>
<span id="cb2-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Obtain .tif files contained in .zip</span></span>
<span id="cb2-9">shp <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dir</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tempdir</span>(), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*.tif$"</span>)</span>
<span id="cb2-10"></span>
<span id="cb2-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Convert to GDAL and project onto axis</span></span>
<span id="cb2-12">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">readGDAL</span>(shp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">silent =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb2-13">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">project</span>(y, axis)</span>
<span id="cb2-14"></span>
<span id="cb2-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Remove temporary files</span></span>
<span id="cb2-16"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">file.remove</span>(temp)</span>
<span id="cb2-17"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">file.remove</span>(shp)</span></code></pre></div>
<p>I wrap this into a function and run it for every url using <code>plyr::llply()</code>. I like to use <code>llply</code> because it has a progress bar functionality that I find useful when scraping. I set <code>axis</code> to 2, which means that I take the maximum value over the rows (longitude). In the end, obtain a data frame with 1250 values for every cell (6250 meter cell size, 5 measurements per meter). Since there are multiple cells within a row, I have to group this data frame by latitude and take the maximum over each group to get to the plottable result.<br>
Plotting is now an easy task using <code>ggplot</code>.</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> elevation)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_line</span>() <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>()</span></code></pre></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-07-15-generating-the-logo-for-this-site/sideview.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Sideview of the Netherlands</figcaption>
</figure>
</div>
<p>This plot displays the country as if we were standing in Germany and looking at the Netherlands without the ability to see perspective. There are some weird values here and there, but overall it looks like can be expected. It is too rough to use as a logo; we should apply some smoothing to make it prettier.<br>
Smoothing can be done in <code>ggplot</code> by simply replacing <code>geom_line</code> with <code>geom_smooth</code>. Under the hood, this is using using cubic regression splines to smooth the values. This yields a pretty picture better suited for using as a logo.</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(df, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x =</span> x, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> elevation)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_smooth</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">se =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb4-3">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>()</span></code></pre></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-07-15-generating-the-logo-for-this-site/sideview_smooth.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Sideview of the Netherlands when squinting</figcaption>
</figure>
</div>
</section>
<section id="conclusion" class="level1">
<h1>Conclusion</h1>
<p>That’s it! Once you have an idea, creating your own logo can be a couple of lines of code away.<br>
The complete <code>R</code> code used can be viewed on my <a href="https://github.com/basjacobs93/limosalogo">Github</a>.</p>


</section>

 ]]></description>
  <guid>https://www.basjacobs.com/post/2018-07-15-generating-the-logo-for-this-site/</guid>
  <pubDate>Sat, 14 Jul 2018 22:00:00 GMT</pubDate>
</item>
<item>
  <title>Pen plotter</title>
  <dc:creator>Bas </dc:creator>
  <link>https://www.basjacobs.com/post/2018-06-28-pen-plotter/</link>
  <description><![CDATA[ 





<p>Inspired by <a href="http://www.tobiastoft.com/posts/an-intro-to-pen-plotters">this</a> blog post, I got interested in pen plotters and computer generated art. I liked the minimalist pieces of art a plotter could create, resembling a human hand doodling on a piece of paper. A lot of examples of this art can be found on Twitter at <a href="https://twitter.com/hashtag/plottertwitter">#plottertwitter</a>. By far the most used plotter on Twitter is the <a href="https://www.axidraw.com/">AxiDraw</a>, but since I didn’t want to spend over 400 euros and I liked the prospect of assembling something myself, I decided to buy the <a href="http://eleksmaker.com/nav/eleksdraw/">EleksDraw</a> which was around 100 euros and came completely unassembled. In this blog post, I am summarising the steps I took to go from a box with nuts and bolts to some nice drawings on paper, hopefully inspiring you to try this out as well. Most of the code used can be found on <a href="https://github.com/basjacobs93/plotter">my GitHub</a>. Note that I wrote this code for myself, so please only use it as a reference and don’t use it without understanding what is going on.</p>
<section id="buying-and-assembling" class="level1">
<h1>Buying and assembling</h1>
<p>I ordered the EleksDraw from BangGood, which means that the product came from China and took around 3 weeks to arrive. It came in more than a hundred pieces and assembling it took me a couple of hours. The instructions on the website were just clear enough; they consisted of just a series of pictures with no text.</p>
<p>The EleksDraw consists of an arm that is connected via a cable to two motors which together can move the arm in the x and y direction. You can mount any pen or pencil to it which is held in place by a screw. After assembling it and hooking it up to my computer, I downloaded the EleksMaker software that can be used to convert an image to commands that this plotter can interpret. However, this software only works on Windows (I’m on a MacBook), and even after booting into Windows, it did not work as it should. Most of the menus didn’t show any text and when loading an image, I got an error that I couldn’t understand because it was in Chinese. I decided to boot back into MacOS and create some software myself. How hard could it be, right?</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-06-28-pen-plotter/plotter.jpg" class="img-fluid figure-img" width="600"></p>
<figcaption>The assembled EleksDraw should look a little something like this</figcaption>
</figure>
</div>
</section>
<section id="hello-world" class="level1">
<h1>Hello, World!</h1>
<p>The MacOS terminal has a <code>screen</code> command that allows you to send commands to an external device. In my case, typing <code>screen /dev/wchusbserial1420</code> connects with the EleksDraw and opens a terminal in which I could write commands. The language that this plotter understands is called G-code. With this code, you can give the device the following commands:</p>
<ul>
<li><code>S0 M5</code> lifts the pen</li>
<li><code>S1000 M3</code> lowers the pen</li>
<li><code>G01 Xa Yb</code> moves to position (a,b)</li>
</ul>
<p>Note that G-code has many variants, so the above commands may not be exactly the same for other pen plotters. Weirdly, the plotter’s <code>(0,0)</code> position was in the top right corner, so I had to make all the coordinates negative to get it to work properly. Could be because I somehow wired it wrong, but I could not figure it out. Anyway, writing my own software allowed me to work around this very easily! Writing these instructions one by one, I could create all kinds of shapes consisting of straight lines. After every command I wrote, the device would either send back the message <code>ok</code> or an error. After this response, I could send it a new instruction. However, I wanted to automatically generate these commands and send them to the device using a script.</p>
<section id="plotter-meets-python" class="level2">
<h2 class="anchored" data-anchor-id="plotter-meets-python">Plotter meets Python</h2>
<p>Using the Python package <a href="https://github.com/pyserial/pyserial">pySerial</a>, I was able to send commands to the plotter through just a couple of lines of code (see <a href="https://github.com/grbl/grbl/blob/master/doc/script/simple_stream.py">here</a>):</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Open serial port</span></span>
<span id="cb1-2">s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> serial.Serial(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/dev/wchusbserial1420'</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">115200</span>)</span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Wake up</span></span>
<span id="cb1-5">s.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\r\n\r\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb1-6">time.sleep(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># wait for grbl to initialize</span></span>
<span id="cb1-7">s.flushInput()      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># flush startup text in serial input</span></span>
<span id="cb1-8"></span>
<span id="cb1-9">s.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"G21</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># units = mm</span></span>
<span id="cb1-10">s.readline()</span>
<span id="cb1-11"></span>
<span id="cb1-12">s.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"F5000</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># speed = 5000 mm/min</span></span>
<span id="cb1-13">s.readline()</span>
<span id="cb1-14"></span>
<span id="cb1-15">s.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"S0 M5</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pen up</span></span>
<span id="cb1-16">s.readline()</span>
<span id="cb1-17"></span>
<span id="cb1-18">s.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"G01 X-10 Y-10</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># go to (10, 10)</span></span>
<span id="cb1-19">s.readline()</span>
<span id="cb1-20"></span>
<span id="cb1-21">s.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"S1000 M3</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pen down</span></span>
<span id="cb1-22">s.readline()</span>
<span id="cb1-23"></span>
<span id="cb1-24">s.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"G01 X-20 Y-10</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># go to (20, 10)</span></span>
<span id="cb1-25">s.readline()</span>
<span id="cb1-26"></span>
<span id="cb1-27">s.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"S0 M5</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pen up</span></span>
<span id="cb1-28">s.readline()</span></code></pre></div>
<p>This piece of code wakes up the plotter, raises the pen, moves to <code>(10, 10)</code> (note I wrote -10 for reasons described above), lowers the pen, moves to <code>(20, 10)</code> and finally raises the pen again. Effectively, this draws a straight line from <code>(10mm, 10mm)</code> to <code>(20mm, 10mm)</code>. Since I figured I would be needing this code more, I wrapped it in a function. I decided to go object-oriented and created classes <code>Point</code> and <code>Line</code>, respectively. For now, these classes only contained <code>draw</code> methods, but I knew more was going to be needed.</p>
</section>
</section>
<section id="plotting-svgs" class="level1">
<h1>Plotting SVGs</h1>
<p>Back to my original idea: I wanted to be able to load an image, convert it to G-code commands and send these commands to the plotter automatically. Using SVG images as input seemed like the right choice since these are vector graphics and hence should be easy to convert to G-code. First step: writing an SVG parser.</p>
<section id="lines-and-points" class="level2">
<h2 class="anchored" data-anchor-id="lines-and-points">Lines and points</h2>
<p>What seemed most intuitive to me was converting the SVG <code>&lt;path&gt;</code> element to G-code instructions. Such an element can contain various types of lines and curves that together create a connected (closed or open) path. A path like this can be constructed by tracing an image in a tool like Inkscape or Sketch. My final goal was to be able to plot Picasso’s drawing ‘Dog’, which could be traced with a single path.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-06-28-pen-plotter/picassodog.jpg" class="img-fluid figure-img" width="600"></p>
<figcaption>Dog (Picasso), pen on paper</figcaption>
</figure>
</div>
<p>An example of the SVG path syntax can be found on <a href="https://www.w3schools.com/graphics/svg_path.asp">w3schools</a>. It turned out that parsing such a path was straightforward with regular expressions. There were three things that made things slightly more complicated.</p>
<ol type="1">
<li>Different instructions can have different numbers of parameters. For example, the <code>M</code> command (move) takes two numbers (an x and y coordinate), the <code>Z</code> (close path) command takes zero parameters, and some curve commands can take up to 7 parameters.</li>
<li>A command letter does not need to be repeated. For example, <code>L 10 20 10 30</code> draws a line from the current position to <code>(10, 20)</code> and then another line to <code>(10, 30)</code> and is the same as <code>L 10 20 L 10 30</code>.</li>
<li>All commands can also be expressed with lower case letters, referring to relative instead of absolute positions. This requires a post processing step in which we keep track of the current position and add it if a relative position was supplied.</li>
</ol>
<p>All of these issues were relatively easy to overcome, and after implementing this, I was able to parse an SVG file into a table which I could then convert to G-code. The code for this parser can be found on my GitHub.</p>
</section>
<section id="bézier-curves" class="level2">
<h2 class="anchored" data-anchor-id="bézier-curves">Bézier curves</h2>
<p>Still, I had only created code for drawing points and lines. To plot arcs, I could of course interpolate these using points, but the results were what I expected them to be: not very pretty. G-code supports circle arcs (an arc obtained by tracing part of a circle), so a better way would be to try to approximate the curves using circle arcs. When tracing an image with a vector graphics tool like Sketch or Inkscape, the result will be a path consisting of <a href="https://en.wikipedia.org/wiki/B%C3%A9zier_curve">Bézier curves</a>. A Bézier curve is a parametric curve that can be described mathematically. I won’t go into more detail on Bézier curves; that is worth a blog post in itself. One thing that’s important to know is that there are quadratic and cubic Bézier curves. The quadratic curves are a special case of the cubic ones, so if I’m able to draw cubic Bézier curves I’m able to draw both.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-06-28-pen-plotter/cubic_bezier.png" class="img-fluid figure-img" width="600"></p>
<figcaption>A cubic Bézier curve is defined by 4 points (source: Wikipedia)</figcaption>
</figure>
</div>
<p>It is in general not possible to convert a Bézier curve to a combination of circle arcs, but there are ways that are ‘good enough’. In particular, I implemented <a href="http://dlacko.org/blog/2016/10/19/approximating-bezier-curves-by-biarcs/">this</a> approach in Python, which approximates a cubic Bézier curve with two circle arcs. I updated the classes for points and lines to include addition of points, multiplication of points with scalars, intersections of lines and so on. After these adjustments, it was relatively straightforward to write a <code>CubicBezier</code> class of which an instantiation could convert itself to two objects of class <code>CircleArc</code>. For debugging purposes, I gave every such class a method that could draw the corresponding shape on a PyGame canvas. That way, I had a way of testing if everything worked without having to go through stacks of paper. In the end, this also allowed me to check if the thing I was going to plot looked the way it should, before actually sending it to the EleksDraw. For example, find below the code for <code>Line</code>.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> plotter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb2-2"></span>
<span id="cb2-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Line():</span>
<span id="cb2-4">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a line is defined by 2 points</span></span>
<span id="cb2-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, point1, point2):</span>
<span id="cb2-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> point1</span>
<span id="cb2-7">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> point2</span>
<span id="cb2-8"></span>
<span id="cb2-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> intersect(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, line2):</span>
<span id="cb2-10">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># calculates the intersection point of the lines</span></span>
<span id="cb2-11">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># solution is based on simple algebra</span></span>
<span id="cb2-12">        a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P1.x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.x</span>
<span id="cb2-13">        b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P1.y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.y</span>
<span id="cb2-14"></span>
<span id="cb2-15">        u <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(line2.P2.y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.y) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> b<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(line2.P2.x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.x)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/\</span></span>
<span id="cb2-16">            (a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(line2.P2.y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>line2.P1.y) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> b<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>(line2.P2.x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>line2.P1.x))</span>
<span id="cb2-17"></span>
<span id="cb2-18">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (line2.P1.times(u)).plus(line2.P2.times(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>u))</span>
<span id="cb2-19"></span>
<span id="cb2-20">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> perpendicular_at(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, P):</span>
<span id="cb2-21">        U <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Point(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P1.y, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P1.x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.x)</span>
<span id="cb2-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Line(P, P.plus(U))</span>
<span id="cb2-23"></span>
<span id="cb2-24">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> draw(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, canvas, color):</span>
<span id="cb2-25">        pygame.draw.line(canvas, color,</span>
<span id="cb2-26">                         (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P1.x, canvas.get_height()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P1.y),</span>
<span id="cb2-27">                         (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.x, canvas.get_height()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.y))</span>
<span id="cb2-28"></span>
<span id="cb2-29">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_instructions(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb2-30">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># assumes we are at P1</span></span>
<span id="cb2-31">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [plt.move(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.x, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.P2.y)]</span></code></pre></div>
<p>After all this work, I was finally able to plot Picasso’s dog.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-06-28-pen-plotter/picassodog_plot.png" class="img-fluid figure-img" width="600"></p>
<figcaption>Dog (Picasso/EleksDraw), pen on paper</figcaption>
</figure>
</div>
</section>
</section>
<section id="drawing-a-harmonograph" class="level1">
<h1>Drawing a harmonograph</h1>
<p>Another <a href="https://aschinchon.wordpress.com/2014/10/13/beautiful-curves-the-harmonograph/">blog post</a> inspired me to try and plot some harmonographs. A harmonograph is a device that uses pendulums to draw trajectories on a piece of paper. The output of such a harmonograph can be described mathematically and we can simulate a random harmonograph by drawing random numbers and following a trajectory defined by sine waves. I followed the blog post mentioned above which draws 12 random numbers and plots the trajectory defined by</p>
<p><img src="https://latex.codecogs.com/png.latex?%20x(t)=e%5E%7B-d_1t%7D%5Csin(tf_1+p_1)+e%5E%7B-d_2t%7D%5Csin(tf_2+p_2)"> <img src="https://latex.codecogs.com/png.latex?y(t)=e%5E%7B-d_3t%7D%5Csin(tf_3+p_3)+e%5E%7B-d_4t%7D%5Csin(tf_4+p_4)"> where <img src="https://latex.codecogs.com/png.latex?t"> runs from <img src="https://latex.codecogs.com/png.latex?0"> to <img src="https://latex.codecogs.com/png.latex?1">. In his post, the author implemented the harmonograph in R, but since my plotter works from Python, I ported his code to Python.</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb3-2"></span>
<span id="cb3-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># draw the necessary random numbers</span></span>
<span id="cb3-4">f1, f2, f3, f4 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.randint(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (np.random.random(size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb3-5">d1, d2, d3, d4 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.uniform(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-02</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb3-6">p1, p2, p3, p4 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.uniform(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, np.pi, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb3-7"></span>
<span id="cb3-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># define the space and follow the trajectory</span></span>
<span id="cb3-9">t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.linspace(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, num <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb3-10">xs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> xt(t)</span>
<span id="cb3-11">ys <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> yt(t)</span></code></pre></div>
<p>After this, I could plot the curve by defining lines between subsequent points and sending the instructions to my plotter. Using the classes and functions I defined before, this was very easy:</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">objs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [shapes.Point(xs[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], ys[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+\</span></span>
<span id="cb4-2">  [shapes.Line(</span>
<span id="cb4-3">      shapes.Point(xs[i], ys[i]),</span>
<span id="cb4-4">      shapes.Point(xs[i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], ys[i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb4-5">   ) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(xs)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)]</span>
<span id="cb4-6"></span>
<span id="cb4-7">s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> wake_up_serial(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/dev/tty.wchusbserial1410'</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">115200</span>)</span>
<span id="cb4-8">objs_to_plotter(objs, s)</span></code></pre></div>
<p>Note that I started with a <code>Point</code> because the pen needs to move to the initial position before it can start drawing. If you look carefully, you can see that the figure was built up using small line segments. Increasing the number of steps in the <code>np.linspace</code> command above will make the result smoother. Nevertheless, I think the result looks very nice!</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.basjacobs.com/post/2018-06-28-pen-plotter/harmonograph.jpg" class="img-fluid figure-img" width="600"></p>
<figcaption>Harmonograph, pen on paper</figcaption>
</figure>
</div>
</section>
<section id="conclusion" class="level1">
<h1>Conclusion</h1>
<p>All in all, it was a nice journey. I never considered myself an artist, but now I kind of know what it feels like to be one, even though I did not design anything by hand. Someday, I want to learn <a href="https://processing.org/">Processing</a>, a programming language designed specifically for creating computer generated art.</p>


</section>

 ]]></description>
  <guid>https://www.basjacobs.com/post/2018-06-28-pen-plotter/</guid>
  <pubDate>Wed, 27 Jun 2018 22:00:00 GMT</pubDate>
</item>
</channel>
</rss>
