<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5337060275163361458</id><updated>2025-05-24T01:01:47.632+01:00</updated><category term="en"/><category term="pt"/><category term="mathematics"/><category term="twitter proof"/><category term="project"/><category term="machine learning"/><category term="programming"/><category term="python"/><category term="100daysofmlcode"/><category term="algorithms"/><category term="artificial intelligence"/><category term="construction"/><category term="pocket maths"/><category term="approximations"/><category term="games"/><category term="polynomials"/><category term="pygame"/><category term="counterintuitive"/><category term="graphs"/><category term="integers"/><category term="java"/><category term="markov"/><category term="number theory"/><category term="probability"/><category term="recursion"/><category term="reinforcement learning"/><category term="roots"/><category term="astronomy"/><category term="binary"/><category term="cardinality"/><category term="exponential"/><category term="geometry"/><category term="introduction"/><category term="intuition"/><category term="mazes"/><category term="mdp"/><category term="neural networks"/><category term="processing"/><category term="proof"/><category term="puzzle"/><category term="simulation"/><category term="stochastic"/><category term="tutorial"/><category term="visualization"/><category term="Newton&#39;s method"/><category term="algebraic topology"/><category term="asymptotics"/><category term="bet"/><category term="bfs"/><category term="binomial theorem"/><category term="bitwise operations"/><category term="brute force"/><category term="circuits"/><category term="combinatorics"/><category term="complex conjugate"/><category term="complex numbers"/><category term="computer vision"/><category term="continued fractions"/><category term="contradiction"/><category term="cryptography"/><category term="decision trees"/><category term="degree"/><category term="diophantine equations"/><category term="divisibility"/><category term="electronics"/><category term="equations"/><category term="equivalence relation"/><category term="fermat"/><category term="functions"/><category term="generating functions"/><category term="genetic algorithms"/><category term="groups"/><category term="hanoi"/><category term="homotopy"/><category term="induction"/><category term="infinity"/><category term="interpolation"/><category term="invariants"/><category term="irrationals"/><category term="limits"/><category term="logic"/><category term="matrices"/><category term="measure theory"/><category term="memory"/><category term="mental maths"/><category term="mnist"/><category term="modular arithmetics"/><category term="permutations"/><category term="pigeonhole principle"/><category term="primes"/><category term="random walks"/><category term="sequences"/><category term="series"/><category term="set theory"/><category term="squares"/><category term="sudoku"/><category term="surjective function"/><category term="symmetries"/><category term="topology"/><category term="trigonometry"/><category term="winding number"/><title type='text'>Mathspp: mathematics and programming</title><subtitle type='html'>This amazing blog is being migrated to &lt;a href=&quot;https://mathspp.com&quot;&gt;mathspp.com&lt;/a&gt;!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://mathspp.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Rodrigo Girão Serrão</name><uri>http://www.blogger.com/profile/15887398552525674427</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-2403277858053664065</id><published>2020-02-02T21:52:00.001+00:00</published><updated>2020-02-02T21:52:31.861+00:00</updated><title type='text'>New blog!!!</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

My blog is being migrated to &lt;a href=&quot;mathspp.com&quot;&gt;mathspp.com&lt;/a&gt;!!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

O meu blogue está a ser migrado para o meu novo site: &lt;a href=&quot;mathspp.com&quot;&gt;mathspp.com&lt;/a&gt;!!

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;!--&lt;div style=&quot;text-align:center; clear:both&quot;&gt;&lt;iframe src=&quot;https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fmathspp%2Fposts%2F857606641263037&amp;width=500&quot; width=&quot;500&quot; height=&quot;536&quot; style=&quot;border:none;overflow:hidden&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; allowTransparency=&quot;true&quot; allow=&quot;encrypted-media&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;--&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/2403277858053664065'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/2403277858053664065'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2020/02/new-blog.html' title='New blog!!!'/><author><name>Rodrigo Girão Serrão</name><uri>http://www.blogger.com/profile/15887398552525674427</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-990402937960554664</id><published>2019-03-16T22:28:00.001+00:00</published><updated>2019-03-18T20:48:58.495+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="algorithms"/><category scheme="http://www.blogger.com/atom/ns#" term="computer vision"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="machine learning"/><category scheme="http://www.blogger.com/atom/ns#" term="mnist"/><category scheme="http://www.blogger.com/atom/ns#" term="neural networks"/><category scheme="http://www.blogger.com/atom/ns#" term="project"/><title type='text'>Generating natural-looking digits with neural networks</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDBgLL8lt468zN-8plTWK4tUvkVMODUmrvf1LcQ5otpsmT-xsbHyZtwHT7ASJ-lJOKIOou7lVdwsK03_PKxblg46KAtL_ht-9Y9PVXIrohg-DRKy9JsTps7PVf2bDNJFHMUi3uaEwPN5E/s1600/digitpalette.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDBgLL8lt468zN-8plTWK4tUvkVMODUmrvf1LcQ5otpsmT-xsbHyZtwHT7ASJ-lJOKIOou7lVdwsK03_PKxblg46KAtL_ht-9Y9PVXIrohg-DRKy9JsTps7PVf2bDNJFHMUi3uaEwPN5E/s1600/digitpalette.png&quot; data-original-width=&quot;726&quot; data-original-height=&quot;73&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this post I will show you how I got a neural network to write digits that look like they&#39;ve been handwritten. In fact, the digits you can see in the first image of this post where generated by said neural network. The code that did all this is &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/NaturalDigitGeneration&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
It all started when I read, some time ago, about this funny way in which you could use neural networks: you are going to train a neural network to take a vector of size $N$ as input, and you are going to teach your network to do nothing. That is, you are going to teach your neural network to behave as the identity function... but with a twist! If your input size is $N$, somewhere in the middle of the network you want to have a layer with less than $N$ neurons! If this happens, you can think that your vector $x$ that is going in, first has to be squeezed through that tight layer, and then it expands again to be the output of the network.&lt;br /&gt;
&lt;br /&gt;
If now you slice your network in half, the part of the network from the input up until the &lt;i&gt;&quot;squeeze it tight&quot;&lt;/i&gt; part, compresses your inputs. The second half, from the &lt;i&gt;&quot;squeeze it tight&quot;&lt;/i&gt; part until the output, decompresses your data (for those of you interested in looking this up, I think the correct name for this network is &quot;encoder&quot;, but I am not sure).&lt;br /&gt;
&lt;br /&gt;
Let that sink in for a second.&lt;br /&gt;
Now that I &quot;know&quot; how to compress things, imagine this scenario: I teach a neural network to compress digit images into a vector of size $10$ (one component per existing digit), and let us call &lt;code&gt;encoder&lt;/code&gt; to this network. To train the &lt;code&gt;encoder&lt;/code&gt;, all I have to do is effectively teach the network to classify the images of the digits. After training the &lt;code&gt;encoder&lt;/code&gt;, I will create a new network (let&#39;s call it &lt;code&gt;decoder&lt;/code&gt;) that takes $10$ values as input, and returns an image as output. Now I will teach the &lt;code&gt;decoder&lt;/code&gt; to undo whatever the &lt;code&gt;encoder&lt;/code&gt; does.&lt;br /&gt;
&lt;br /&gt;
After doing that for a bit, say I take this image of a $2$:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6WWhj_CgUkS5yRuLY0ft_X746NV_-MDikxCqUivBOi052uA513iOmdRyhogsJooqjPhPAcfc1o1U8Rvea5LtRhZksirIbnmMBPCSZ4Tsp6vEF2MEIlnoGYN06DKd4WG9cOd3ucosfUec/s1600/natural_digits_pre_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6WWhj_CgUkS5yRuLY0ft_X746NV_-MDikxCqUivBOi052uA513iOmdRyhogsJooqjPhPAcfc1o1U8Rvea5LtRhZksirIbnmMBPCSZ4Tsp6vEF2MEIlnoGYN06DKd4WG9cOd3ucosfUec/s1600/natural_digits_pre_2.png&quot; data-original-width=&quot;197&quot; data-original-height=&quot;197&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
If I feed that image into my &lt;code&gt;encoder&lt;/code&gt;, this is what comes out:
&lt;pre&gt;&lt;code&gt;tensor([[-3.2723,  3.7296,  9.6557,  4.9145, -8.6327, -3.1320,
                    -3.5934,  6.0783, -0.8307, -5.3434]])&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
If now I take that vector and feed it into the &lt;code&gt;decoder&lt;/code&gt;, this is the image that comes out:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5JLWCD5EgAPxgvpxlZFDaDQUjn7LQLv-tQCtHBvLKjnRe6_Tg3E9h-2Iw139xvfARZa3u0djY-adktQrT7GLLhBi9yehcxgJOd8srXYmqrmv2qZq7nX0b6HrIrvh_LW89lWRJWI-XcaY/s1600/natural_digits_pos_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5JLWCD5EgAPxgvpxlZFDaDQUjn7LQLv-tQCtHBvLKjnRe6_Tg3E9h-2Iw139xvfARZa3u0djY-adktQrT7GLLhBi9yehcxgJOd8srXYmqrmv2qZq7nX0b6HrIrvh_LW89lWRJWI-XcaY/s1600/natural_digits_pos_2.png&quot; data-original-width=&quot;196&quot; data-original-height=&quot;196&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Looks good, right? Of course it is not exactly the same, but take a second to appreciate that the original image was $28 \times 28$, hence had $784$ values; those $784$ values were compressed into the $10$ numbers you saw above and then those $10$ numbers were used to reconstruct this beautiful $2$.&lt;br /&gt;
&lt;br /&gt;
Of course that to build this $2$ we had to first have a $2$ go through the &lt;code&gt;encoder&lt;/code&gt;, but I don&#39;t really like that step. What I had envisioned was a system that only made use of a single network.&lt;br /&gt;
&lt;br /&gt;
One possible first idea would be to feed the &lt;code&gt;decoder&lt;/code&gt; a vector of zeroes with a single $1$ in the right place. The only reason that does not work so well is because the &lt;code&gt;encoder&lt;/code&gt; doesn&#39;t really compress the images to such nice-looking vectors, so the &lt;code&gt;decoder&lt;/code&gt; doesn&#39;t really know how to handle that. Instead, I have a little helper function that creates a random vector of size $10$, where each entry is randomly chosen in $[-2, 1]$, except for the coordinate that corresponds to the digit I want to create: that one is a random number in $[13, 14]$.&lt;br /&gt;
&lt;br /&gt;
Using that $5$ times for each digit, I was able to create these &quot;handwritten&quot; digits:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqppTgKafv37Bd5knQST3zQbKEf9Z7zahbz4wubQmNaE8H7v6TxrAedlrb2vIMFJsnbLwxmGLbqfJXf-AMJElsWmX6R8QmHqIkJBilxzQ-P1V13YT1xEvHjwKTfmq7yZNdk75ZnBnVmAI/s1600/generated_0.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqppTgKafv37Bd5knQST3zQbKEf9Z7zahbz4wubQmNaE8H7v6TxrAedlrb2vIMFJsnbLwxmGLbqfJXf-AMJElsWmX6R8QmHqIkJBilxzQ-P1V13YT1xEvHjwKTfmq7yZNdk75ZnBnVmAI/s1600/generated_0.png&quot; data-original-width=&quot;373&quot; data-original-height=&quot;106&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguDOy2RWALCtLL08zpn4EnkOp9l3wAAu5g7QPgACORBCPSkuqJESwj_7RTxr76cnbyssFtR1Pm94UlFa9dyMepkhRqfYYkiM8T4pvoJiW7b-rwHPNPUndsLjmg2qNiMVqa6zKVbkwXr0k/s1600/generated_1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguDOy2RWALCtLL08zpn4EnkOp9l3wAAu5g7QPgACORBCPSkuqJESwj_7RTxr76cnbyssFtR1Pm94UlFa9dyMepkhRqfYYkiM8T4pvoJiW7b-rwHPNPUndsLjmg2qNiMVqa6zKVbkwXr0k/s1600/generated_1.png&quot; data-original-width=&quot;379&quot; data-original-height=&quot;111&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRfig_TK4qOeGTj3ccBAKPJq1Xiu8UQ8fu__TFnwuLhH7wIE7X5SgxkpjaXIaHzW8vDSU3xfQ48-8wLQBB7BwcneLpto5ryHWTlNIoQu1wWk93RrI-5pG2dkCFXMLFa7MEUZ3JmJ6UshU/s1600/generated_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRfig_TK4qOeGTj3ccBAKPJq1Xiu8UQ8fu__TFnwuLhH7wIE7X5SgxkpjaXIaHzW8vDSU3xfQ48-8wLQBB7BwcneLpto5ryHWTlNIoQu1wWk93RrI-5pG2dkCFXMLFa7MEUZ3JmJ6UshU/s1600/generated_2.png&quot; data-original-width=&quot;374&quot; data-original-height=&quot;100&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibgUfTkhPwkF7891598XqU0gYQ2HTLZL9sFTS4yEfmdxMluvV-0g1anYJBbi7Qh9cgoL7ugYij5Vr6m5un2PpJhtr-AH7Jo8akFwF-NM3b0OnaZgb7-tsMMeUUCbdSmj_ZUpYbyk5m1gY/s1600/generated_3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibgUfTkhPwkF7891598XqU0gYQ2HTLZL9sFTS4yEfmdxMluvV-0g1anYJBbi7Qh9cgoL7ugYij5Vr6m5un2PpJhtr-AH7Jo8akFwF-NM3b0OnaZgb7-tsMMeUUCbdSmj_ZUpYbyk5m1gY/s1600/generated_3.png&quot; data-original-width=&quot;375&quot; data-original-height=&quot;96&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcvw9LQ7Xd2uLkeNXuOp8jSiW2kyJ8aWm6mR8qBbj70HvdvtkVj_-Mq_mfXn9j9I8GN5hdzmNvE7OUq5C9gf_9G4gxO7yPCE2BNjUFEYpt1JwBMM9-4_udNfxyReWuW3YT3elhgxnDm_o/s1600/generated_4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcvw9LQ7Xd2uLkeNXuOp8jSiW2kyJ8aWm6mR8qBbj70HvdvtkVj_-Mq_mfXn9j9I8GN5hdzmNvE7OUq5C9gf_9G4gxO7yPCE2BNjUFEYpt1JwBMM9-4_udNfxyReWuW3YT3elhgxnDm_o/s1600/generated_4.png&quot; data-original-width=&quot;375&quot; data-original-height=&quot;99&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj00KnSKoIRprH50ObbDzC9pmSMRkz0mnaj558KFOx2fXkzk2_LlNSY0dgRW3Bj1kpHwhVcfDYzIvhkQHzjEi_PHaRln3jpyWMi010yEBnqOGdiG9IiXZWaTTXlUbZyqm8B8EQ6NuBCTf0/s1600/generated_5.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj00KnSKoIRprH50ObbDzC9pmSMRkz0mnaj558KFOx2fXkzk2_LlNSY0dgRW3Bj1kpHwhVcfDYzIvhkQHzjEi_PHaRln3jpyWMi010yEBnqOGdiG9IiXZWaTTXlUbZyqm8B8EQ6NuBCTf0/s1600/generated_5.png&quot; data-original-width=&quot;370&quot; data-original-height=&quot;98&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEzFfpcCgF3JAy4IHYOHvKLtsAM3rbBkbQX5I8U01yeJUfTM0bflFwBYrmvMgpLFIQdsXCOGc94PEd_mFQOL-VZohNSypxG-pSs7yBvAA47eDUm6N8QqgxGIsWL6b378SyZDAn4eDU6M8/s1600/generated_6.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEzFfpcCgF3JAy4IHYOHvKLtsAM3rbBkbQX5I8U01yeJUfTM0bflFwBYrmvMgpLFIQdsXCOGc94PEd_mFQOL-VZohNSypxG-pSs7yBvAA47eDUm6N8QqgxGIsWL6b378SyZDAn4eDU6M8/s1600/generated_6.png&quot; data-original-width=&quot;378&quot; data-original-height=&quot;94&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUynUU5MKt5oHfirUea1HxXbu63tZWU1WaE8v7UAIaJ_Fh29lk2yqOt-isLEjHv8cRHpV7fbl0olCRLfSoUwbjGVKX08pbwCVgn9vkTTY79DmGcmH6q9P74Uto6houGVk1n0wpkd_DTPg/s1600/generated_7.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUynUU5MKt5oHfirUea1HxXbu63tZWU1WaE8v7UAIaJ_Fh29lk2yqOt-isLEjHv8cRHpV7fbl0olCRLfSoUwbjGVKX08pbwCVgn9vkTTY79DmGcmH6q9P74Uto6houGVk1n0wpkd_DTPg/s1600/generated_7.png&quot; data-original-width=&quot;373&quot; data-original-height=&quot;101&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbsBfumf_lNq_irP1jHECFchh0V9h58gP4CXeLI0TYW2qWz4eqF0kgGBLowm2uEZ03ZMkbPFlimowmvr8N47jaz4NKow2GfEtBbSJXvFKTpklLjR3xrDjVyFG-8L9VtxGNK13ek7O5x-0/s1600/generated_8.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbsBfumf_lNq_irP1jHECFchh0V9h58gP4CXeLI0TYW2qWz4eqF0kgGBLowm2uEZ03ZMkbPFlimowmvr8N47jaz4NKow2GfEtBbSJXvFKTpklLjR3xrDjVyFG-8L9VtxGNK13ek7O5x-0/s1600/generated_8.png&quot; data-original-width=&quot;377&quot; data-original-height=&quot;99&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2RXRpONBF9wXtjJUSPD7floTGOD9FN8CQC2rQH3E3LM4fyohBEqXrcFziurEhap4PlKR2bCSFX7bqpHgIdXp-1wdk5d4ateyAtrKH0eqOLvbdY3e_7D6x9h5WMljtYZOYLT_jj5f3vVs/s1600/generated_9.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2RXRpONBF9wXtjJUSPD7floTGOD9FN8CQC2rQH3E3LM4fyohBEqXrcFziurEhap4PlKR2bCSFX7bqpHgIdXp-1wdk5d4ateyAtrKH0eqOLvbdY3e_7D6x9h5WMljtYZOYLT_jj5f3vVs/s1600/generated_9.png&quot; data-original-width=&quot;375&quot; data-original-height=&quot;98&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
It is true that they look practically the same, but they are not!&lt;br /&gt;
&lt;br /&gt;
Then I looked at those pictures, chose one digit out of each row, and used some basic thresholding to try and set the background to black and the number to white, to see if I could make the digits more easily read. This is what I ended up with:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4wxXwogaMnRcjvx5wtCXMg1SN1YJShWDTwDCnXcBMAF9zdYdosGktxsd3ZOp9PJgNRs8eTxgEYuV0xRA_F1fQpkf-6ueRo34vDlkc8NyioHZdjdfoYW5c1nlTIEciTQ8FGpHqw7pqDKY/s1600/digitpalette.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4wxXwogaMnRcjvx5wtCXMg1SN1YJShWDTwDCnXcBMAF9zdYdosGktxsd3ZOp9PJgNRs8eTxgEYuV0xRA_F1fQpkf-6ueRo34vDlkc8NyioHZdjdfoYW5c1nlTIEciTQ8FGpHqw7pqDKY/s400/digitpalette.png&quot; width=&quot;400&quot; height=&quot;40&quot; data-original-width=&quot;726&quot; data-original-height=&quot;73&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
which is not too shabby, in my opinion.&lt;br /&gt;
&lt;br /&gt;
As future work, there is still everything to be done! Trying different neural network architectures, studying if the accuracy of the &lt;code&gt;encoder&lt;/code&gt; is very important or not, finding more clever ways of giving the input to the &lt;code&gt;decoder&lt;/code&gt;, finding more clever ways of enhancing the image produced by the &lt;code&gt;decoder&lt;/code&gt;, trying to understand if it is possible for the network to generate more distinct digits, etc.&lt;br /&gt;
&lt;br /&gt;
All this was written in a Jupyter notebook that you can find &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/NaturalDigitGeneration&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;. I used &lt;code&gt;pytorch&lt;/code&gt; for this, so if you want to run it you&#39;ll need to have that. Otherwise, you can still look at the pictures and check the specifications of what I did, and try to reproduce this with your own packages and whatnot.

&lt;b&gt;TL;DR&lt;/b&gt; the images throughout this post are of digits that were generated by a neural network.

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post vou mostrar como é que treinei uma rede neuronal para desenhar dígitos que parecem manuscritos. Na verdade, os dígitos que vêem no início do post foram desenhados pela tal rede neuronal. Todo o código que diz respeito a esta experiência está &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/NaturalDigitGeneration&quot; target=&quot;_blank&quot;&gt;aqui&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Tudo começou quando eu li, há algum tempo atrás, sobre uma utilização engraçada que se podia dar às redes neuronais: treinamos uma rede neuronal (com $N$ inputs) para ser a função identidade, uma rede que devolve exatamente aquilo que recebeu. No entanto, no meio da rede neuronal pômos uma camada com tamanho menor que $N$. Se fizermos isto, então o que a rede neuronal está a fazer é a espremer o input pela camada que é mais apertada, e depois a expandi-lo de novo.&lt;br /&gt;
&lt;br /&gt;
Se separarmos agora a nossa rede neuronal, a metade que está à esquerda da camada mais apertada serve para comprimir os nossos inputs. A segunda metade, à direita da camada mais apertada, é a metade da rede que expande os inputs depois de eles terem sido espremidos, i.e. é uma rede que descomprime (para os mais curiosos, acho que isto são &quot;encoders&quot; no mundo das redes neuronais, mas não tenho a certeza).&lt;br /&gt;
&lt;br /&gt;
Vamos deixar a ideia repousar por um segundo.&lt;br /&gt;
Agora que &quot;sabemos&quot; comprimir coisas, imaginemos o seguinte: vou ensinar uma rede neuronal a comprimir imagens de dígitos em vetores de tamanho $10$ (uma coordenada no vetor por cada dígito que existe), e vamos dizer que essa rede se vai chamar &lt;code&gt;encoder&lt;/code&gt;. Para treinar a minha rede &lt;code&gt;encoder&lt;/code&gt; posso ensiná-la a classificar imagens dos $10$ dígitos. Depois de treinar o &lt;code&gt;encoder&lt;/code&gt;, treino outra rede neuronal (a que vou chamar &lt;code&gt;decoder&lt;/code&gt;) cujo objetivo vai ser desfazer tudo o que o &lt;code&gt;encoder&lt;/code&gt; fizer.&lt;br /&gt;
&lt;br /&gt;
Depois de treinar as duas redes neuronais um bocado, imaginemos que pego nesta imagem de um $2$:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6WWhj_CgUkS5yRuLY0ft_X746NV_-MDikxCqUivBOi052uA513iOmdRyhogsJooqjPhPAcfc1o1U8Rvea5LtRhZksirIbnmMBPCSZ4Tsp6vEF2MEIlnoGYN06DKd4WG9cOd3ucosfUec/s1600/natural_digits_pre_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6WWhj_CgUkS5yRuLY0ft_X746NV_-MDikxCqUivBOi052uA513iOmdRyhogsJooqjPhPAcfc1o1U8Rvea5LtRhZksirIbnmMBPCSZ4Tsp6vEF2MEIlnoGYN06DKd4WG9cOd3ucosfUec/s1600/natural_digits_pre_2.png&quot; data-original-width=&quot;197&quot; data-original-height=&quot;197&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Se eu passar esta imagem pelo meu &lt;code&gt;encoder&lt;/code&gt;, o resultado que obtenho é este:
&lt;pre&gt;&lt;code&gt;tensor([[-3.2723,  3.7296,  9.6557,  4.9145, -8.6327, -3.1320,
                    -3.5934,  6.0783, -0.8307, -5.3434]])&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Se agora eu pegar nesse vetor e o puser dentro do &lt;code&gt;decoder&lt;/code&gt;, obtenho esta imagem:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5JLWCD5EgAPxgvpxlZFDaDQUjn7LQLv-tQCtHBvLKjnRe6_Tg3E9h-2Iw139xvfARZa3u0djY-adktQrT7GLLhBi9yehcxgJOd8srXYmqrmv2qZq7nX0b6HrIrvh_LW89lWRJWI-XcaY/s1600/natural_digits_pos_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5JLWCD5EgAPxgvpxlZFDaDQUjn7LQLv-tQCtHBvLKjnRe6_Tg3E9h-2Iw139xvfARZa3u0djY-adktQrT7GLLhBi9yehcxgJOd8srXYmqrmv2qZq7nX0b6HrIrvh_LW89lWRJWI-XcaY/s1600/natural_digits_pos_2.png&quot; data-original-width=&quot;196&quot; data-original-height=&quot;196&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Até tem bom aspeto, não? Claro que não são exatamente a mesma coisa, mas reparem que a imagem original tem $28 \times 28$ valores, $784$ pedaços de informação; esses $784$ valores foram espremidos para apenas $10$ valores, e desses $10$ valores o &lt;code&gt;decoder&lt;/code&gt; conseguiu retirar esta representação do $2$.&lt;br /&gt;
&lt;br /&gt;
Claro que para construir este $2$ eu tive de fazer uso do &lt;code&gt;encoder&lt;/code&gt; primeiro, mas não é assim que eu quero que isto funcione. Depois de usar o &lt;code&gt;encoder&lt;/code&gt; para treinar o &lt;code&gt;decoder&lt;/code&gt;, quero poder deitá-lo fora!&lt;br /&gt;
&lt;br /&gt;
Uma possível ideia seria alimentar o &lt;code&gt;decoder&lt;/code&gt; com um vetor de zeros, a menos de uma única coordenada onde estaria um $1$. O único motivo pelo qual isso não funciona tão bem é porque o &lt;code&gt;encoder&lt;/code&gt; nunca comprimiu nenhuma imagem para um vetor tão lindinho, e portanto o &lt;code&gt;decoder&lt;/code&gt; provavelmente não há de saber como descomprimir esse vetor. Para contornar este problema, arranjei uma função auxiliar que devolve um vetor de tamanho $10$, onde $9$ das coordenadas são escolhidas aleatoriamente em $[-2, 1]$ e a coordenada que diz respeito ao dígito que quero criar é um número aleatório em $[13, 14]$.&lt;br /&gt;
&lt;br /&gt;
Usando essa função $5$ vezes para cada dígito, criei estas imagens:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqppTgKafv37Bd5knQST3zQbKEf9Z7zahbz4wubQmNaE8H7v6TxrAedlrb2vIMFJsnbLwxmGLbqfJXf-AMJElsWmX6R8QmHqIkJBilxzQ-P1V13YT1xEvHjwKTfmq7yZNdk75ZnBnVmAI/s1600/generated_0.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqppTgKafv37Bd5knQST3zQbKEf9Z7zahbz4wubQmNaE8H7v6TxrAedlrb2vIMFJsnbLwxmGLbqfJXf-AMJElsWmX6R8QmHqIkJBilxzQ-P1V13YT1xEvHjwKTfmq7yZNdk75ZnBnVmAI/s1600/generated_0.png&quot; data-original-width=&quot;373&quot; data-original-height=&quot;106&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguDOy2RWALCtLL08zpn4EnkOp9l3wAAu5g7QPgACORBCPSkuqJESwj_7RTxr76cnbyssFtR1Pm94UlFa9dyMepkhRqfYYkiM8T4pvoJiW7b-rwHPNPUndsLjmg2qNiMVqa6zKVbkwXr0k/s1600/generated_1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguDOy2RWALCtLL08zpn4EnkOp9l3wAAu5g7QPgACORBCPSkuqJESwj_7RTxr76cnbyssFtR1Pm94UlFa9dyMepkhRqfYYkiM8T4pvoJiW7b-rwHPNPUndsLjmg2qNiMVqa6zKVbkwXr0k/s1600/generated_1.png&quot; data-original-width=&quot;379&quot; data-original-height=&quot;111&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRfig_TK4qOeGTj3ccBAKPJq1Xiu8UQ8fu__TFnwuLhH7wIE7X5SgxkpjaXIaHzW8vDSU3xfQ48-8wLQBB7BwcneLpto5ryHWTlNIoQu1wWk93RrI-5pG2dkCFXMLFa7MEUZ3JmJ6UshU/s1600/generated_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRfig_TK4qOeGTj3ccBAKPJq1Xiu8UQ8fu__TFnwuLhH7wIE7X5SgxkpjaXIaHzW8vDSU3xfQ48-8wLQBB7BwcneLpto5ryHWTlNIoQu1wWk93RrI-5pG2dkCFXMLFa7MEUZ3JmJ6UshU/s1600/generated_2.png&quot; data-original-width=&quot;374&quot; data-original-height=&quot;100&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibgUfTkhPwkF7891598XqU0gYQ2HTLZL9sFTS4yEfmdxMluvV-0g1anYJBbi7Qh9cgoL7ugYij5Vr6m5un2PpJhtr-AH7Jo8akFwF-NM3b0OnaZgb7-tsMMeUUCbdSmj_ZUpYbyk5m1gY/s1600/generated_3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibgUfTkhPwkF7891598XqU0gYQ2HTLZL9sFTS4yEfmdxMluvV-0g1anYJBbi7Qh9cgoL7ugYij5Vr6m5un2PpJhtr-AH7Jo8akFwF-NM3b0OnaZgb7-tsMMeUUCbdSmj_ZUpYbyk5m1gY/s1600/generated_3.png&quot; data-original-width=&quot;375&quot; data-original-height=&quot;96&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcvw9LQ7Xd2uLkeNXuOp8jSiW2kyJ8aWm6mR8qBbj70HvdvtkVj_-Mq_mfXn9j9I8GN5hdzmNvE7OUq5C9gf_9G4gxO7yPCE2BNjUFEYpt1JwBMM9-4_udNfxyReWuW3YT3elhgxnDm_o/s1600/generated_4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcvw9LQ7Xd2uLkeNXuOp8jSiW2kyJ8aWm6mR8qBbj70HvdvtkVj_-Mq_mfXn9j9I8GN5hdzmNvE7OUq5C9gf_9G4gxO7yPCE2BNjUFEYpt1JwBMM9-4_udNfxyReWuW3YT3elhgxnDm_o/s1600/generated_4.png&quot; data-original-width=&quot;375&quot; data-original-height=&quot;99&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj00KnSKoIRprH50ObbDzC9pmSMRkz0mnaj558KFOx2fXkzk2_LlNSY0dgRW3Bj1kpHwhVcfDYzIvhkQHzjEi_PHaRln3jpyWMi010yEBnqOGdiG9IiXZWaTTXlUbZyqm8B8EQ6NuBCTf0/s1600/generated_5.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj00KnSKoIRprH50ObbDzC9pmSMRkz0mnaj558KFOx2fXkzk2_LlNSY0dgRW3Bj1kpHwhVcfDYzIvhkQHzjEi_PHaRln3jpyWMi010yEBnqOGdiG9IiXZWaTTXlUbZyqm8B8EQ6NuBCTf0/s1600/generated_5.png&quot; data-original-width=&quot;370&quot; data-original-height=&quot;98&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEzFfpcCgF3JAy4IHYOHvKLtsAM3rbBkbQX5I8U01yeJUfTM0bflFwBYrmvMgpLFIQdsXCOGc94PEd_mFQOL-VZohNSypxG-pSs7yBvAA47eDUm6N8QqgxGIsWL6b378SyZDAn4eDU6M8/s1600/generated_6.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEzFfpcCgF3JAy4IHYOHvKLtsAM3rbBkbQX5I8U01yeJUfTM0bflFwBYrmvMgpLFIQdsXCOGc94PEd_mFQOL-VZohNSypxG-pSs7yBvAA47eDUm6N8QqgxGIsWL6b378SyZDAn4eDU6M8/s1600/generated_6.png&quot; data-original-width=&quot;378&quot; data-original-height=&quot;94&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUynUU5MKt5oHfirUea1HxXbu63tZWU1WaE8v7UAIaJ_Fh29lk2yqOt-isLEjHv8cRHpV7fbl0olCRLfSoUwbjGVKX08pbwCVgn9vkTTY79DmGcmH6q9P74Uto6houGVk1n0wpkd_DTPg/s1600/generated_7.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUynUU5MKt5oHfirUea1HxXbu63tZWU1WaE8v7UAIaJ_Fh29lk2yqOt-isLEjHv8cRHpV7fbl0olCRLfSoUwbjGVKX08pbwCVgn9vkTTY79DmGcmH6q9P74Uto6houGVk1n0wpkd_DTPg/s1600/generated_7.png&quot; data-original-width=&quot;373&quot; data-original-height=&quot;101&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbsBfumf_lNq_irP1jHECFchh0V9h58gP4CXeLI0TYW2qWz4eqF0kgGBLowm2uEZ03ZMkbPFlimowmvr8N47jaz4NKow2GfEtBbSJXvFKTpklLjR3xrDjVyFG-8L9VtxGNK13ek7O5x-0/s1600/generated_8.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbsBfumf_lNq_irP1jHECFchh0V9h58gP4CXeLI0TYW2qWz4eqF0kgGBLowm2uEZ03ZMkbPFlimowmvr8N47jaz4NKow2GfEtBbSJXvFKTpklLjR3xrDjVyFG-8L9VtxGNK13ek7O5x-0/s1600/generated_8.png&quot; data-original-width=&quot;377&quot; data-original-height=&quot;99&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2RXRpONBF9wXtjJUSPD7floTGOD9FN8CQC2rQH3E3LM4fyohBEqXrcFziurEhap4PlKR2bCSFX7bqpHgIdXp-1wdk5d4ateyAtrKH0eqOLvbdY3e_7D6x9h5WMljtYZOYLT_jj5f3vVs/s1600/generated_9.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2RXRpONBF9wXtjJUSPD7floTGOD9FN8CQC2rQH3E3LM4fyohBEqXrcFziurEhap4PlKR2bCSFX7bqpHgIdXp-1wdk5d4ateyAtrKH0eqOLvbdY3e_7D6x9h5WMljtYZOYLT_jj5f3vVs/s1600/generated_9.png&quot; data-original-width=&quot;375&quot; data-original-height=&quot;98&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
As imagens são &lt;b&gt;bastante&lt;/b&gt; semelhantes, e isso é um problema que vou tentar apresentar como resolvido num post futuro, mas não são exatamente iguais!&lt;br /&gt;
&lt;br /&gt;
Depois de olhar para as figuras, para cada conjunto de $5$ imagens do mesmo dígito, escolhi uma com bom aspeto e tentei usar umas regras básicas para eliminar o ruído a cinzento claro no fundo de cada imagem. Depois desse passo intermédio, acabei com isto:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4wxXwogaMnRcjvx5wtCXMg1SN1YJShWDTwDCnXcBMAF9zdYdosGktxsd3ZOp9PJgNRs8eTxgEYuV0xRA_F1fQpkf-6ueRo34vDlkc8NyioHZdjdfoYW5c1nlTIEciTQ8FGpHqw7pqDKY/s1600/digitpalette.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4wxXwogaMnRcjvx5wtCXMg1SN1YJShWDTwDCnXcBMAF9zdYdosGktxsd3ZOp9PJgNRs8eTxgEYuV0xRA_F1fQpkf-6ueRo34vDlkc8NyioHZdjdfoYW5c1nlTIEciTQ8FGpHqw7pqDKY/s400/digitpalette.png&quot; width=&quot;400&quot; height=&quot;40&quot; data-original-width=&quot;726&quot; data-original-height=&quot;73&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
O que, na minha opinião, não é terrível.&lt;br /&gt;
&lt;br /&gt;
No futuro, há muito que pode ser feito ainda: tentar arquiteturas de redes neuronais diferentes, estudar se a precisão do &lt;code&gt;encoder&lt;/code&gt; a classificar é importante ou não, encontrar maneiras mais inteligentes de dar input ao &lt;code&gt;decoder&lt;/code&gt;, encontrar maneiras mais inteligentes de melhorar a imagem devolvida pelo &lt;code&gt;decoder&lt;/code&gt;, tentar entender se é possível que a rede neuronal gere dígitos mais distintos, etc.&lt;br /&gt;
&lt;br /&gt;
Este código foi todo escrito num notebook Jupyter que podem encontrar &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/NaturalDigitGeneration&quot; target=&quot;_blank&quot;&gt;aqui&lt;/a&gt;. Usei o &lt;code&gt;pytorch&lt;/code&gt; para estas experiências, portanto hão de precisar dele para correr o meu código. Caso contrário, podem ver os bonecos que fiz e tentar reproduzir (e melhorar!) os meus resultados com outra livraria.

&lt;b&gt;TL;DR&lt;/b&gt; as imagens espalhadas pelo post são de dígitos desenhados por uma rede neuronal.

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/990402937960554664'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/990402937960554664'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2019/03/generating-natural-looking-digits-with.html' title='Generating natural-looking digits with neural networks'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDBgLL8lt468zN-8plTWK4tUvkVMODUmrvf1LcQ5otpsmT-xsbHyZtwHT7ASJ-lJOKIOou7lVdwsK03_PKxblg46KAtL_ht-9Y9PVXIrohg-DRKy9JsTps7PVf2bDNJFHMUi3uaEwPN5E/s72-c/digitpalette.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-5983613188067937579</id><published>2019-03-09T21:58:00.002+00:00</published><updated>2019-03-09T22:00:35.109+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="graphs"/><category scheme="http://www.blogger.com/atom/ns#" term="mazes"/><category scheme="http://www.blogger.com/atom/ns#" term="project"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="pygame"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="random walks"/><title type='text'>Generating (better) random mazes</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqXnmdkuVp7HzWzutjW3NOSizSP_I8u_G2k0qRf6aO7CJKHHZklO4CH4yzlir-ymbOgC4q83GzeW10eTIgAD13__wkb0DJpytq9Oy8LfKYlRAShMVI5TDTUwzCa63NsaeIklcodYbddys/s1600/wilson_animation.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqXnmdkuVp7HzWzutjW3NOSizSP_I8u_G2k0qRf6aO7CJKHHZklO4CH4yzlir-ymbOgC4q83GzeW10eTIgAD13__wkb0DJpytq9Oy8LfKYlRAShMVI5TDTUwzCa63NsaeIklcodYbddys/s1600/wilson_animation.gif&quot; data-original-width=&quot;164&quot; data-original-height=&quot;124&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In &lt;a href=&quot;http://mathspp.blogspot.com/2018/06/random-maze-generation.html&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt; previous post I shared some code and animations of an algorithm that created random mazes. I shared it with you and I got some feedback on Facebook, saying that even the stupidly large mazes I gave you were really easy to solve (I think &lt;a href=&quot;https://www.facebook.com/mathspp/photos/pcb.604083963281974/604083806615323/?type=3&amp;theater&quot; target=&quot;_blank&quot;&gt;this link&lt;/a&gt; can show you what I am talking about). So it was about time I got you some new mazes! And this time, I don&#39;t think they are as easy to solve as the old ones.&lt;br /&gt;
&lt;br /&gt;
The mazes I am sharing today were created by code found in &lt;a href=&quot;https://github.com/RojerGS/projects/tree/master/MazeGenerators&quot; target=&quot;_blank&quot;&gt;this GitHub repo&lt;/a&gt;. The README will tell you to run the &lt;code&gt;wilson_generator.py&lt;/code&gt; file. You can also download the (windows) executable that is zipped inside the &lt;code&gt;wilsonExe&lt;/code&gt; rar. (please notice that in both cases, you can use the &lt;code&gt;wilsonconfig.ini&lt;/code&gt; file to change the size of the maze)&lt;br /&gt;
&lt;br /&gt;
The way our algorithm works is really simple. It will start a random walk on the top left corner of the window. Whenever the random walk intersects itself (creating a loop), it removes the loop from the walk, and then continues. Whenever the random walk connects back to whatever part of the maze was already built, the random walk becomes a part of the maze itself and a new random walk is started somewhere else. This is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Loop-erased_random_walk&quot; target=&quot;_blank&quot;&gt;loop-erased random walk&lt;/a&gt;, the stepping stone of Wilson&#39;s algorithm to generate a random spanning tree of a graph, with a very nice property: it will generate &lt;b&gt;any&lt;/b&gt; of the possible spanning trees with equal probability.&lt;br /&gt;
&lt;br /&gt;
Generating any of the spanning trees uniformly means that our maze won&#39;t be &lt;i&gt;biased&lt;/i&gt; and have only a couple of really long paths, or a bunch of very short paths. And the reason why this algorithm actually has that property is fairly intuitive: just suppose that before running the algorithm, you visit each vertex, and create an infinite random stack of directions; that is, for each vertex $v$ in the graph, you create a random sequence $\{v_i\}_i$, where each $v_i$ was selected randomly and uniformly from the direct neighbours of $v$. After you have done this for every vertex, there is an obvious way to start tracing paths in your graph: just pick a vertex and start following the directions you are given! But the thing is, following those directions might actually make you follow some loops. So before tracing the paths you are presented with, you remove all the loops that you can find on top of all the stacks you created... when that has been done, following the directions that are on top of the stacks will give you a uniformly generated random tree. Of course that to run our algorithm, we don&#39;t generate the infinite stacks in advance, we just generate the elements that are needed on-the-fly.&lt;br /&gt;
&lt;br /&gt;
This algorithm creates really balanced mazes... As an example, take this maze:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI38zeb7sj7sB5CqyyTRNirdmjJR8ODx2-i2wOYSboVT8tEhijZ2kA2Oz0SjiBBBBAxzYDsa5a6OHWnrKyvhwfuyHF0CxuyBHZK6prh6LwHPSCpWSK2ilNzODCsIoxCbEpx4xkRLdPPd0/s1600/wilson_maze_N40_p5_09_35_49_30012019.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI38zeb7sj7sB5CqyyTRNirdmjJR8ODx2-i2wOYSboVT8tEhijZ2kA2Oz0SjiBBBBAxzYDsa5a6OHWnrKyvhwfuyHF0CxuyBHZK6prh6LwHPSCpWSK2ilNzODCsIoxCbEpx4xkRLdPPd0/s1600/wilson_maze_N40_p5_09_35_49_30012019.png&quot; data-original-width=&quot;405&quot; data-original-height=&quot;405&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Now imagine that on the top left corner I will pour a bucket of a special paint: one that gradually changes colour as it travels. The resulting (coloured) maze looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnZuCZXmy_ZeeObRTeWgypT4aTLRivEF4TkY8UHtRJPqUxWA2tyy-Cj1K1kMyE9Fj9fPYS-K2eNMAznHnvcWLjBHZSfp1TaOXdflot4ZCNWHCkU6sOKWsnhrDi0KOmT8oxqb5WVd2aWUk/s1600/wilson_flooded_N40_p5_09_35_49_30012019.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnZuCZXmy_ZeeObRTeWgypT4aTLRivEF4TkY8UHtRJPqUxWA2tyy-Cj1K1kMyE9Fj9fPYS-K2eNMAznHnvcWLjBHZSfp1TaOXdflot4ZCNWHCkU6sOKWsnhrDi0KOmT8oxqb5WVd2aWUk/s1600/wilson_flooded_N40_p5_09_35_49_30012019.png&quot; data-original-width=&quot;405&quot; data-original-height=&quot;405&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
(please bear in mind that the colours used cycle back to the beginning, so it creates a continuous and infinite degradee)&lt;br /&gt;
Also notice that this algorithm can be painfully slow to watch, specially when it has just started. I would &lt;b&gt;strongly&lt;/b&gt; recommend against changing the configuration &lt;code&gt;save_frames = False&lt;/code&gt; to &lt;code&gt;True&lt;/code&gt;, as that will slow down the algorithm for a bit... but if you must do that, point the &lt;code&gt;screenshot_bin&lt;/code&gt; to some existing folder, so that the thousands of frames get dumped there.&lt;br /&gt;
&lt;br /&gt;
That is it! You have a small animation of the algorithm on the beginning of the post and a massive maze down there! Let me know if you manage to find your way from the top left corner to the bottom right corner! (the black and white version of that maze is &lt;a href=&quot;https://github.com/RojerGS/projects/blob/master/MazeGenerators/bin/ss_22_22_15_090319.png&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;)&lt;br /&gt;
I would also recommend checking &lt;a href=&quot;https://bl.ocks.org/mbostock/11357811&quot; target=&quot;_blank&quot;&gt;this link&lt;/a&gt;, as it has some nice animations.

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Num &lt;a href=&quot;http://mathspp.blogspot.com/2018/06/random-maze-generation.html&quot; target=&quot;_blank&quot;&gt;post&lt;/a&gt; antigo eu partilhei código e algumas animações de um algoritmo que criava labirintos aleatórios. Quando partilhei algumas imagens, recebi feedback a dizer que até os labirintos grandes eram fáceis de resolver (penso que &lt;a href=&quot;https://www.facebook.com/mathspp/photos/pcb.604083963281974/604083806615323/?type=3&amp;theater&quot; target=&quot;_blank&quot;&gt;aqui&lt;/a&gt; encontram o feedback a que me refiro). Portanto já estava na altura de eu arranjar uma maneira melhor de gerar os labirintos! E desta vez, acho que os resultados são melhores.&lt;br /&gt;
&lt;br /&gt;
Os labirintos deste post foram criados por código que está &lt;a href=&quot;https://github.com/RojerGS/projects/tree/master/MazeGenerators&quot; target=&quot;_blank&quot;&gt;neste repositório do GitHub&lt;/a&gt;. O ficheiro README explica como usar o ficheiro &lt;code&gt;wilson_generator.py&lt;/code&gt;. Também há a opção de usarem o executável windows que está zippado dentro do ficheiro &lt;code&gt;wilsonExe.rar&lt;/code&gt;. (em qualquer um dos casos, o ficheiro &lt;code&gt;wilsonconfig.ini&lt;/code&gt; pode ser usado para mudar o tamanho do labirinto)&lt;br /&gt;
&lt;br /&gt;
O modo como o algoritmo funciona é simples. Basta começar um caminho aleatório no canto superior esquerdo da janela. De cada vez que esse caminho aleatório se intersetar a si próprio (criando assim um ciclo), o algoritmo retira esse ciclo do caminho e retoma a construção do caminho aleatório. Sempre que o caminho aleatório tocar numa parte do labirinto que já estava construída, esse caminho aleatório passa a fazer parte do labirinto e começamos outro caminho aleatório noutra posição qualquer. Estes &lt;a href=&quot;https://en.wikipedia.org/wiki/Loop-erased_random_walk&quot; target=&quot;_blank&quot;&gt;caminhos aleatórios sem ciclos&lt;/a&gt; são a base do algoritmo de Wilson para criar uma árvore geradora de um grafo com a seguinte propriedade: qualquer árvore geradora tem igual probabilidade de ser criada.&lt;br /&gt;
&lt;br /&gt;
Como a árvore geradora é escolhida uniformemente de entre todas as árvores geradoras possíveis, em geral o nosso labirinto não tem os defeitos específicos de outros algoritmos, como só ter um par de caminhos muito longos ou ter imensos caminhos, mas todos muito curtos. Perceber porque é que o algoritmo tem esta propriedade não é completamente impossível: imaginemos que antes de começar o algoritmo, eu visitei cada vértice do grafo e criei uma pilha infinita de direções; ou seja, para cada vértice $v$ do grafo, criei uma sucessão aleatória $\{v_i\}_i$, onde cada $v_i$ é escolhido uniformemente de entre os vizinhos diretos de $v$. Depois de isto ser feito para cada vértice, há uma maneira óbvia de começar a percorrer caminhos no grafo: basta escolher um vértice e seguir as direções que me são dadas! Mas há um pequeno senão: seguir estas direções fará certamente com que encontremos ciclos. Para prevenir isto, antes de começarmos a seguir as indicações que nos são dadas, retiramos todos os ciclos que estejam a ser criados pelas direções que estão nas pilhas... quando isto tiver sido feito, podemos seguir as direções dos vários vértices e criamos assim uma árvore geradora do nosso grafo. Claro que para correr o algoritmo, não criamos pilhas infinitas à priori. Vamos calculando as direções à medida que elas são necessárias.&lt;br /&gt;
&lt;br /&gt;
Os labirintos criados por este algoritmo são bastante equilibrados, no sentido de não terem poucos caminhos muito longos ou muitos caminhos bastante curtos. Na verdade, olhando para este labirinto:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI38zeb7sj7sB5CqyyTRNirdmjJR8ODx2-i2wOYSboVT8tEhijZ2kA2Oz0SjiBBBBAxzYDsa5a6OHWnrKyvhwfuyHF0CxuyBHZK6prh6LwHPSCpWSK2ilNzODCsIoxCbEpx4xkRLdPPd0/s1600/wilson_maze_N40_p5_09_35_49_30012019.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI38zeb7sj7sB5CqyyTRNirdmjJR8ODx2-i2wOYSboVT8tEhijZ2kA2Oz0SjiBBBBAxzYDsa5a6OHWnrKyvhwfuyHF0CxuyBHZK6prh6LwHPSCpWSK2ilNzODCsIoxCbEpx4xkRLdPPd0/s1600/wilson_maze_N40_p5_09_35_49_30012019.png&quot; data-original-width=&quot;405&quot; data-original-height=&quot;405&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Posso pensar em colori-lo de uma maneira especial: no canto superior esquerdo vou deitar um balde de tinta que muda de cor gradualmente à medida que escorre. O labirinto fica então pintado desta maneira:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnZuCZXmy_ZeeObRTeWgypT4aTLRivEF4TkY8UHtRJPqUxWA2tyy-Cj1K1kMyE9Fj9fPYS-K2eNMAznHnvcWLjBHZSfp1TaOXdflot4ZCNWHCkU6sOKWsnhrDi0KOmT8oxqb5WVd2aWUk/s1600/wilson_flooded_N40_p5_09_35_49_30012019.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnZuCZXmy_ZeeObRTeWgypT4aTLRivEF4TkY8UHtRJPqUxWA2tyy-Cj1K1kMyE9Fj9fPYS-K2eNMAznHnvcWLjBHZSfp1TaOXdflot4ZCNWHCkU6sOKWsnhrDi0KOmT8oxqb5WVd2aWUk/s1600/wilson_flooded_N40_p5_09_35_49_30012019.png&quot; data-original-width=&quot;405&quot; data-original-height=&quot;405&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
(note-se que as cores da &quot;tinta&quot; são cíclicas, para que eu possa sempre criar uma difusão contínua e infinita)&lt;br /&gt;
Também gostava de avisar que este algoritmo pode ser particularmente aborrecido de ver correr, principalmente se tiver acabado de começar a correr. &lt;b&gt;Não&lt;/b&gt; aconselho ninguém a mudar a configuração &lt;code&gt;save_frames = False&lt;/code&gt; para &lt;code&gt;True&lt;/code&gt;, porque isso desacelera o algoritmo ainda mais... mas se alguém quiser mesmo, então também é melhor mudar &lt;code&gt;screenshot_bin&lt;/code&gt; para uma pasta qualquer que exista, para que as imagens sejam guardadas lá.&lt;br /&gt;
&lt;br /&gt;
E por agora é tudo. Há uma pequena animação do algoritmo no início deste post e um labirinto absurdamente grande no fim! Avisem-me se o completarem, encontrando um caminho do canto superior esquerdo ao canto inferior direito. (a versão a preto e branco está &lt;a href=&quot;https://github.com/RojerGS/projects/blob/master/MazeGenerators/bin/ss_22_22_15_090319.png&quot; target=&quot;_blank&quot;&gt;aqui&lt;/a&gt;)&lt;br /&gt;
Também aconselho &lt;a href=&quot;https://bl.ocks.org/mbostock/11357811&quot; target=&quot;_blank&quot;&gt;este link&lt;/a&gt; que tem algumas animações giras.

&lt;/div&gt;
&lt;br /&gt;
&lt;small&gt;$600 \times 450$ maze&lt;/small&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRPO1d3B4eSNBpbKvhI7I0gpVSkyyo8JJi9P4dfkU0n3LXPXctEaxchZpttM9uA8P832tqrd2mE_ZG87tOML7IuBXTNZhefygyS-x4HxAdHdnlIr7EXkUOxiKcOuoBSQaJyANYpUSwjN4/s1600/ss_22_22_32_090319.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRPO1d3B4eSNBpbKvhI7I0gpVSkyyo8JJi9P4dfkU0n3LXPXctEaxchZpttM9uA8P832tqrd2mE_ZG87tOML7IuBXTNZhefygyS-x4HxAdHdnlIr7EXkUOxiKcOuoBSQaJyANYpUSwjN4/s1600/ss_22_22_32_090319.png&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;1200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/5983613188067937579'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/5983613188067937579'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2019/03/generating-better-random-mazes.html' title='Generating (better) random mazes'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqXnmdkuVp7HzWzutjW3NOSizSP_I8u_G2k0qRf6aO7CJKHHZklO4CH4yzlir-ymbOgC4q83GzeW10eTIgAD13__wkb0DJpytq9Oy8LfKYlRAShMVI5TDTUwzCa63NsaeIklcodYbddys/s72-c/wilson_animation.gif" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-6670678395926090717</id><published>2019-02-23T21:18:00.000+00:00</published><updated>2019-02-23T21:20:44.233+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="binary"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="number theory"/><category scheme="http://www.blogger.com/atom/ns#" term="pocket maths"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><title type='text'>Pocket maths: folding halves into thirds</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjN8V9O5I3EjBs2mnWCMbL2VyAhajQhgROA8c4GXfFUrbsGI0D1ZOj8z8UENFzXcgZVlGcifUKCEAEReDcb5BmzA7ca6-VPoSy27axvLCzKmjnKQgADAhTJ0xIUFtAS8bBoIz-_TLdcsNk/s1600/paper_folded.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjN8V9O5I3EjBs2mnWCMbL2VyAhajQhgROA8c4GXfFUrbsGI0D1ZOj8z8UENFzXcgZVlGcifUKCEAEReDcb5BmzA7ca6-VPoSy27axvLCzKmjnKQgADAhTJ0xIUFtAS8bBoIz-_TLdcsNk/s400/paper_folded.png&quot; width=&quot;400&quot; height=&quot;356&quot; data-original-width=&quot;234&quot; data-original-height=&quot;208&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

I have folded a piece of paper in half hundreds of times in my life. And probably so did you. Folding a piece of paper in half is fairly easy: just bend the piece of paper until the corners meet, and then crease. That is it. And with this method one can also fold a piece of paper in $4$, in $8$, etc. We just have to successively divide the sections of the paper in half.&lt;br /&gt;
&lt;br /&gt;
But what if we wanted to fold a piece of paper into thirds, as in the picture above? Some people are good at doing that, but they don&#39;t really measure anything: they just do it approximately by looking at the paper and folding where it seems &lt;i&gt;about&lt;/i&gt; right. I guess it goes without saying, but mathematicians don&#39;t like things to be &quot;about right&quot;, they want them right... and even though I wasn&#39;t a mathematician, when I was a child I thought that maybe there was a way for me to successively fold different parts of the paper in half, until one of the creases would be the crease at a third of the paper.&lt;br /&gt;
&lt;br /&gt;
I thought of doing that because dividing a piece of paper in half is easy, as everyone knows. So I decided to find a sequence of folds that would allow me to do that! Except that one such sequence &lt;i&gt;does not&lt;/i&gt; exist.&lt;br /&gt;
&lt;br /&gt;
I will give you a second to try and prove that for yourself...&lt;br /&gt;
&lt;br /&gt;
The proof is actually quite simple. If such a sequence of folds existed, that would mean that $\frac{1}{3}$ could be written as a finite sum of some fractions of the form $\frac{1}{2^n}$ (can you see why?). We will assume that such a sequence exists, in order to arrive at a &lt;a href=&quot;http://mathspp.blogspot.com/2018/01/converse-contradiction-and-construction.html&quot; target=&quot;_blank&quot;&gt;proof by contradiction&lt;/a&gt;.&lt;br /&gt;
Like I already said, if such a sequence exists, then there are some natural numbers $0 &lt; n_1 &lt; n_2 &lt; \cdots &lt; n_k$ such that
$$\frac13 = \frac{1}{2^{n_1}} + \frac1{2^{n_2}} + \cdots + \frac1{2^{n_k}}$$
Of course that we can reduce all the fractions on the right hand side to the same denominator, getting
$$\frac13 = \frac{2^{n_k-n_1}}{2^{n_k}} + \frac{2^{n_k - n_2}}{2^{n_k}} + \cdots + \frac{1}{2^{n_k}} = \frac{2^{n_k - n_1} + 2^{n_k-n_2} + \cdots + 1}{2^{n_k}}$$
from which one is able to get
$$2^{n_k} = 3\times(2^{n_k - n_1} + 2^{n_k-n_2} + \cdots + 1)$$
which is absurd, because $2^{n_k}$ is not divisible by $3$.&lt;br /&gt;
&lt;br /&gt;
And so the dreams of a young boy were shattered...

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Toda a gente já dobrou folhas de papel ao meio centenas de vezes. Talvez seja por causa da prática ou talvez seja porque é uma tarefa mesmo simples, mas qualquer pessoa consegue dobrar uma folha ao meio razoavelmente bem. O modo como eu o faço é o que quase toda a gente faz: juntamos os cantos da folha com cuidado e depois vincamos a folha ao meio. Já está. E desta maneira também dá para dobrar a folha em $4$ ou em $8$, é só dobrar ao meio sucessivamente.&lt;br /&gt;
&lt;br /&gt;
Mas e se eu quisesse dobrar a folha em três, tal como na imagem em cima? Há pessoas que o conseguem fazer bastante bem, mas não o fazem de forma precisa, fazem-no &lt;i&gt;a olho&lt;/i&gt;. Claro que para efeitos práticos isso costuma chegar, mas para o meu &quot;eu&quot; de 10 anos isso não era satisfatório. Eu queria arranjar uma maneira de conseguir dobrar a folha em três e ter a certeza absoluta que os vincos estavam no sítio certo. Como eu conseguia dobrar a folha ao meio, pensei que se fosse dobrando ao meio as secções certas, conseguiria chegar à dobra do terço da folha.&lt;br /&gt;
&lt;br /&gt;
Eu estava enganado, já que não há nenhuma sequência de &quot;dobras ao meio&quot; que me faça chegar à dobra a um terço da folha.&lt;br /&gt;
&lt;br /&gt;
Pensem um pouco sobre isso...&lt;br /&gt;
&lt;br /&gt;
A prova é bastante simples. Se essa sequência de dobras existisse, então $\frac13$ poderia ser escrito como uma soma de frações da forma $\frac1{2^n}$ (conseguem perceber porquê?). Vamos assumir que a sequência de dobras existe para fazermos uma &lt;a href=&quot;http://mathspp.blogspot.com/2018/01/converse-contradiction-and-construction.html&quot; target=&quot;_blank&quot;&gt;prova por contradição&lt;/a&gt;.&lt;br /&gt;
Tal como eu disse em cima, se essa sequência existisse, existiriam números naturais $0 &lt; n_1 &lt; n_2 &lt; \cdots &lt; n_k$ tais que
$$\frac13 = \frac{1}{2^{n_1}} + \frac1{2^{n_2}} + \cdots + \frac1{2^{n_k}}$$
Claro que podemos reduzir as frações do lado direito ao mesmo denominador, obtendo assim
$$\frac13 = \frac{2^{n_k-n_1}}{2^{n_k}} + \frac{2^{n_k - n_2}}{2^{n_k}} + \cdots + \frac{1}{2^{n_k}} = \frac{2^{n_k - n_1} + 2^{n_k-n_2} + \cdots + 1}{2^{n_k}}$$
de onde se obtém
$$2^{n_k} = 3\times(2^{n_k - n_1} + 2^{n_k-n_2} + \cdots + 1)$$
que é absurdo porque $2^{n_k}$ não é divisível por $3$.&lt;br /&gt;
&lt;br /&gt;
E é assim que se destroem os sonhos de uma criança...

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6670678395926090717'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6670678395926090717'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2019/02/pocket-maths-folding-halves-into-thirds.html' title='Pocket maths: folding halves into thirds'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjN8V9O5I3EjBs2mnWCMbL2VyAhajQhgROA8c4GXfFUrbsGI0D1ZOj8z8UENFzXcgZVlGcifUKCEAEReDcb5BmzA7ca6-VPoSy27axvLCzKmjnKQgADAhTJ0xIUFtAS8bBoIz-_TLdcsNk/s72-c/paper_folded.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-2044791714560395196</id><published>2019-01-27T23:27:00.000+00:00</published><updated>2019-01-27T23:27:46.434+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="mental maths"/><category scheme="http://www.blogger.com/atom/ns#" term="pocket maths"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><title type='text'>Pocket maths: how to compute averages in your head</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

Being able to do basic arithmetic calculations in your head is a great skill. Not because it is sexy but because it is useful in your daily life: it can help you check the change you are given when shopping, it can help you know if you will have enough money to pay for your groceries, it can help you estimate how much things cost after the discounts, etc...&lt;br /&gt;
&lt;br /&gt;
This often reduces to being able to sum and subtract decently; sometimes you need to make a couple of small multiplications, but that is it.&lt;br /&gt;
&lt;br /&gt;
More likely than not, you don&#39;t need to compute averages every day. But sometimes you just want the scoring average of your team for the past few games, or the average price per person of a given meal, or the average time you spent stuck in traffic this past week... And averages may appear nastier than simply adding or subtracting, because averages also require you to perform a division: in fact, you have to add all the numbers you want and then divide the total by how many numbers there were.&lt;br /&gt;
&lt;br /&gt;
As an example, say I went to have a meal with three friends and we paid $7$, $8$, $10$ and $12$ euros for our meals. What was the average price? In school we learned to do $7+8+10+12 = 37$ and then $37/4 = 9.25$. Sure, this wasn&#39;t to bad if you are not afraid to do maths, but:
&lt;ol&gt;
&lt;li&gt;If you are good with mental maths, you can get to this result even faster;&lt;/li&gt;
&lt;li&gt;If you hate doing weird mental calculations, you can get to a nice estimation with little effort.&lt;/li&gt;
&lt;/ol&gt;
For the &quot;method&quot; you just need three small steps. First, you guess what the average will be. It is good if you guess close, but it is often more useful if your guess is a round number. So $9$ or $10$ would be useful guesses but $9.2$ maybe not so much. Say I was guessing $10$. Then I just have to find the &quot;score&quot; of my guess, which is done by adding or subtracting the &quot;points&quot; each number gives. The &quot;points&quot; a number gives are just the difference between the number and my guess. So $7$ and $8$ are worth $-3$ and $-2$ points, because they fall short of my guess by $3$ and $2$ units respectively. $10$ is worth $0$ points and $12$ is worth $2$ points, so my final score would be $-3$. In the end, you just divide the score by how many numbers you dealt with, and add that to the guess: so $-3/4 = -0.75$ and $10 + (-0.75) = 9.25$.&lt;br /&gt;
&lt;br /&gt;
Does this look bad? Maybe it does, but this is actually quite decent. If you didn&#39;t want to do $-3/4$ in your head you could even notice that $3/4$ is greater than $1/2$ and so the average price for the meal was between $9$ and $9.5$...&lt;br /&gt;
As you use this &quot;trick&quot; a couple of times, you will get good at getting decent first guesses, which means you will get a very small final score, which means you will be able to get a very good estimation even if you can&#39;t make the final division in your head! What is more, the final division is usually easier than the division of the standard way to compute the average because the number you are dividing is much smaller.&lt;br /&gt;
&lt;br /&gt;
As a little test, try computing the average of these grades: $13$, $15$, $15$, $13$, $14$, $16$, $13$, $15$. I &lt;i&gt;just&lt;/i&gt; wrote them down so I will be doing this as I write; I am guessing $14$, which means the scores are $-1$,$1$,$1$,$-1$,$0$,$2$,$-1$,$1$ adding up to a grand total of $2$, that I shall divide by $8$. So $2/8 = 1/4 = 0.25$ and the actual average is $14.25$. Don&#39;t believe me? Use a calculator. Do you think I got lucky? Maybe. But so will you. What if there were $7$ numbers instead of $8$? Then $2/7$ would be a bit more than $0.25$ and below $0.33$ (because of $2/6=1/3$) and so the average would be around $14.3$. These estimations are often enough for you &lt;b&gt;and&lt;/b&gt; many people will be impressed by how accurate you can be in such a short time... not because the calculations were extremely difficult but because people aren&#39;t expecting you to even try.&lt;br /&gt;
&lt;br /&gt;
For the sake of completeness, and you don&#39;t have to read this if you don&#39;t want to, I will just include the &quot;proof&quot; that the method I described works. Let us call $s$ to my guess, $\bar{x}$ to the average and $x_1, x_2, \cdots, x_n$ to the numbers you want to average out. The number $x_i$ contributes with $x_i - s$ points to the score, so the total score $T$ of my guess is
$$T = (x_1 - s) + (x_2 - s) + \cdots + (x_n - s) = x_1 + x_2 + \cdots + x_n - n\times s$$
which I then divide by $n$ and add to the guess $s$.&lt;br /&gt;
In one equation, my method gives
$$
\begin{align}s + \frac{T}{n} &amp;= s + \frac{x_1 + x_2 + \cdots + x_n - n\times s}{n} \\
&amp;= s + \frac{x_1 + x_2 + \cdots + x_n}{n} - s\\
&amp;= \frac{x_1 + x_2 + \cdots + x_n}{n} = \bar{x}\end{align}$$
which means my method isn&#39;t dark magic!&lt;br /&gt;
&lt;br /&gt;
Please use the comment section below to share any mental maths tricks you know and/or use!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Saber fazer contas de cabeça é uma habilidade bestial. Não por ser sexy mas sim porque é extremamente útil nas nossas vidas quotidianas: ajuda-nos a verificar o troco quando compramos algo, ajuda-nos a antever se temos dinheiro suficiente na carteira para pagar as compras ou se temos de usar o cartão, ajuda-nos a estimar o preço dos artigos depois de aplicados os descontos, etc...&lt;br /&gt;
&lt;br /&gt;
Geralmente isto reduz-se a saber somar e subtrair bem de cabeça; às vezes também precisamos de fazer algumas multiplicações pequenas, mas não costuma passar daí.&lt;br /&gt;
&lt;br /&gt;
Claro que o caso muda de figura quando estamos a falar de calcular médias de cabeça. Acho pouco provável que quem estiver a ler isto tenha a necessidade de calcular médias de cabeça com muita frequência, mas de vez em quando gostávamos de conseguir ter uma ideia da média de pontos que a nossa equipa preferida tem marcado, ou saber qual foi o preço médio por pessoa de certa refeição, ou então estimar o tempo médio que gastámos no trânsito esta semana. E fazer médias de cabeça adivinha-se ser mais chato que só fazer somas ou subtações, porque para calcular médias também é preciso fazer uma divisão: na verdade, fazer a média de alguns números é somá-los a todos e depois dividir por quantos eram.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, suponhamos que eu fui jantar com três amigos e pagámos $7$, $8$, $10$ e $12$ euros pelas nossas refeições. Qual foi o preço médio? Para calcular a média pelo método clássico somamos tudo, $7+8+10+12 = 37$ e depois dividimos por $4$, que dá $37/4 = 9.25$. Claro que esta conta não seria particularmente desagradável de se fazer de cabeça, mas:
&lt;ol&gt;
&lt;li&gt;Aqueles que já são bons a fazer contas de cabeça podem chegar ao resultado final ainda mais depressa;&lt;/li&gt;
&lt;li&gt;Quem não gosta de fazer contas &quot;chatas&quot; de cabeça pode chegar a uma boa estimativa final sem muito trabalho mental.&lt;/li&gt;
&lt;/ol&gt;
O meu &quot;método&quot; é composto por três passos. Primeiro, adivinhamos quanto é que a média final vai ser. Dá jeito que o nosso palpite esteja perto da média certa mas também costuma ser mais útil que o nosso palpite seja um número redondo. Ou seja, os palpites $9$ ou $10$ são palpites úteis ao passo que $9.2$, apesar de estar mais perto da resposta certa, vai dar mais trabalho. Depois de termos o nosso palpite, vamos calcular qual é a &quot;pontuação&quot; do nosso palpite. Para a &quot;pontuação&quot; do nosso palpite temos de ver com quantos &quot;pontos&quot; é que cada número contribui e depois somamos tudo. Um número que seja mais pequeno que o nosso palpite contribui com &quot;pontos&quot; negativos e um número acima do nosso palpite contribui com &quot;pontos&quot; positivos; a quantidade de pontos é simplesmente a distância do número ao palpite. No nosso exemplo, e assumindo que o meu palpite inicial era $10$, temos que os números $7$ e $8$ dão &quot;pontos&quot; negativos, respetivamente $-3$ e $-2$. O número $10$ contribui com $0$ e o número $12$ contribui com $2$. Somando essas contribuições todas dá $-3$. O último passo é dividir a contribuição total pelo número de contribuintes e somar isso ao palpite: $-3$ (a contribuição total) a dividir por $4$ (o número de contribuintes) dá $-3/4 = -0.75$ que somado ao palpite dá $10 + (-0.75) = 9.25$, a média final.&lt;br /&gt;
&lt;br /&gt;
É bastante provável que o método que descrevi pareça demasiado complicado... Mas há muitas coisas muito simples que são muito complicadas de explicar! O melhor que têm a fazer é testar o método e decidirem se é útil ou não. Para as pessoas que não queriam/conseguiam fazer a divisão $-3/4$ de cabeça, bastava notar que $3/4$ é maior que $1/2$ e portanto a média final era inferior a $9.5$ mas superior a $9$.&lt;br /&gt;
À medida que forem usando este truque vão começar a usar palpites iniciais melhores, o que significa que a &quot;pontuação&quot; final do palpite vai ser menor, o que significa que a divisão final vai ser mais simples (e vai dar um número mais pequeno) e portanto as estimativas vão ficar cada vez melhores. De qualquer das maneiras, a divisão que tem de ser feita neste método costuma ser mais simples que a divisão final se fizerem as contas usuais.&lt;br /&gt;
&lt;br /&gt;
Como pequeno teste, tentem calcular a média dos seguintes números: $13$, $15$, $15$, $13$, $14$, $16$, $13$, $15$. Acabei de inventar os números, portanto este exemplo não foi fabricado para ser simpático. Eu vou adivinhar que a média é $14$, o que significa que as contribuições são $-1$,$1$,$1$,$-1$,$0$,$2$,$-1$,$1$, que somadas dão $2$. Como há $8$ contribuintes, calculo $2/8 = 1/4 = 0.25$, que somado ao palpite $14$ dá uma média final de $14.25$. Quem não acreditar pode usar a calculadora para confirmar. Será que eu tive sorte por causa da divisão que tive de fazer no fim..? Talvez, mas vocês também terão sorte nas contas que vos aparecerem à frente. O que teria acontecido se fossem $7$ números em vez de $8$? $2/7$ já não é tão fácil de calcular quanto $2/8$, mas neste caso podíamos notar que $2/7$ é maior que $0.25$ mas menor que $0.33$ (por causa de $2/6=1/3$) e portanto a média final estaria perto de $14.3$. Este tipo de estimativas costuma ser mais do que suficiente para qualquer propósito prático &lt;b&gt;e&lt;/b&gt; muitas pessoas ficarão impressionadas pela exatidão da vossa estimativa &lt;i&gt;versus&lt;/i&gt; o tempo que demoraram a calculá-a: não porque as contas fossem extremamente complicadas mas porque as pessoas não estão à espera que vocês se dêem ao trabalho.&lt;br /&gt;
&lt;br /&gt;
Para terminar, vou provar que o meu método não é magia negra. Obviamente o método tem um fundamento matemático, que explano aqui: suponha-se que quero calcular a média dos números $x_1, x_2, \cdots, x_n$, vou chamar $s$ ao meu palpite e vou chamar $\bar{x}$ à média real dos vários $x_i$, que se calcula com a fórmula
$$\frac{x_1 + x_2 + \cdots + x_n}{n} = \bar{x}$$
Ora cada número $x_i$ contribui com $x_i - s$ &quot;pontos&quot; para a pontuação total $P$ do meu palpite, logo a pontuação total do meu palpite é
$$P = (x_1 - s) + (x_2 - s) + \cdots + (x_n - s) = x_1 + x_2 + \cdots + x_n - n\times s$$
que depois de calculada (a pontuação total) deve ser dividida por $n$ e somada ao palpite inicial $s$. Assim, numa única fórmula o meu método é
$$\begin{align}s + \frac{P}{n} &amp;= s + \frac{x_1 + x_2 + \cdots + x_n - n \times s }{n} \\
&amp;= s + \frac{x_1 + x_2 + \cdots + x_n}{n} - s \\
&amp;= \frac{x_1 + x_2 + \cdots + x_n}{n} = \bar{x}\end{align}$$
&lt;br /&gt;
Partilhem comigo os vossos métodos de cálculo mental na secção de comentários em baixo.

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/2044791714560395196'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/2044791714560395196'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2019/01/pocket-maths-how-to-compute-averages-in.html' title='Pocket maths: how to compute averages in your head'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-5801936956575074545</id><published>2019-01-13T19:59:00.001+00:00</published><updated>2019-01-13T19:59:40.377+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cryptography"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="matrices"/><category scheme="http://www.blogger.com/atom/ns#" term="modular arithmetics"/><category scheme="http://www.blogger.com/atom/ns#" term="project"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Introduction to the Hill Cipher</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8zD86XtQ2-XAwkDs3YBCGPYbbISTzF9q2_sHyzyj3DghQlJBbcu5p0yo13Ija0oJPT1DgMYYisq8Nm_fhtZi7Up2-MvkKhDCTJRJnGkl2aJtzbelIr1IkNK_5jR763RvmSwys9Tt1BHg/s1600/cryptography.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8zD86XtQ2-XAwkDs3YBCGPYbbISTzF9q2_sHyzyj3DghQlJBbcu5p0yo13Ija0oJPT1DgMYYisq8Nm_fhtZi7Up2-MvkKhDCTJRJnGkl2aJtzbelIr1IkNK_5jR763RvmSwys9Tt1BHg/s320/cryptography.jpg&quot; width=&quot;320&quot; height=&quot;320&quot; data-original-width=&quot;550&quot; data-original-height=&quot;550&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

The &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Hill_cipher&quot;&gt;Hill cipher&lt;/a&gt; is a very simple cipher that works by using modular arithmetic and matrices.&lt;br /&gt;
&lt;br /&gt;
In a nutshell, your key is a matrix in some $\mathbb{Z}_m$ and you encrypt messages by breaking them up into pieces and then multiplying the pieces by the key matrix. That&#39;s it.&lt;br /&gt;
&lt;br /&gt;
I will be giving a workshop on this subject in a near future, and so I decided to write a Python notebook with a brief explanation of how the Hill cipher works, as well as providing an implementation of said cipher. The notebook can be downloaded and read &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/RojerGS/projects/blob/master/misc/HillCipher.ipynb&quot;&gt;here&lt;/a&gt;. I will be glad if you leave any suggestions/comments in the section below!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

A &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Hill_cipher&quot;&gt;cifra de Hill&lt;/a&gt; é uma cifra simples que faz uso de noções de aritmética modular e de álgebra linear (mais concretamente, matrizes).&lt;br /&gt;
&lt;br /&gt;
Em duas frases, a cifra de Hill tem como chave uma matriz num dado $\mathbb{Z}_m$ e o modo como encripta mensagens é partindo-a em bocados com o mesmo tamanho e depois multiplicando a matriz chave por esses bocados.&lt;br /&gt;
&lt;br /&gt;
Num futuro próximo eu vou dar um workshop sobre o assunto e por isso decidi escrever um notebook em Python com uma breve explicação da cifra, bem como com uma implementação da mesma cifra. O notebook está disponível para ser lido e descarregado &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/RojerGS/projects/blob/master/misc/HillCipher.ipynb&quot;&gt;aqui&lt;/a&gt;. Se tiverem alguma sugestão ou comentário, estão à vontade para o deixarem na secção em baixo.

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/5801936956575074545'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/5801936956575074545'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2019/01/introduction-to-hill-cipher.html' title='Introduction to the Hill Cipher'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8zD86XtQ2-XAwkDs3YBCGPYbbISTzF9q2_sHyzyj3DghQlJBbcu5p0yo13Ija0oJPT1DgMYYisq8Nm_fhtZi7Up2-MvkKhDCTJRJnGkl2aJtzbelIr1IkNK_5jR763RvmSwys9Tt1BHg/s72-c/cryptography.jpg" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-4646849952174080975</id><published>2018-12-26T01:43:00.004+00:00</published><updated>2018-12-26T01:43:49.797+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="games"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="project"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="pygame"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>DumbFire, a simple shooting game</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijNfRpWGJ4cRLm9FDldxTY1nqwoq4aOocbfYfmRdFWKuMur_kl5cV57LIjrprGqKXAEsuNR8FjPUQD78VdsNqJa7wKU5ldaHHb6fLnLylQaMDtfXMh1TkeZjz6xATSZLV9XIlKO32udIY/s1600/dumbFireMidGame.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijNfRpWGJ4cRLm9FDldxTY1nqwoq4aOocbfYfmRdFWKuMur_kl5cV57LIjrprGqKXAEsuNR8FjPUQD78VdsNqJa7wKU5ldaHHb6fLnLylQaMDtfXMh1TkeZjz6xATSZLV9XIlKO32udIY/s320/dumbFireMidGame.gif&quot; width=&quot;320&quot; height=&quot;200&quot; data-original-width=&quot;800&quot; data-original-height=&quot;500&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;
DumbFire is a very simple shooting game that I created with Python and pygame and you can find the code &lt;a href=&quot;https://github.com/RojerGS/games/tree/master/dumbfire&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;. As of now, the game does not have a menu whatsoever nor it has any kind of instructions...&lt;br /&gt;
&lt;i&gt;(btw, to play it use the WASD keys to move and the space bar to shoot; if the coloured balls hit you, you lose health; if you shoot them, you get health back)&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
I have been incredibly busy so I am not sure I will tidy this up any time soon but feel free to fork the repo in GitHub and to add different types of enemies and maybe some kind of power-up or whatnot. Actually, I would be very interested in hearing from you the answer to: &lt;i&gt;if I could only add one single extra functionality to the game, what would that be?&lt;/i&gt;&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;
O jogo DumbFire é um jogo simplecíssimo de tiros que eu fiz com Python e com pygame. O código está no &lt;a href=&quot;https://github.com/RojerGS/games/tree/master/dumbfire&quot; target=&quot;_blank&quot;&gt;repo usual&lt;/a&gt; e convido-vos a fazerem uma cópia do mesmo para experimentarem alterar os tipos de inimigos, talvez juntar um ou outro power-up, etc. De momento o jogo não tem qualquer tipo de menu nem instruções.&lt;br /&gt;
&lt;i&gt;(para jogar, usem as teclas WASD para mover a bola e o espaço para disparar; se as bolas coloridas chocarem contra vocês, perdem vida; se acertarem nas bolas coloridas, ganham vida)&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Tenho andado com pouco tempo e portanto não acho que vá dar os toques finais neste joguinho em breve... Se puderem, gostava que partilhassem comigo qual seria o detalhe/funcionalidade que diriam que eu devia mesmo pôr neste jogo se eu já só pudesse implementar mais uma coisa.&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/4646849952174080975'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/4646849952174080975'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/12/dumbfire-simple-shooting-game.html' title='DumbFire, a simple shooting game'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijNfRpWGJ4cRLm9FDldxTY1nqwoq4aOocbfYfmRdFWKuMur_kl5cV57LIjrprGqKXAEsuNR8FjPUQD78VdsNqJa7wKU5ldaHHb6fLnLylQaMDtfXMh1TkeZjz6xATSZLV9XIlKO32udIY/s72-c/dumbFireMidGame.gif" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-7309978911929849721</id><published>2018-12-20T16:09:00.000+00:00</published><updated>2018-12-20T16:09:41.121+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="binary"/><category scheme="http://www.blogger.com/atom/ns#" term="bitwise operations"/><category scheme="http://www.blogger.com/atom/ns#" term="circuits"/><category scheme="http://www.blogger.com/atom/ns#" term="electronics"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="logic"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="simulation"/><category scheme="http://www.blogger.com/atom/ns#" term="visualization"/><title type='text'>Building an 8-bit addition calculator with circuits</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8mPVKJAmxCJtW1Khvu71F1tEnrVrp7TdgjWKXzIsQEEpgXPcpXbvLk7SWyYw1_F2aIUpS-MhPhLLxMONmswaAEQ2nyRSQEz-kOFKsPLRPeli4YPjl4vXOl9DjQQ1cy4rlMJnmZhfQFEY/s1600/circuits_half_adder.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8mPVKJAmxCJtW1Khvu71F1tEnrVrp7TdgjWKXzIsQEEpgXPcpXbvLk7SWyYw1_F2aIUpS-MhPhLLxMONmswaAEQ2nyRSQEz-kOFKsPLRPeli4YPjl4vXOl9DjQQ1cy4rlMJnmZhfQFEY/s1600/circuits_half_adder.png&quot; data-original-width=&quot;567&quot; data-original-height=&quot;252&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

I have a childhood friend that had very interesting toys... He used to play around with circuits, multimeters, LED lights, small batteries, etc. I loved going to his house and watch him play with all that. That is probably why I find circuits (in their basic form) very interesting: the current flowing and the logic gates operating on the circuits and whatnot.&lt;br /&gt;
&lt;br /&gt;
Because of that, in this post I will show you how to build an 8-bit addition calculator just with circuits! For that I will be using &lt;a href=&quot;https://logic.ly/demo&quot; target=&quot;_blank&quot;&gt;logic.ly&lt;/a&gt;, a circuits simulator that I can run in my browser.&lt;br /&gt;
&lt;br /&gt;
The best way to go about this is by starting with small components and then using a nice feature of logic.ly, which enables one to create &quot;integrated circuits&quot;: it takes one circuit we created and transforms it into a single piece.&lt;br /&gt;
&lt;br /&gt;
Of course that before anything else one must know how to add two numbers in binary. It is essentially the same as in with decimal numbers, except that $1 + 1 = 10$ now. To create an addition calculator, we will develop a circuit that adds two numbers bit by bit and that takes care of carries from one place to the other.&lt;br /&gt;
&lt;br /&gt;
The image in the beginning of the post is a circuit that adds two bits $A$ and $B$ together. The result is in $S$ and the $Cout$ light bulb represents the carry digit we may get. This small circuit could be used to add the least significant digits in a sum, storing the least significant digit of the result in $S$ and then signaling if there is any carry in $Cout$.&lt;br /&gt;
The idea will be to create a circuit that adds two bits of the same significance (possibly taking a carry bit from the previous operation) and then returning both the resulting bit and a possible carry digit.&lt;br /&gt;
&lt;br /&gt;
Let us start by understanding how one comes up with the first circuit shown, a &lt;a href=&quot;https://en.wikipedia.org/wiki/Adder_(electronics)#Half_adder&quot; target=&quot;_blank&quot;&gt;half adder&lt;/a&gt; as it is called in electronics. To do that we will summarize the possible combinations of input bits $A, B$ in a table, together with the results of adding them:&lt;br /&gt;
\[
\begin{array}{|c|c|c|c|}
\hline
A &amp; B &amp; S &amp; Cout\\ \hline
0 &amp; 0 &amp; 0 &amp; 0\\ \hline
0 &amp; 1 &amp; 1 &amp; 0\\ \hline
1 &amp; 0 &amp; 1 &amp; 0\\ \hline
1 &amp; 1 &amp; 0 &amp; 1\\ \hline
\end{array} \]
&lt;br /&gt;
From the table above one can see clearly that $S$ should be $1$ only when there is exactly one input equal to $1$ and $Cout$ should be $1$ only when both inputs are equal to $1$; this means that $S = A\stackrel{\cdot}{\vee}B$ and $Cout = A\wedge B$ (the symbol $\stackrel{\cdot}{\vee}$ is the exclusive disjunction, also known as XOR).&lt;br /&gt;
&lt;br /&gt;
The next step is creating a circuit that has three inputs $A$, $B$ and $Cin$, which represent two bits of the same significance and a carry bit from a least significant calculation (respectively) and returns the resulting bit $S$, as well as a carry digit $Cout$. If we build this, we will get a &lt;a href=&quot;https://en.wikipedia.org/wiki/Adder_(electronics)#Full_adder&quot; target=&quot;_blank&quot;&gt;full adder&lt;/a&gt;. How does one do it?&lt;br /&gt;
&lt;br /&gt;
First we notice that $S$ will only be $1$ if: all three input bits are $1$ or only one input bit is $1$. We already know if only one of $A$, $B$ is $1$, in which case we want $Cin$ to be $0$. If $A$,$B$ are both $1$ or both $0$, we want $Cin$ to be $1$. Joining the two we can write $$S = [(A\stackrel{\cdot}{\vee}B) \wedge \lnot Cin] \vee [\lnot(A \stackrel{\cdot}{\vee} B) \wedge Cin]$$
Carefull inspection shows that this can be simplified to $$S = (A \stackrel{\cdot}{\vee} B) \stackrel{\cdot}{\vee} Cin$$
In fact, that is exactly what is written in the first expression: $S$ is $1$ whenever only one of $A \stackrel{\cdot}{\vee} B$, $Cin$ is $1$.&lt;br /&gt;
&lt;br /&gt;
Having computed $S$ we are only left with computing $Cout$. We know that there will be a carry digit if at least two of the input bits are $1$. We already know when $A$ and $B$ are both $1$, so the other alternative is when only one of $A, B$ is $1$ and $Cin$ is also $1$, hence $$Cout = (A \wedge B) \vee ([A \stackrel{\cdot}{\vee} B] \wedge Cin)$$
We use the exclusive disjuntion instead of the disjunction on the right because that allows us to reuse information we already have. If we put everything together in a circuit, we get this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhILiXCqbfxjF3162sZE4giaBRbqhh_nBYFZwSA-elUNEqlbPsllnOCSnXU6P0xDvsAGebQiNRDqmQcXKlnhydTKabkIu7us-2FPxW_Hf-HmWyG2Eh9aDAw2moHvmxpAqLmTlb83EMX58w/s1600/circuits_full_adder.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhILiXCqbfxjF3162sZE4giaBRbqhh_nBYFZwSA-elUNEqlbPsllnOCSnXU6P0xDvsAGebQiNRDqmQcXKlnhydTKabkIu7us-2FPxW_Hf-HmWyG2Eh9aDAw2moHvmxpAqLmTlb83EMX58w/s1600/circuits_full_adder.png&quot; data-original-width=&quot;667&quot; data-original-height=&quot;418&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Because all switches are turned off, we are computing $0 + 0$ which is $0$, as the two light bulbs show.&lt;br /&gt;
If we compare the symbols of the logic gates with the first image in the post, we see two XOR gates on the top, an OR gate on the bottom right (the XOR gates are equal to the OR gate with an extra line on the left) and two AND gates centred on the bottom of the image.&lt;br /&gt;
&lt;br /&gt;
With the full adder in place, we aggregate everything and use logic.ly&#39;s feature of creating an integrated circuit which creates this piece:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-3DNb8Flftf2IWlR_f_KzIpKkgbmc9_6xaSI759DneoHr5ev-h3W08XDz_66lX2turbNv5g5tgTAYYmXgpbMZt7bHtiY14KcGY9uZCQfvrGPSb_cMG4st3rOPF_A6Te0qg8rTZudmQ5I/s1600/circuits_FA_IC.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-3DNb8Flftf2IWlR_f_KzIpKkgbmc9_6xaSI759DneoHr5ev-h3W08XDz_66lX2turbNv5g5tgTAYYmXgpbMZt7bHtiY14KcGY9uZCQfvrGPSb_cMG4st3rOPF_A6Te0qg8rTZudmQ5I/s1600/circuits_FA_IC.png&quot; data-original-width=&quot;147&quot; data-original-height=&quot;98&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
This piece is a compact representation of the circuit I showed above. With four of these it is straightforward to create a 4-bit addition calculator: a calculator that takes two 4-bit numbers and returns its result:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQxlQ0P1vUAHCSVQJJCvIMOQFNFXMRfPro0g5hm2-H0pV3tvJ7sAxXcl3AfJTE3_Cd25FeeXuab7edUqrcwTa0CejpWl4w2NJAxqP0CbZBbiUO6FTZbNpKI11zxNSgcD3Zb_3zy6tP-yE/s1600/circuits_4bit_adder.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQxlQ0P1vUAHCSVQJJCvIMOQFNFXMRfPro0g5hm2-H0pV3tvJ7sAxXcl3AfJTE3_Cd25FeeXuab7edUqrcwTa0CejpWl4w2NJAxqP0CbZBbiUO6FTZbNpKI11zxNSgcD3Zb_3zy6tP-yE/s1600/circuits_4bit_adder.png&quot; data-original-width=&quot;1025&quot; data-original-height=&quot;495&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
The image above shows the calculator computing the sum $5 + 12 = 17$. Notice how we plug in a constant $0$ on the first $Cin$ and how the last $Cout$ is connected to the fifth light bulb. Renaming the switches and plugging a switch into the first $Cin$ allows me to create yet another integrated circuit that already adds 4-bit numbers! This is how the modified circuit will look like, before creating the IC:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPWXRvvX_VNZAoMOtC0zJ8adIvSw5gT6gupOehKju-NJnbNSKpi9gywWZChE4PwL8yVp1ScF1ZtN1wjFAPbCfr3yDrHylBUV8kKqJqL-_dZmf025Ii_aAuuwZfq3LYCnXXt8Xx1UD952Q/s1600/circuits_4bit_adder_IC.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPWXRvvX_VNZAoMOtC0zJ8adIvSw5gT6gupOehKju-NJnbNSKpi9gywWZChE4PwL8yVp1ScF1ZtN1wjFAPbCfr3yDrHylBUV8kKqJqL-_dZmf025Ii_aAuuwZfq3LYCnXXt8Xx1UD952Q/s1600/circuits_4bit_adder_IC.png&quot; data-original-width=&quot;1052&quot; data-original-height=&quot;502&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
With two of those, one can create an 8-bit addition calculator, as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjrld4FCiLp4g9oOnED3fb_iEx63UshykV3DWpR5ZYe9EjuRV6vZ_PnUdplIYiONx2QjAaOwJl_oOUq9OHkzTQiB80gT_OJlNdQGu4xxaY34X4UVw_PdRsm6KC9HEjMLIvr_FPhaSoeOk/s1600/circuits_8bit_calculator.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjrld4FCiLp4g9oOnED3fb_iEx63UshykV3DWpR5ZYe9EjuRV6vZ_PnUdplIYiONx2QjAaOwJl_oOUq9OHkzTQiB80gT_OJlNdQGu4xxaY34X4UVw_PdRsm6KC9HEjMLIvr_FPhaSoeOk/s1600/circuits_8bit_calculator.png&quot; data-original-width=&quot;991&quot; data-original-height=&quot;394&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
In this particular screenshot, the calculator is computing the sum $73 + 37 = 110$.&lt;br /&gt;
&lt;br /&gt;
And this is it. In the future I might try to build the calculator with actual physical parts, who knows? If you try logic.ly and create something cool, consider sharing it in the comments! Does anyone have the patience to build a 16-bit number adder? Or maybe a circuit that performs subtraction?

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Tenho um amigo de infância que tinha uns brinquedos super engraçados... Ele costumava brincar com circuitos, multímetros, LEDs, pilhas, etc. Adorava ir a casa dele e vê-lo mexer naquilo tudo e ele costumava ensinar-me qualquer coisinha. É provavelmente por causa disso que circuitos elétricos me fascinam tanto: como as portas lógicas conseguem fazer tudo o que fazem quando bem conjugadas.&lt;br /&gt;
&lt;br /&gt;
É por causa desse fascínio que, neste post, vou mostrar como construir uma calculadora (que só sabe somar) com circuitos! Para isso vamos usar o &lt;a href=&quot;https://logic.ly/demo&quot; target=&quot;_blank&quot;&gt;logic.ly&lt;/a&gt;, um simulador de circuitos que se pode correr no browser.&lt;br /&gt;
&lt;br /&gt;
A melhor maneira de fazer isto é começando com circuitos mais pequenos e depois usar uma funcionalidade do logic.ly que permite compactar circuitos em peças únicas.&lt;br /&gt;
&lt;br /&gt;
Claro que antes de começar a montar seja o que for é preciso saber somar em binário. É essencialmente igual a fazer somas no sistema decimal, mas agora $1 + 1 = 10$. Para criar a calculadora vamos desenvolver um circuito que os soma bit a bit, tratando também do &quot;e vai $1$&quot;, que chamamos &quot;carry&quot; em inglês (lamentavelmente não arranjei nenhuma outra designação para este &quot;e vai $1$&quot;, e portanto é esta a designação que vou usar durante o post).&lt;br /&gt;
&lt;br /&gt;
A imagem no início do post é de um circuito que soma dois bits $A$ e $B$. O bit resultante fica em $S$ e o &quot;e vai $1$&quot;, se houver, fica em $Cout$, sinalizado pela lâmpada. Este circuito em particular pode ser usado para somar os dois dígitos menos significantes, i.e. pode ser usado para obter o dígito mais à direita numa soma.&lt;br /&gt;
A ideia vai ser criar um circuito que vá calculando cada bit do resultado, olhando para os bits respetivos do input, e que vá transferindo os &quot;e vai $1$&quot; sempre que necessário.&lt;br /&gt;
&lt;br /&gt;
Vamos começar por entender como criar o primeiro circuito de todos, a que chamamos &lt;a href=&quot;https://en.wikipedia.org/wiki/Adder_(electronics)#Half_adder&quot; target=&quot;_blank&quot;&gt;half adder&lt;/a&gt; em eletrónica. Para isso vamos começar por sumarizar todas as combinações que podemos ter no input para $A$ e $B$ e sistematizá-las numa tabela, juntamente com os resultados pretendidos (que obtemos se somarmos $A$ com $B$):&lt;br /&gt;
\[
\begin{array}{|c|c|c|c|}
\hline
A &amp; B &amp; S &amp; Cout\\ \hline
0 &amp; 0 &amp; 0 &amp; 0\\ \hline
0 &amp; 1 &amp; 1 &amp; 0\\ \hline
1 &amp; 0 &amp; 1 &amp; 0\\ \hline
1 &amp; 1 &amp; 0 &amp; 1\\ \hline
\end{array} \]
&lt;br /&gt;
Pela tabela em cima podemos ver que $S$ deve ser $1$ quando apenas um dos inputs é igual a $1$ e $Cout$ deve ser $1$ quando os dois inputs são $1$; isto significa que $S = A \stackrel{\cdot}{\vee} B$ e $Cout = A\wedge B$ (o símbolo $\stackrel{\cdot}{\vee}$ é a disjunção exclusiva, também conhecida como XOR).&lt;br /&gt;
&lt;br /&gt;
O próximo passo é criar um circuito com três inputs $A$, $B$ e $Cin$, que representam respetivamente dois bits dos números que queremos somar e um possível &quot;e vai $1$&quot; do passo anterior, e que devolve o bit resultante em $S$, bem como o possível &quot;vai $1$&quot; desta adição em $Cout$. Se construirmos isto obtemos um &lt;a href=&quot;https://en.wikipedia.org/wiki/Adder_(electronics)#Full_adder&quot; target=&quot;_blank&quot;&gt;full adder&lt;/a&gt;. Como o fazemos?&lt;br /&gt;
&lt;br /&gt;
Primeiro notamos que $S$ só é $1$ se: ou os três bits de input forem $1$ ou se apenas um bit de input for $1$. Já temos como saber se apenas $A$ ou apenas $B$ são $1$, caso em que queremos que $Cin$ seja $0$. Se $A$ e $B$ têm o mesmo valor, então precisamos que $Cin$ seja $1$. Juntando estas duas premissas obtemos $$S = [(A\stackrel{\cdot}{\vee}B) \wedge \lnot Cin] \vee [\lnot(A \stackrel{\cdot}{\vee} B) \wedge Cin]$$
Se olharmos com atenção percebemos que podemos simplificar esta expressão para $$S = (A \stackrel{\cdot}{\vee} B) \stackrel{\cdot}{\vee} Cin$$
De facto, isto é exatamente o que está escrito na primeira expressão: $S$ é $1$ sempre que apenas um de $A \stackrel{\cdot}{\vee} B$ ou $Cin$ tenha o valor $1$.&lt;br /&gt;
&lt;br /&gt;
Tendo calculado $S$, falta-nos calcular $Cout$. Sabemos que &quot;vai $1$&quot; se dois ou mais dos bits de input forem $1$. Já sabemos quando é que $A$ e $B$ são os dois $1$, portanto só falta ver quando apenas um de $A$, $B$ é $1$ e $Cin$ também é $1$, de onde vem $$Cout = (A \wedge B) \vee ([A \stackrel{\cdot}{\vee} B] \wedge Cin)$$
Usamos a disjunção exclusiva em vez da disjunção (&quot;normal&quot;) porque desse modo podemos reutilizar uma porta lógica que já temos no circuito. Se montarmos tudo, obtemos o seguinte:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhILiXCqbfxjF3162sZE4giaBRbqhh_nBYFZwSA-elUNEqlbPsllnOCSnXU6P0xDvsAGebQiNRDqmQcXKlnhydTKabkIu7us-2FPxW_Hf-HmWyG2Eh9aDAw2moHvmxpAqLmTlb83EMX58w/s1600/circuits_full_adder.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhILiXCqbfxjF3162sZE4giaBRbqhh_nBYFZwSA-elUNEqlbPsllnOCSnXU6P0xDvsAGebQiNRDqmQcXKlnhydTKabkIu7us-2FPxW_Hf-HmWyG2Eh9aDAw2moHvmxpAqLmTlb83EMX58w/s1600/circuits_full_adder.png&quot; data-original-width=&quot;667&quot; data-original-height=&quot;418&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Porque todos os interruptores estão desligados, estamos a calcular a soma $0 + 0$ que é, obviamente, $0$, tal como as duas lâmpadas desligadas mostram.&lt;br /&gt;
Se compararmos estas portas lógicas com as da primeira imagem do post, vemos que as duas portas usadas no topo são portas XOR, vemos que temos uma porta OR em baixo à direita (com a mesma forma das portas XOR, a diferença é que a porta OR tem um traço a menos) e duas portas AND centradas na parte de baixo da imagem.&lt;br /&gt;
&lt;br /&gt;
Com este circuito feito, compactamos tudo num circuito integrado (uma funcionalidade do logic.ly) para obter a seguinte peça:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-3DNb8Flftf2IWlR_f_KzIpKkgbmc9_6xaSI759DneoHr5ev-h3W08XDz_66lX2turbNv5g5tgTAYYmXgpbMZt7bHtiY14KcGY9uZCQfvrGPSb_cMG4st3rOPF_A6Te0qg8rTZudmQ5I/s1600/circuits_FA_IC.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-3DNb8Flftf2IWlR_f_KzIpKkgbmc9_6xaSI759DneoHr5ev-h3W08XDz_66lX2turbNv5g5tgTAYYmXgpbMZt7bHtiY14KcGY9uZCQfvrGPSb_cMG4st3rOPF_A6Te0qg8rTZudmQ5I/s1600/circuits_FA_IC.png&quot; data-original-width=&quot;147&quot; data-original-height=&quot;98&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Esta peça não é mais do que uma representação compacta do circuito em cima. Com quatro destas peças é facílimo construir uma calculadora que some dois números de 4 bits:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQxlQ0P1vUAHCSVQJJCvIMOQFNFXMRfPro0g5hm2-H0pV3tvJ7sAxXcl3AfJTE3_Cd25FeeXuab7edUqrcwTa0CejpWl4w2NJAxqP0CbZBbiUO6FTZbNpKI11zxNSgcD3Zb_3zy6tP-yE/s1600/circuits_4bit_adder.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQxlQ0P1vUAHCSVQJJCvIMOQFNFXMRfPro0g5hm2-H0pV3tvJ7sAxXcl3AfJTE3_Cd25FeeXuab7edUqrcwTa0CejpWl4w2NJAxqP0CbZBbiUO6FTZbNpKI11zxNSgcD3Zb_3zy6tP-yE/s1600/circuits_4bit_adder.png&quot; data-original-width=&quot;1025&quot; data-original-height=&quot;495&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
A imagem mostra-nos o cálculo $5 + 12 = 17$. Note-se que em baixo usámos um sinal constante igual a $0$ como primeiro $Cin$ e que ligámos o último $Cout$ à quinta lâmpada, a de maior significância (16). Se mudarmos os nomes dos interruptores e se ligarmos um interruptor ao primeiro $Cin$, podemos criar &lt;i&gt;outro&lt;/i&gt; novo circuito integrado! Esta foi a modificação que fiz para poder criar o circuito integrado:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPWXRvvX_VNZAoMOtC0zJ8adIvSw5gT6gupOehKju-NJnbNSKpi9gywWZChE4PwL8yVp1ScF1ZtN1wjFAPbCfr3yDrHylBUV8kKqJqL-_dZmf025Ii_aAuuwZfq3LYCnXXt8Xx1UD952Q/s1600/circuits_4bit_adder_IC.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPWXRvvX_VNZAoMOtC0zJ8adIvSw5gT6gupOehKju-NJnbNSKpi9gywWZChE4PwL8yVp1ScF1ZtN1wjFAPbCfr3yDrHylBUV8kKqJqL-_dZmf025Ii_aAuuwZfq3LYCnXXt8Xx1UD952Q/s1600/circuits_4bit_adder_IC.png&quot; data-original-width=&quot;1052&quot; data-original-height=&quot;502&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Com dois desses circuitos integrados maiores faz-se uma calculadora que some dois números de 8 bits, como se vê de seguida:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjrld4FCiLp4g9oOnED3fb_iEx63UshykV3DWpR5ZYe9EjuRV6vZ_PnUdplIYiONx2QjAaOwJl_oOUq9OHkzTQiB80gT_OJlNdQGu4xxaY34X4UVw_PdRsm6KC9HEjMLIvr_FPhaSoeOk/s1600/circuits_8bit_calculator.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjrld4FCiLp4g9oOnED3fb_iEx63UshykV3DWpR5ZYe9EjuRV6vZ_PnUdplIYiONx2QjAaOwJl_oOUq9OHkzTQiB80gT_OJlNdQGu4xxaY34X4UVw_PdRsm6KC9HEjMLIvr_FPhaSoeOk/s1600/circuits_8bit_calculator.png&quot; data-original-width=&quot;991&quot; data-original-height=&quot;394&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Nesta captura de ecrã em particular a calculadora computou a soma $73 + 37 = 110$.&lt;br /&gt;
&lt;br /&gt;
Está feito! No futuro sou capaz de tentar construir fisicamente esta calculadora com as portas lógicas mesmo, só porque sim. Se forem experimentar o logic.ly e se fizerem alguma coisa engraçada, partilhem-na nos comentários! Será que alguém tem paciência para fazer um circuito que some números de 16 bits? Ou talvez que faça subtrações?


&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;portugues&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/7309978911929849721'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/7309978911929849721'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/12/building-8-bit-addition-calculator-with.html' title='Building an 8-bit addition calculator with circuits'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8mPVKJAmxCJtW1Khvu71F1tEnrVrp7TdgjWKXzIsQEEpgXPcpXbvLk7SWyYw1_F2aIUpS-MhPhLLxMONmswaAEQ2nyRSQEz-kOFKsPLRPeli4YPjl4vXOl9DjQQ1cy4rlMJnmZhfQFEY/s72-c/circuits_half_adder.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-6785553280012068768</id><published>2018-12-03T09:50:00.000+00:00</published><updated>2018-12-03T09:50:52.323+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="approximations"/><category scheme="http://www.blogger.com/atom/ns#" term="continued fractions"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="irrationals"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="pocket maths"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><title type='text'>Pocket maths: good rational approximations</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

An obvious way of creating rational approximations for irrational numbers is by truncating its decimal expansion. For example, $3$, $3.1$ and $3.14$ are all rational approximations of $\pi $; as fractions, those approximations would be written $3$, $\frac{31}{10}$ and $\frac{314}{100} $.&lt;br /&gt;
&lt;br /&gt;
Notice how $\frac{314}{100}$ has $100$ as the denominator and yet only produces an approximation correct up to two decimal places. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Claim:&lt;/b&gt; by using continued fractions one can obtain better rational approximations for irrational numbers. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Method:&lt;/b&gt; if $x $ is an irrational number, instead of truncating its decimal expansion, we can truncate its continued fraction. &lt;br /&gt;
Taking $\pi $ as an example, we have
$$\pi = 3 + \frac1{7 + \frac1{15 + \cdots}} $$
and by taking
$$\pi \approx 3 + \frac17 = \frac{22}{7} $$
we get the approximation $\pi \approx 3.14285\cdots$: it is correct up to two decimal places just as $\frac{314}{100} $, but $7$ is a much smaller denominator than $100$. (And all in all, $\frac{22}{7}$ is a much more elegant fraction that $\frac{314}{100} $)&lt;br /&gt;
&lt;br /&gt;
This can be done for any irrational number and it can be shown that this method produces the &lt;i&gt;best&lt;/i&gt; rational approximations for irrational numbers... maybe a post for another time! &lt;br /&gt;
&lt;br /&gt;
What is your favourite continued fraction?

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Truncar a expansão decimal de um número irracional é uma maneira óbvia de criar aproximações racionais para esse número. Por exemplo, $3$, $3.1$ e $3.14$ são aproximações racionais de $\pi$: estas aproximações escrevem-se $3$, $\frac{31}{10}$ e $\frac{314}{100} $ como frações.&lt;br /&gt;
&lt;br /&gt;
Note-se que a fração $\frac{314}{100}$ tem $100$ como denominador e produz uma aproximação que só está certa até duas casas decimais.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Proposição:&lt;/b&gt; usando frações contínuas conseguimos obter aproximações racionais muito melhores para os números irracionais.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Método:&lt;/b&gt; se $x $ é um número irracional, em vez de truncarmos a sua expansão decimal podemos truncar a sua fração contínua.&lt;br /&gt;
Por exemplo, a fração contínua do $\pi $ é 
$$\pi = 3 + \frac1{7 + \frac1{15 + \cdots}} $$
e se a truncarmos depois do $7$,
$$\pi \approx 3 + \frac17 = \frac{22}{7} $$
obtemos a aproximação $\pi \approx 3.14285\cdots$: está correta até à segunda casa decimal, tal como $\frac{314}{100} $, mas $7$ é um denominador muito mais pequeno que $100$. (Para além de que $\frac{22}{7} $ é uma aproximação muito mais elegante que $\frac{314}{100} $...)&lt;br /&gt;
&lt;br /&gt;
Isto pode ser feito com qualquer número irracional e também se pode mostrar que este método produz as &lt;i&gt;melhores&lt;/i&gt; aproximações racionais para números irracionais... talvez num post futuro!&lt;br /&gt;
&lt;br /&gt;
Qual é a tua fração contínua preferida?

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6785553280012068768'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6785553280012068768'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/12/pocket-maths-good-rational.html' title='Pocket maths: good rational approximations'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-2770506806485944003</id><published>2018-11-26T10:05:00.000+00:00</published><updated>2018-11-26T10:05:00.888+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="complex conjugate"/><category scheme="http://www.blogger.com/atom/ns#" term="complex numbers"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="polynomials"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="twitter proof"/><title type='text'>Twitter proof: the roots go hand in hand</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this twitter proof we will have a look at a rather curious, yet simple, property of real polynomials. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Claim:&lt;/b&gt; if $p(x) = \sum_{i=0}^n a_ix^i $ is a polynomial with real coefficients, then for all complex numbers $z $,
$$p(z) = 0 \iff p(\bar{z}) = 0$$
which means that the complex roots of $p(x) $ come in conjugate pairs. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Twitter proof:&lt;/b&gt; it suffices to show that $p(z) = 0 \implies p(\bar{z}) = 0$. Assume that $p(z) = 0$ and recall that $a_i = \bar{a_i} $:
$$\begin{align}
p(\bar{z}) &amp;= \sum_{i=0}^n a_i\bar{z}^i \\
&amp;= \sum_{i=0}^n \overline{a_iz^i} \\
&amp;= \overline{\sum_{i=0}^n a_iz^i} = \overline{p(z)} = 0
\end {align} $$

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post vamos dar uma olhadela a uma propriedade curiosa, mas simples, dos polinómios com coeficientes reais.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Proposição:&lt;/b&gt; se $p(x) = \sum_{i=0}^n a_ix^i $ é um polinómio com coeficientes reais, então para qualquer número complexo $z $ vem
$$p(z) = 0 \iff p(\bar{z}) = 0$$
o que significa que as raízes complexas de $p(x) $ vêm em pares conjugados. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Prova num tweet:&lt;/b&gt; basta provar que $p(z) = 0 \implies p(\bar{z}) = 0$. Assumamos que $p(z) = 0$ (e lembremo-nos que $a_i = \bar{a_i} $):
$$\begin{align}
p(\bar{z}) &amp;= \sum_{i=0}^n a_i\bar{z}^i \\
&amp;= \sum_{i=0}^n \overline{a_iz^i} \\
&amp;= \overline{\sum_{i=0}^n a_iz^i} = \overline{p(z)} = 0
\end {align} $$
provando assim o pretendido.

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/2770506806485944003'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/2770506806485944003'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/11/twitter-proof-roots-go-hand-in-hand.html' title='Twitter proof: the roots go hand in hand'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-6077494901635324485</id><published>2018-11-19T10:42:00.000+00:00</published><updated>2018-11-19T10:42:03.872+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="approximations"/><category scheme="http://www.blogger.com/atom/ns#" term="construction"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="interpolation"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="polynomials"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="twitter proof"/><title type='text'>Twitter proof: interpolating polynomials</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this post I will show the existence of a family of polynomials that are very useful for interpolation. For that I will use what are known as Lagrange polynomials.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Claim:&lt;/b&gt; given $n+1$ pairs $(x_i, y_i) $ with $0\leq i \leq n $ and with $x_i \neq x_j $ whenever $i\neq j $, there exists a polynomial $p(x) $ of degree at most $n $ such that
$$p(x_i) = y_i,\ i = 0, \cdots, n $$
&lt;br /&gt;
&lt;b&gt;Twitter proof:&lt;/b&gt; consider the polynomial
$$l_i(x) = \prod_{j\neq i} \frac{x - x_j}{x_i - x_j} $$
with $l_i(x_i) = 1$ and $l_i(x_j) = 0$ whenever $j \neq i$. Define $p(x) $ to be
$$p(x) = \sum_{i=0}^{n} y_i l_i(x) $$
$p(x) $ has degree at most $n $ because so do the $l_i(x) $ and $p(x_k) = \sum_i y_i l_i(x_k) = y_k $.&lt;br /&gt;
&lt;br /&gt;
In a future post I will show the uniqueness of the polynomial satisfying the constraints in the claim.

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post vou mostrar a existência de uma família interessante de polinómios, muito útil em interpolação. Para isso vou usar uns polinómios chamados polinómios de Lagrange. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Proposição:&lt;/b&gt; dados $n+1$ pares $(x_i, y_i) $ onde $0\leq i \leq n $ e tais que $x_i \neq x_j $ sempre que $i\neq j $, existe um polinómio $p(x) $ de grau menor ou igual a $n $ satisfazendo as igualdades
$$p(x_i) = y_i,\ i = 0, \cdots, n $$
&lt;br /&gt;
&lt;b&gt;Prova num tweet:&lt;/b&gt; considere-se o polinómio
$$l_i(x) = \prod_{j\neq i} \frac{x - x_j}{x_i - x_j} $$
que satisfaz $l_i(x_i) = 1$ e $l_i(x_j) = 0$ sempre que $j \neq i$. Definimos $p(x) $ como
$$p(x) = \sum_{i=0}^{n} y_i l_i(x) $$
$p(x) $ tem grau menor ou igual a $n $ porque os $l_i(x) $ o têm e $p(x_k) = \sum_i y_i l_i(x_k) = y_k $.&lt;br /&gt;
&lt;br /&gt;
Num post futuro mostrarei a unicidade do polinómio que satisfaz as restrições da proposição.

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6077494901635324485'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6077494901635324485'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/11/twitter-proof-interpolating-polynomials.html' title='Twitter proof: interpolating polynomials'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-871482181622322609</id><published>2018-11-12T10:15:00.000+00:00</published><updated>2018-11-12T10:15:09.211+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="asymptotics"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="exponential"/><category scheme="http://www.blogger.com/atom/ns#" term="limits"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="polynomials"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><title type='text'>Twitter proof: can&#39;t touch this (exponential)</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this twitter proof we will see that no polynomial grows faster than the exponential function. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Claim:&lt;/b&gt; the ratio $\frac{x^p}{e^x}$ tends to $0$ as $x $ tends to infinity. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Twitter proof:&lt;/b&gt; recall that by the &lt;a target=&quot;_blank&quot; href=&quot;https://en.m.wikipedia.org/wiki/Taylor_series#Examples&quot;&gt;Taylor expansion &lt;/a&gt; of $e^x $ we have
$$e^x = \sum_{i=0}^\infty \frac{x^i}{i!}$$
and for $x &gt; 0$ we have
$$\frac{x^p}{e^x} \leq \frac{x^p}{\sum_{i=0}^{p+1} a_ix^i} \to 0 $$
where $a_{p+1} \neq 0$ thus proving our claim. &lt;br /&gt;
&lt;br /&gt;
The way I like to look at this is &quot;if the exponential has a bit of every polynomial inside, then it will grow faster than any fixed polynomial $p(x)$&quot; (because, in particular, the exponential &quot;has a bit&quot; of all other polynomials that have degree higher than that of $p(x) $.


&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post vamos ver que a função exponencial cresce mais depressa que qualquer função polinomial. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Proposição:&lt;/b&gt; o rácio $\frac{x^p}{e^x}$ tende para $0$ quando $x $ tende para infinito. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Prova num tweet:&lt;/b&gt; sabemos pela &lt;a target=&quot;_blank&quot; href=&quot;https://en.m.wikipedia.org/wiki/Taylor_series#Examples&quot;&gt;expansão de Taylor&lt;/a&gt; de $e^x $ que
$$e^x = \sum_{i=0}^\infty \frac{x^i}{i!}$$
e portanto, para $x &gt; 0$ temos
$$\frac{x^p}{e^x} \leq \frac{x^p}{\sum_{i=0}^{p+1} a_ix^i} \to 0 $$
onde $a_{p+1} \neq 0$ provando assim a proposição.&lt;br /&gt;
&lt;br /&gt;
O modo como eu gosto de interpretar isto é &quot;se a exponencial tem um bocado de todos os polinómios, obviamente vai crescer mais depressa que qualquer polinómio $p(x) $ fixo&quot;, porque em particular a exponencial &quot;tem bocados&quot; de todos os polinómios com um grau superior ao de $p(x) $.

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/871482181622322609'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/871482181622322609'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/11/twitter-proof-cant-touch-this.html' title='Twitter proof: can&#39;t touch this (exponential)'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-6016224483766194338</id><published>2018-11-05T09:50:00.000+00:00</published><updated>2018-11-05T09:50:08.158+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="diophantine equations"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="fermat"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="roots"/><category scheme="http://www.blogger.com/atom/ns#" term="twitter proof"/><title type='text'>Twitter proof: irrational high-order roots of 2</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

For this twitter proof we will be using a piece of mathematics straight from the 17th century. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Claim:&lt;/b&gt; the number $\sqrt[n]{2} $ is irrational for $n \geq 3$. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Twitter proof:&lt;/b&gt; suppose that $n \geq 3$ and $\sqrt[n]{2}$ is rational, i.e. $\sqrt[n]{2} = \frac{a}{b}$ for some integers $a, b $. Then taking the $n $-th power of both sides we get $2 = \frac{a^n}{b^n} \iff b^n + b^n = a^n $, contradicting the well-known &lt;a target=&quot;_blank&quot; href=&quot;https://en.m.wikipedia.org/wiki/Fermat%27s_Last_Theorem&quot;&gt;Fermat&#39;s Last Theorem&lt;/a&gt;.

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Para esta prova num tweet vamos usar um pedaço de matemática do século 17. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Proposição:&lt;/b&gt; o número  $\sqrt[n]{2} $ é irracional para $n \geq 3$. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Prova num tweet:&lt;/b&gt; suponhamos que $n\geq 3$ e que $\sqrt[n]{2} $ é racional, i.e. $\sqrt[n]{2} = \frac{a}{b} $ para alguns inteiros $a, b $. Se for esse o caso, elevando os dois lados da igualdade a $n $, obtemos $2 = \frac{a^n}{b^n} \iff b^n + b^n = a^n $, contrariando o famoso &lt;a target=&quot;_blank&quot; href=&quot;https://en.m.wikipedia.org/wiki/Fermat%27s_Last_Theorem&quot;&gt;Último Teorema de Fermat&lt;/a&gt;.

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6016224483766194338'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6016224483766194338'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/11/twitter-proof-irrational-high-order.html' title='Twitter proof: irrational high-order roots of 2'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-7931944142937322737</id><published>2018-10-29T08:30:00.000+00:00</published><updated>2018-10-29T13:41:09.327+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="construction"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="series"/><category scheme="http://www.blogger.com/atom/ns#" term="twitter proof"/><title type='text'>Twitter proof: the sum of inverses diverges</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this post I will share with you my favourite proof that the series of the inverses diverges: $\sum_{i=1}^\infty \frac1i = \infty $.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Claim &lt;/b&gt;: the series $\sum_i \frac1i$ diverges.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Twitter proof&lt;/b&gt;: consider the series $$
\begin{align}
&amp;\frac12 + \frac12 + \frac12 + \cdots = \\
&amp;\frac12 + 2 \times\frac14 + 4\times \frac18 + \cdots = \\
&amp;\frac12 + \frac14 + \frac14 + \frac18 + \cdots \leq \\
&amp;\frac12 + \frac13 + \frac14 + \frac15 + \cdots
\end{align}$$

that clearly diverges because it is a series of a constant nonzero term. By the comparison test, the series of the inverses also diverges.&lt;br /&gt;
&lt;br /&gt;
Comment with your favourite way to prove this fact!!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post quero partilhar com todos a minha prova preferida de que a série dos inversos dos naturais diverge: $\sum_{i=1}^\infty \frac1i = \infty $.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Proposição&lt;/b&gt;: a série $\sum_i \frac1i$ diverge.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Prova num tweet&lt;/b&gt;: considere-se a série$$
\begin{align}
&amp;\frac12 + \frac12 + \frac12 + \cdots = \\
&amp;\frac12 + 2 \times\frac14 + 4\times \frac18 + \cdots = \\
&amp;\frac12 + \frac14 + \frac14 + \frac18 + \cdots \leq \\
&amp;\frac12 + \frac13 + \frac14 + \frac15 + \cdots
\end{align}$$

que diverge claramente porque é a série em que se soma um termo constante diferente de zero. Pelo teste da comparação, a série dos inversos também diverge.&lt;br /&gt;
&lt;br /&gt;
Comentem qual a vossa forma preferida de provar este facto!!

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/7931944142937322737'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/7931944142937322737'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/10/twitter-proof-sum-of-inverses-diverges.html' title='Twitter proof: the sum of inverses diverges'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-8171248603073399042</id><published>2018-10-02T18:29:00.000+01:00</published><updated>2018-10-08T17:36:16.947+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="hanoi"/><category scheme="http://www.blogger.com/atom/ns#" term="induction"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="recursion"/><category scheme="http://www.blogger.com/atom/ns#" term="twitter proof"/><title type='text'>Twitter proof: the Tower of Hanoi</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6WiIAX2aH9XgJ_74W_FAK6EK_LYw92nhoC4ZdVWXLrZmzjIdRqBGH-4MiOAZwjt9OjcpcM2WwsHjXfLB8DMXF-r6r5ilq2_W5jZJpnzfgnDwTg9tzCMF9StKquo1qc2X7Oq-OJCX0ICU/s1600/hanoi_n4.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6WiIAX2aH9XgJ_74W_FAK6EK_LYw92nhoC4ZdVWXLrZmzjIdRqBGH-4MiOAZwjt9OjcpcM2WwsHjXfLB8DMXF-r6r5ilq2_W5jZJpnzfgnDwTg9tzCMF9StKquo1qc2X7Oq-OJCX0ICU/s1600/hanoi_n4.gif&quot; data-original-width=&quot;874&quot; data-original-height=&quot;333&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this post we prove what the minimum number of moves to solve the problem of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Tower_of_Hanoi&quot; target=&quot;_blank&quot;&gt;Tower of Hanoi&lt;/a&gt; is!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Claim:&lt;/b&gt; let $T(n)$ denote the number of moves it takes to solve the Tower of Hanoi with $n$ disks; then $T(n) = 2^{n}-1$.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Twitter proof:&lt;/b&gt; note that to solve the problem with $n$ disks, we first have to move the top $n-1$ disks to one of the two poles, move the bottom disk (the bigger one) to the remaining pole, and then move the top $n-1$ disks to the top of the bigger disk. Each time we move the top $n-1$ disks to another pole we must take, at least, $T(n-1)$ moves (by definition of $T$) hence we clearly have $T(n) = 2T(n-1) + 1$. Just notice that $B(n) = 2^n - 1$ satisfies the recurrence relation and that $T(0) = B(0) = 0$.&lt;br /&gt;
&lt;br /&gt;
If you are having trouble understanding what I mean by &lt;i&gt;to solve the problem with $n$ disks, we first have to move the top $n-1$ disks to one of the two poles, move the bottom disk (the bigger one) to the remaining pole, and then move the top $n-1$ disks to the top of the bigger disk&lt;/i&gt;, check the following sequence of images that contains some of the intermediate steps to solve the Tower of Hanoi with $4$ disks:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgShhm8c0NnWcT29i0Pnsb0FP7OOBZvFxwdqOtijjdgAX-GzgscQDv64-Xxo1aawu1_D9qISahnjdP8te1vBpeT2_WBqtjmUH1E12rf_DKFrE5DD6SDcSDMZl7RLx9wh7s_aFD1sTVqoP4/s1600/frame07.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgShhm8c0NnWcT29i0Pnsb0FP7OOBZvFxwdqOtijjdgAX-GzgscQDv64-Xxo1aawu1_D9qISahnjdP8te1vBpeT2_WBqtjmUH1E12rf_DKFrE5DD6SDcSDMZl7RLx9wh7s_aFD1sTVqoP4/s1600/frame07.png&quot; data-original-width=&quot;874&quot; data-original-height=&quot;333&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
First we move the top $3$ disks to the centre pole in $T(3)$ moves...&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTePm4t8OOVNIYUHB98369e1ou964SUIunPEakgzB6qZ6KvtdOvmT9pBddQFbgwCDlZhBoM8I4kwFFEBhDcvZCd1jOh_oRm3KeCR8oo81fFZH2fXFWb7RbxNluK3TaBOkYRXQQA19YMLg/s1600/frame08.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTePm4t8OOVNIYUHB98369e1ou964SUIunPEakgzB6qZ6KvtdOvmT9pBddQFbgwCDlZhBoM8I4kwFFEBhDcvZCd1jOh_oRm3KeCR8oo81fFZH2fXFWb7RbxNluK3TaBOkYRXQQA19YMLg/s1600/frame08.png&quot; data-original-width=&quot;874&quot; data-original-height=&quot;333&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Then we change the bottom disk to the available pole in $1$ move...&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzoy3sPh_E2oMgyU6kYrWnni2PAjtZJZKMWXS5XhURT_I45oHcLJH7QlI4luxl5tJQ5il_MlpOsTmEhycnFUlhxD6ARsuKNrzbKNzngJYtyzg0pWaWp79OzctHtuHSFe-sx3XGXqFJ9OQ/s1600/frame15.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzoy3sPh_E2oMgyU6kYrWnni2PAjtZJZKMWXS5XhURT_I45oHcLJH7QlI4luxl5tJQ5il_MlpOsTmEhycnFUlhxD6ARsuKNrzbKNzngJYtyzg0pWaWp79OzctHtuHSFe-sx3XGXqFJ9OQ/s1600/frame15.png&quot; data-original-width=&quot;874&quot; data-original-height=&quot;333&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Then we move the top $3$ disks again in $T(3)$ moves!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post vou provar qual é o número mínimo de movimentos necessário para resolver o problema da &lt;a href=&quot;https://en.wikipedia.org/wiki/Tower_of_Hanoi&quot; target=&quot;_blank&quot;&gt;Torre de Hanoi&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Proposição:&lt;/b&gt; se $T(n)$ é o número mínimo de movimentos necessários para resolver o problema da Torre de Hanoi com $n$ discos, então $T(n) = 2^{n}-1$.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Prova num tweet:&lt;/b&gt; repare-se que para resolver o problema com $n$ discos, primeiro temos de mexer os $n-1$ discos mais pequenos para uma das duas varas livres, depois mexemos o maior disco para a outra vara vazia, depois voltamos a mexer os $n-1$ discos mais pequenos para cima do disco maior. De cada vez que mudamos os $n-1$ discos mais pequenos de vara, temos de fazer &lt;i&gt;pelo menos&lt;/i&gt; $T(n-1)$ movimentos (pela definição de $T$) portanto temos claramente $T(n) = 2T(n-1) + 1$. Agora basta reparar que $B(n) = 2^n - 1$ satisfaz a relação de recurrência e que $T(0) = B(0) = 0$.&lt;br /&gt;
&lt;br /&gt;
Se está a custar a entender o que quero dizer com &lt;i&gt;para resolver o problema com $n$ discos, primeiro temos de mexer os $n-1$ discos mais pequenos para uma das duas varas livres, depois mexemos o maior disco para a outra vara vazia, depois voltamos a mexer os $n-1$ discos mais pequenos para cima do disco maior&lt;/i&gt;, vejam a sequência de imagens seguinte, que contém alguns passos intermédios para resolver a Torre de Hanoi com $4$ discos:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgShhm8c0NnWcT29i0Pnsb0FP7OOBZvFxwdqOtijjdgAX-GzgscQDv64-Xxo1aawu1_D9qISahnjdP8te1vBpeT2_WBqtjmUH1E12rf_DKFrE5DD6SDcSDMZl7RLx9wh7s_aFD1sTVqoP4/s1600/frame07.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgShhm8c0NnWcT29i0Pnsb0FP7OOBZvFxwdqOtijjdgAX-GzgscQDv64-Xxo1aawu1_D9qISahnjdP8te1vBpeT2_WBqtjmUH1E12rf_DKFrE5DD6SDcSDMZl7RLx9wh7s_aFD1sTVqoP4/s1600/frame07.png&quot; data-original-width=&quot;874&quot; data-original-height=&quot;333&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Primeiro mudamos os $3$ discos mais pequenos para a vara do meio em $T(3)$ movimentos...&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTePm4t8OOVNIYUHB98369e1ou964SUIunPEakgzB6qZ6KvtdOvmT9pBddQFbgwCDlZhBoM8I4kwFFEBhDcvZCd1jOh_oRm3KeCR8oo81fFZH2fXFWb7RbxNluK3TaBOkYRXQQA19YMLg/s1600/frame08.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTePm4t8OOVNIYUHB98369e1ou964SUIunPEakgzB6qZ6KvtdOvmT9pBddQFbgwCDlZhBoM8I4kwFFEBhDcvZCd1jOh_oRm3KeCR8oo81fFZH2fXFWb7RbxNluK3TaBOkYRXQQA19YMLg/s1600/frame08.png&quot; data-original-width=&quot;874&quot; data-original-height=&quot;333&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Depois mudamos o disco maior para a vara livre em $1$ movimento...&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzoy3sPh_E2oMgyU6kYrWnni2PAjtZJZKMWXS5XhURT_I45oHcLJH7QlI4luxl5tJQ5il_MlpOsTmEhycnFUlhxD6ARsuKNrzbKNzngJYtyzg0pWaWp79OzctHtuHSFe-sx3XGXqFJ9OQ/s1600/frame15.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzoy3sPh_E2oMgyU6kYrWnni2PAjtZJZKMWXS5XhURT_I45oHcLJH7QlI4luxl5tJQ5il_MlpOsTmEhycnFUlhxD6ARsuKNrzbKNzngJYtyzg0pWaWp79OzctHtuHSFe-sx3XGXqFJ9OQ/s1600/frame15.png&quot; data-original-width=&quot;874&quot; data-original-height=&quot;333&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Depois mudamos os $3$ discos mais pequenos da vara central para a vara mais à direita, em apenas $T(3)$ movimentos!

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/8171248603073399042'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/8171248603073399042'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/10/twitter-proof-tower-of-hanoi.html' title='Twitter proof: the Tower of Hanoi'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6WiIAX2aH9XgJ_74W_FAK6EK_LYw92nhoC4ZdVWXLrZmzjIdRqBGH-4MiOAZwjt9OjcpcM2WwsHjXfLB8DMXF-r6r5ilq2_W5jZJpnzfgnDwTg9tzCMF9StKquo1qc2X7Oq-OJCX0ICU/s72-c/hanoi_n4.gif" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-4272167676179621526</id><published>2018-10-01T00:35:00.001+01:00</published><updated>2018-10-08T17:33:53.250+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="100daysofmlcode"/><category scheme="http://www.blogger.com/atom/ns#" term="artificial intelligence"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="machine learning"/><category scheme="http://www.blogger.com/atom/ns#" term="markov"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="reinforcement learning"/><category scheme="http://www.blogger.com/atom/ns#" term="stochastic"/><title type='text'>Markov Decision Processes 03: optimal policy variation</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi__5G2_fBe2V-x69SmVr4uPqEyAZrzKfmyz9JqmR7MhbxlKgRN2C1GVsI_DNzREwl1EdeZUuUFWSGfIkQhLZhMEIHunzM45EFN0JZ3Q64__me_s3YQckA1vpMMefOfcWgLkYbRUytsJ4/s1600/mdp3_alternative_policy.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi__5G2_fBe2V-x69SmVr4uPqEyAZrzKfmyz9JqmR7MhbxlKgRN2C1GVsI_DNzREwl1EdeZUuUFWSGfIkQhLZhMEIHunzM45EFN0JZ3Q64__me_s3YQckA1vpMMefOfcWgLkYbRUytsJ4/s1600/mdp3_alternative_policy.png&quot; data-original-width=&quot;500&quot; data-original-height=&quot;394&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

This post is going to follow up what was discussed &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-02-how.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;, and I will show you how changing the value of the discount factor may affect what the optimal policy is.&lt;br /&gt;
&lt;br /&gt;
For that, consider the MDP defined below:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi__5G2_fBe2V-x69SmVr4uPqEyAZrzKfmyz9JqmR7MhbxlKgRN2C1GVsI_DNzREwl1EdeZUuUFWSGfIkQhLZhMEIHunzM45EFN0JZ3Q64__me_s3YQckA1vpMMefOfcWgLkYbRUytsJ4/s1600/mdp3_alternative_policy.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi__5G2_fBe2V-x69SmVr4uPqEyAZrzKfmyz9JqmR7MhbxlKgRN2C1GVsI_DNzREwl1EdeZUuUFWSGfIkQhLZhMEIHunzM45EFN0JZ3Q64__me_s3YQckA1vpMMefOfcWgLkYbRUytsJ4/s1600/mdp3_alternative_policy.png&quot; data-original-width=&quot;500&quot; data-original-height=&quot;394&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
This MDP is inspired in the example I have been using; I added an extra state and stripped the MDP of the majority of the transitions so we can focus on what is essential here. From the MDP above there is a clear contender for the title of optimal policy:
$$\begin{align}
&amp;\pi(H) = E\\
&amp;\pi(T) = D\\
&amp;\pi(TU) = D\end{align}$$
Assume that when we enter the MDP there is a $50\%$ chance we start Hungry and a $50\%$ chance we start Thirsty. If we use the policy $\pi$ then the expected reward is
$$E[R | \pi] = 0.5E[R_T | \pi] + 0.5E[R_H | \pi]$$
where $E[R_s | \pi]$ is the expected reward we get by following policy $\pi$ starting from state $s$. From &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-02-how.html&quot; target=&quot;_blank&quot;&gt;my previous post&lt;/a&gt; we know that $E[R_T | \pi] = E[R_H | \pi] = \frac{1}{1-\gamma}$ and hence
$$E[R | \pi] = \frac{1}{1-\gamma}$$

But what if we followed the seemingly masochist policy $\pi&#39;$ where we eat compulsively, getting a negative reward, just to be able to get a bigger reward when we drink and recover? Define $\pi&#39;$ as
$$\begin{align}
&amp;\pi&#39;(H) = CE\\
&amp;\pi&#39;(TU) = D\\
&amp;\pi&#39;(T) = D\end{align}$$

Can we compute the expected reward for this policy, assuming the same $50/50$ probabilities for the initial state? Of course we can, just notice that
$$\begin{cases}
\begin{align}
&amp;E[R_H | \pi&#39;] = -2 + \gamma E[R_{TU} | \pi&#39;] \\
&amp;E[R_{TU} | \pi&#39;] = 5 + \gamma E[R_T | \pi&#39;] \\
&amp;E[R_T | \pi&#39;] = 1 + \gamma E[R_H | \pi&#39;]
\end{align}
\end{cases}$$
and we can compute those by solving the system it encodes,
$$\begin{cases}
\begin{align}
&amp;x = -2 + \gamma y \\
&amp;y = 5 + \gamma z \\
&amp;z = 1 + \gamma x
\end{align}
\end{cases}$$
giving
$$\begin{cases}
\begin{align}
&amp;x = -\frac{\gamma ^2+5 \gamma -2}{\gamma ^3-1}\\
&amp;y = -\frac{-2 \gamma ^2+\gamma +5}{\gamma ^3-1}\\
&amp;z = -\frac{5 \gamma ^2-2 \gamma +1}{\gamma ^3-1}
\end{align}
\end{cases}$$
for a final expected reward of
$$E[R | \pi&#39;] = \frac{6 \gamma ^2 + 3 \gamma - 1}{2 \left(1 - \gamma^3\right)}$$

Is this value greater than $E[R | \pi]$? With a bit more maths, one can find that for the legal values of $\gamma$,

$$E[R | \pi&#39;] \geq E[R | \pi] \iff \gamma \geq \frac34$$

For example, if $\gamma = 0.9$, then the regular policy $\pi$ has an expected reward of $10$ but the masochist policy $\pi&#39;$ is worth $\approx 12.1$; at $\gamma = 0.75$ they are both worth $4$ and for $\gamma = 0.5$, $\pi$ has expected reward $2$ while $\pi&#39;$ only has $\approx 1.14$.&lt;br /&gt;
&lt;br /&gt;
This actually makes some sense: we would only consider the policy $\pi&#39;$ if the $+5$ we can get, even though it comes amortized, is better than losing $-2$ right now; i.e. if we see the $+5$ as a &lt;i&gt;long-term&lt;/i&gt; investment that will compensate our loss of $-2$. In particular, losing $2$ now and gaining an amortized $\gamma 5$ must be better than the safer option which is to go back and forth between being Hungry and Thirsty: if we are starting in the Hungry position, we either do
$$EC \to D \to E,\ \text{following } \pi&#39;$$
or we do
$$E \to D \to E,\ \text{following } \pi$$
The first sequence is worth $-2 + 5\gamma  + \gamma^2$ while the second sequence of actions is worth $1 + \gamma + \gamma^2$; therefore we would prefer $\pi&#39;$ over $\pi$ whenever
$$\begin{align}
-2 + 5\gamma + \gamma^2 &gt; 1 + \gamma + \gamma^2 &amp;\iff -2 + 5\gamma &gt; 1 + \gamma \\
&amp;\iff -2 + 4\gamma &gt; 1 \\
&amp;\iff \gamma &gt; \frac34
\end{align}
$$
If we start in the Thirsty position, we either do
$$D \to EC \to D,\ \text{following } \pi&#39;$$
or we do
$$D \to E \to D,\ \text{following } \pi$$
The first sequence is worth $1 - 2\gamma + 5\gamma^2$ while the second sequence of actions is worth $1 + \gamma + \gamma^2$;
this means that, when we start Thirsty, we would prefer $\pi&#39;$ over $\pi$ whenever (remember that $\gamma \geq 0$)
$$\begin{align}
1 - 2\gamma + 5\gamma^2 &gt; 1 + \gamma + \gamma^2 &amp;\iff - 3\gamma + 4\gamma^2 &gt; 0 \\
&amp;\iff \gamma &gt; \frac34
\end{align}$$

So we can see that everything adds up nicely; regardless of our starting position, we would prefer $\pi&#39;$ over $\pi$ whenever $\gamma &gt; 0.75$ so that is exactly the final result we got.&lt;br /&gt;
&lt;br /&gt;
This concludes this post. We have seen how the value of $\gamma$ might affect what the optimal policy is! This example might seem fabricated, but that is because I wanted to show these changes in optimal policies with the simplest example possible. In real life the MDPs are way bigger and much more complex, so it shouldn&#39;t be difficult to believe the value of $\gamma$ might end up being decisive.&lt;br /&gt;
&lt;br /&gt;
In a future post, we will be tackling algorithms to find the optimal policy in a general MDP and hopefully I will find a good example of application to show how they work!&lt;br /&gt;
&lt;br /&gt;
This post was brought to you by the &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/pledging-to-do-100-days-of-machine.html&quot; target=&quot;_blank&quot;&gt;#100DaysOfMLCode&lt;/a&gt; initiative.&lt;br /&gt;
&lt;br /&gt;
All posts on the MDP series:&lt;br /&gt;
&lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-basics.html&quot; target=&quot;_blank&quot;&gt;MDP#01 Basics&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-02-how.html&quot; target=&quot;_blank&quot;&gt;MDP#02 Discount Factor&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://mathspp.blogspot.com/2018/10/markov-decision-processes-03-optimal.html&quot; target=&quot;_blank&quot;&gt;MDP#03 Optimal Policy Variation&lt;/a&gt;&lt;br /&gt;

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;
(tradução indisponível de momento)&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/4272167676179621526'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/4272167676179621526'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/10/markov-decision-processes-03-optimal.html' title='Markov Decision Processes 03: optimal policy variation'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi__5G2_fBe2V-x69SmVr4uPqEyAZrzKfmyz9JqmR7MhbxlKgRN2C1GVsI_DNzREwl1EdeZUuUFWSGfIkQhLZhMEIHunzM45EFN0JZ3Q64__me_s3YQckA1vpMMefOfcWgLkYbRUytsJ4/s72-c/mdp3_alternative_policy.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-468715912657683085</id><published>2018-09-29T00:51:00.001+01:00</published><updated>2018-10-08T17:34:14.747+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="100daysofmlcode"/><category scheme="http://www.blogger.com/atom/ns#" term="artificial intelligence"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="machine learning"/><category scheme="http://www.blogger.com/atom/ns#" term="markov"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="mdp"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="reinforcement learning"/><category scheme="http://www.blogger.com/atom/ns#" term="stochastic"/><title type='text'>Markov Decision Processes 02: how the discount factor works</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeYmgQPmfIt2KuzWG2ggmW5Gx2PaIPo21ch_biLJzIBiv7vCHAv9lEYmGeu30SCJUb4qP-P2Lg9wxyzeS_4VvFb11RydQMiykwZNqYjVLrYp7hPjZ7ANRqOyTWW_0drD3yb50BryVHZNM/s1600/mdp_discounted_time_sequence.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeYmgQPmfIt2KuzWG2ggmW5Gx2PaIPo21ch_biLJzIBiv7vCHAv9lEYmGeu30SCJUb4qP-P2Lg9wxyzeS_4VvFb11RydQMiykwZNqYjVLrYp7hPjZ7ANRqOyTWW_0drD3yb50BryVHZNM/s1600/mdp_discounted_time_sequence.png&quot; data-original-width=&quot;551&quot; data-original-height=&quot;141&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-basics.html&quot; target=&quot;_blank&quot;&gt;this previous&lt;/a&gt; post I defined a Markov Decision Process and explained all of its components; now, we will be exploring what the discount factor $\gamma$ really is and how it influences the MDP.&lt;br /&gt;
&lt;br /&gt;
Let us start with the complete example of last post:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihXwL6UHQmdYFBcmcWwH3JUAABsFDtEr7lOYm8pTVQ7g45iYljRrCUl1c-NKH55pue01WpDKhtQE4e133CLwUAiPOPlycJLYNRSgE1QFMftSkEDHCEID6pXOExdBHN6j6R9UkBklV82tg/s1600/mdp_full.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihXwL6UHQmdYFBcmcWwH3JUAABsFDtEr7lOYm8pTVQ7g45iYljRrCUl1c-NKH55pue01WpDKhtQE4e133CLwUAiPOPlycJLYNRSgE1QFMftSkEDHCEID6pXOExdBHN6j6R9UkBklV82tg/s1600/mdp_full.png&quot; data-original-width=&quot;549&quot; data-original-height=&quot;398&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
In this MDP the states are Hungry and Thirsty (which we will represent with $H$ and $T$) and the actions are Eat and Drink (which we will represent with $E$ and $D$). The transition probabilities are specified by the numbers on top of the arrows. In the previous post we put forward that the best policy for this MDP was defined as
$$\begin{cases}
\pi(H) = E\\
\pi(T) = D\end{cases}$$
but I didn&#39;t really prove that. I will do that in a second, but first what are all the other possible policies? Well, recall that the policy $\pi$ is the &lt;i&gt;&quot;best strategy&quot;&lt;/i&gt; to be followed, and $\pi$ is formally seen as a function from the states to the actions, i.e. $\pi: S \to A$. Because of that, we must know what $\pi(H)$ and $\pi(T)$ are:
$$\begin{cases}
\pi(T) = \text{action to be taken when Thirsty}\\
\pi(H) = \text{action to be taken when Hungry}\end{cases}$$
We know that both $\pi(H)$ and $\pi(T)$ can be either $D$ or $E$ so we really have $4$ possible policies:
$$\begin{align}
\pi_1(H) = E&amp;,\ \pi_1(T) = E\\
\pi_2(H) = E&amp;,\ \pi_2(T) = D\\
\pi_3(H) = D&amp;,\ \pi_3(T) = E\\
\pi_4(H) = D&amp;,\ \pi_4(T) = D\end{align}$$
All we have to do now is to measure how &lt;i&gt;good&lt;/i&gt; each policy is, and to do that, we will use the rewards! Intuitively, what would be the best policy? The best policy is the one that allows us to collect more rewards.&lt;br /&gt;
&lt;br /&gt;
How do we measure the rewards we can collect, then? We use the mathematical notion of &lt;i&gt;expected value&lt;/i&gt;. For each policy, we should compute the &lt;i&gt;expected reward&lt;/i&gt; we would get by following it, and then stick with the policy that has a bigger expected reward. We will compute the expected reward of $\pi_2$, the policy I claimed to be the best one, but first we will start with this simpler MDP:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO0b1ji-IgenLQx2rkS0aDknmOAM_xoPczm2_eiIo-zVTKpU_balXLXdNrjiqtMAVw-AJBisCaQ0pivZ84tPScMaYwrWAhx7uJ3IcDLzB68KGAV9yjbD_qqhNCFePOyWoLzJdeY5BB1sA/s1600/mdp_simple.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO0b1ji-IgenLQx2rkS0aDknmOAM_xoPczm2_eiIo-zVTKpU_balXLXdNrjiqtMAVw-AJBisCaQ0pivZ84tPScMaYwrWAhx7uJ3IcDLzB68KGAV9yjbD_qqhNCFePOyWoLzJdeY5BB1sA/s1600/mdp_simple.png&quot; data-original-width=&quot;247&quot; data-original-height=&quot;201&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
In this MDP we only have one state and one action, which gives a reward of $+1$ whenever we choose it. The obvious policy here is to take the only action available. Suppose we are at a given time step $t$. To compute how good our position in the MDP is, we have to consider the reward we will get when we perform the next action (which will give us $+1$) but we must also consider the rewards we will get in the future:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDjVTNWwM-8dk0P4jiNLgd6nfvrN-lKhcl3uSxGTo2nZKdS4YzxAP_LFXYEayKzw6lIJHd4WtermnaGTjUP6A4wX-BnMBh0q8hrBgCgUwJ4TVZHCJtf4Ti0eb8zU4hJRoxlW_RRpNDmHg/s1600/mdp_time_sequence.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDjVTNWwM-8dk0P4jiNLgd6nfvrN-lKhcl3uSxGTo2nZKdS4YzxAP_LFXYEayKzw6lIJHd4WtermnaGTjUP6A4wX-BnMBh0q8hrBgCgUwJ4TVZHCJtf4Ti0eb8zU4hJRoxlW_RRpNDmHg/s1600/mdp_time_sequence.png&quot; data-original-width=&quot;537&quot; data-original-height=&quot;100&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
except that those rewards we will get in the future aren&#39;t as good as the $+1$ we are going to receive &lt;i&gt;right now&lt;/i&gt;! To compensate for that, we will make them less valuable by multiplying a number smaller than $1$ which we call a discount factor: our $\gamma$. When a reward $r$ is only one time step away, we multiply it by $\gamma$ yielding $\gamma r$; if a reward is three time steps away, we multiply it by $\gamma^3$ giving $\gamma^3 r$ and so on and so forth:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnb50rHdEOzpYGnWmp-jZ-DvWS1-Ri4wcIJT24bL6AKgh8yL2sXMLGTlsh-FMHA6GP6bMMH_BLvccVN0qrz_nUBXI7hXwqfNU9NsOxbIFoMHJoBIuWzZdyf8UxjLHeJIfiJA4gJR9SoeQ/s1600/mdp_discounted_time_sequence.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnb50rHdEOzpYGnWmp-jZ-DvWS1-Ri4wcIJT24bL6AKgh8yL2sXMLGTlsh-FMHA6GP6bMMH_BLvccVN0qrz_nUBXI7hXwqfNU9NsOxbIFoMHJoBIuWzZdyf8UxjLHeJIfiJA4gJR9SoeQ/s1600/mdp_discounted_time_sequence.png&quot; data-original-width=&quot;551&quot; data-original-height=&quot;141&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Therefore we get that the expected reward is
$$1 + \gamma + \gamma^2 + \gamma^3 +  \cdots$$
which can be simplified to $\frac{1}{1 - \gamma}$ when $0 \leq \gamma &lt; 1$.&lt;br /&gt;
&lt;br /&gt;
This computation was fairly easy because our actions never had bifurcations: even though we were looking into the future, we were always sure of where we would be... Now we will compute how good the policy $\pi_2$ is!&lt;br /&gt;
&lt;br /&gt;
Let us assume that when we enter the MDP, we have a $50\%$ probability of starting Hungry and a $50\%$ probability of starting Thirsty. This means that the expected &lt;i&gt;worth&lt;/i&gt; of the policy is
$$E[R | \pi_2] = 0.5E[R_H|\pi_2] + 0.5E[R_T|\pi_2]$$
where $E[R_H | \pi_2]$ is the expected worth of starting Hungry and $E[R_T | \pi_2]$ is the expected worth of starting Thirsty.&lt;br /&gt;
&lt;br /&gt;
How do we compute $E[R_H | \pi_2]$? Recall that this expected value can be interpreted as the total rewards we will get if we start Hungry and then follow the policy $\pi_2$. If we are Hungry and follow $\pi_2$, our action will be $\pi_2(H) = E$. If we Eat when we are Hungry, we get a reward $+1$ and then: there is a $10\%$ chance that we stay Hungry and there is a $90\%$ chance that we become Thirsty. This means that
$$E[R_H | \pi_2] = 1 + 0.1\gamma E[R_H | \pi_2] + 0.9\gamma E[R_T | \pi_2]$$
What does this expression mean? The term $+1$ is the immediate reward we get when we choose to Eat and the remainder $0.1\gamma E[R_H | \pi_2] + 0.9\gamma E[R_T | \pi_2]$ accounts for the future rewards we &lt;i&gt;hope&lt;/i&gt; to get (as in, expect to get).&lt;br /&gt;
Recall that when we are evaluating the worth of an action, we also have to think ahead (&lt;i&gt;into the future&lt;/i&gt;) and account for the rewards we might get if we go down that road, making them slightly less valuable by multiplying with $\gamma$. Therefore,
$$0.1\gamma E[R_H | \pi_2] + 0.9\gamma E[R_T | \pi_2]$$
breaks down into $0.1\gamma E[R_H | \pi_2]$ for what we might get if, after Eating, we stay Hungry ($E[R_H]$), and $0.9\gamma E[R_T | \pi_2]$ for what we might get if we become Thirsty ($E[R_T]$). Those expected values are multiplied by $\gamma$ because they are only future rewards and then the extra coefficient, either $0.1$ or $0.9$, accounts for the fact that we are not certain of where we will be.&lt;br /&gt;
&lt;br /&gt;
In a similar way we get that
$$E[R_T | \pi_2] = 1 + 0.1\gamma E[R_T | \pi_2] + 0.9\gamma E[R_H | \pi_2]$$
For the sake of brevity let me write $x = E[R_H | \pi_2]$ and $y = E[R_T | \pi_2]$. Rewriting the two equations from above we have
$$\begin{cases}
x = 1 + 0.1\gamma x + 0.9\gamma y \\
y = 1 + 0.1\gamma y + 0.9\gamma x
\end{cases}$$ 
which is a system of two equations with two unknowns! If we solve it we find
$$\begin{cases}
x = E[R_H | \pi_2] = \frac{1}{1 - \gamma} \\
y = E[R_T | \pi_2] = \frac{1}{1 - \gamma} \end{cases}$$
that we can plug in the first expression
$$E[R | \pi_2] = 0.5E[R_H|\pi_2] + 0.5E[R_T|\pi_2]$$
to get
$$E[R | \pi_2] = \frac{1}{1 - \gamma}$$
It is not surprising that this gave the exact same result as the simpler MDP above: even though we are not sure of where we will start and we won&#39;t be able to tell to where will be going, whenever we act we get a reward of $+1$; for example, this could happen:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ_7M7WLfn-T4xzqJet2Q0l8GGmi_LDOfPnHE2wSGzhOh6RPlfHBBlo7E-OWwRdUA2hY15HpMnvg6feLK-oflbuie4_pi0N1fs9wnAX4AJIBajdVGu_7c-sbi_Mejyy0QLRBqiTUYt7eg/s1600/mdp_example_time_sequence.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ_7M7WLfn-T4xzqJet2Q0l8GGmi_LDOfPnHE2wSGzhOh6RPlfHBBlo7E-OWwRdUA2hY15HpMnvg6feLK-oflbuie4_pi0N1fs9wnAX4AJIBajdVGu_7c-sbi_Mejyy0QLRBqiTUYt7eg/s1600/mdp_example_time_sequence.png&quot; data-original-width=&quot;587&quot; data-original-height=&quot;96&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
If $\pi_2$ is in fact the best policy, then this value $\frac{1}{1 - \gamma}$ will be greater than the worth of any of the three remaining policies. It is fairly simple to see that $E[R | \pi_3] = 0$. Computing $E[R | \pi_1]$ and $E[R | \pi_4]$ is similar, so we will do $\pi_1$ only:
$$\begin{cases}
E[R_H | \pi_1] = 1 + 0.1\gamma E[R_H | \pi_1] + 0.9\gamma E[R_T | \pi_1]\\
E[R_T | \pi_1] = 0 + \gamma E[R_T | \pi_1]
\end{cases}$$
which gives (if $\gamma &lt; 1$)
$$\begin{cases}
E[R_H | \pi_1] = \frac{1}{1 - 0.1\gamma}\\
E[R_T | \pi_1] = 0
\end{cases}$$
that adds up to
$$E[R | \pi_1] = 0.5\frac{1}{1 - 0.1\gamma} &lt; \frac{1}{1 - \gamma} = E[R | \pi_2]$$
showing that the policy $\pi_2$ is the best one!&lt;br /&gt;
&lt;br /&gt;
After all these calculations, you could try to convince yourself that the general expressions for $E[R | \pi]$ and $E[R_s | \pi]$ are
$$E[R | \pi] = \sum_{s \in S} P(s_0 = s)E[R_s | \pi]$$
where $P(s_0 = s)$ is the probability that we start at state $s$, and writing $a = \pi(s)$
$$E[R_s | \pi] = \sum_{s&#39; \in S} P_{a}(s, s&#39;)\left( R_{a}(s, s&#39;) + \gamma E[R_{s&#39;} | \pi] \right)$$
&lt;br /&gt;
In this post we calculated some expected rewards with the discount factor. In the next post we will see an example of how changing the discount factor can change the best policy to follow!&lt;br /&gt;
&lt;br /&gt;
This post was brought to you by the &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/pledging-to-do-100-days-of-machine.html&quot; target=&quot;_blank&quot;&gt;#100DaysOfMLCode&lt;/a&gt; initiative.&lt;br /&gt;
&lt;br /&gt;
All posts on the MDP series:&lt;br /&gt;
&lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-basics.html&quot; target=&quot;_blank&quot;&gt;MDP#01 Basics&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-02-how.html&quot; target=&quot;_blank&quot;&gt;MDP#02 Discount Factor&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://mathspp.blogspot.com/2018/10/markov-decision-processes-03-optimal.html&quot; target=&quot;_blank&quot;&gt;MDP#03 Optimal Policy Variation&lt;/a&gt;&lt;br /&gt;

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;
(tradução ainda não está disponível)&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/468715912657683085'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/468715912657683085'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/09/markov-decision-processes-02-how.html' title='Markov Decision Processes 02: how the discount factor works'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeYmgQPmfIt2KuzWG2ggmW5Gx2PaIPo21ch_biLJzIBiv7vCHAv9lEYmGeu30SCJUb4qP-P2Lg9wxyzeS_4VvFb11RydQMiykwZNqYjVLrYp7hPjZ7ANRqOyTWW_0drD3yb50BryVHZNM/s72-c/mdp_discounted_time_sequence.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-3399821072862209913</id><published>2018-09-27T17:39:00.000+01:00</published><updated>2018-10-08T17:34:23.481+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="100daysofmlcode"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="machine learning"/><category scheme="http://www.blogger.com/atom/ns#" term="markov"/><category scheme="http://www.blogger.com/atom/ns#" term="mdp"/><category scheme="http://www.blogger.com/atom/ns#" term="probability"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="reinforcement learning"/><category scheme="http://www.blogger.com/atom/ns#" term="tutorial"/><title type='text'>Markov Decision Processes 01: the basics</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAG_2IOPsbeJDZ_IJT0OlfTB6ZXDUXC2j90ci7kN-QUs9sZg1sweoZ71yH9rdCPKTX4A84BRPW2sy4NgX-dOh6MZ9jPnZu0tIgFjAh0rSMvcV35yeydcT1EvaBy-EiJ1Hj-kiq5XfwIuA/s1600/mdp_discount.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAG_2IOPsbeJDZ_IJT0OlfTB6ZXDUXC2j90ci7kN-QUs9sZg1sweoZ71yH9rdCPKTX4A84BRPW2sy4NgX-dOh6MZ9jPnZu0tIgFjAh0rSMvcV35yeydcT1EvaBy-EiJ1Hj-kiq5XfwIuA/s1600/mdp_discount.png&quot; data-original-width=&quot;549&quot; data-original-height=&quot;398&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this post I will introduce Markov Decision Processes, a common tool used in Reinforcement Learning, a branch of Machine Learning. By the end of the post you will be able to make some sense of the figure above!&lt;br /&gt;
I will couple the formal details, definitions and maths with an intuitive example that will accompany us throughout this post. In later posts we will make our example more complete and use other examples to explain other properties and characteristics of the MDPs. &lt;br /&gt;
&lt;br /&gt;
Let me introduce the context of the example:&lt;br /&gt;
From a simplistic point of view, I only have two moods: &quot;&lt;i&gt;hungry&lt;/i&gt;&quot; and &quot;&lt;i&gt;thirsty&lt;/i&gt;&quot;. Thankfully, my parents taught me how to eat and how to drink, so that I can fulfill the needs I mentioned earlier. Of course that eating when I am hungry makes me happy, just as drinking when I am thirsty makes me happy! Not only that, but eating when I am hungry &lt;i&gt;usually&lt;/i&gt; satisfies me, much like drinking when I am thirsty &lt;i&gt;usually&lt;/i&gt; satisfies me.&lt;br /&gt;
&lt;br /&gt;
Suppose that, given the situation I just described, you want to study formally the evolution of my happiness as I take different actions and feel different moods. Markov Decision Processes can be used just for that: studying a system with different states (my moods) and different possible actions (eating/drinking), as well as planning the optimal behaviour (the behaviour that makes me the happiest). &lt;br /&gt;
&lt;br /&gt;
Googling for the definition of MDP will eventually take you to the mathematical one, so we might as well just deal with it now. An MDP is a quintuple $(S,A,P_a,R_a,\gamma)$ where:&lt;br /&gt;
$S$ is a set of states, defining the possible ways in which you can be; in my example, $S = \{ \text{Hungry}, \text{Thirsty} \}$ i.e., the states are my moods.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_cPndmM3bHJlaIAVshfjP7lCVQYb2hyphenhyphenf_c36HzN7hrIAGCWMQ9dl5Yx7_t8ju-DZgPqSojXo72IZ5hZpjOVaC0CT5JKX_DEx_HdhbUnOhA02e69bfE0obHnhqwrC7_y4O4vfLQFRI3G8/s1600/mdp_states.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_cPndmM3bHJlaIAVshfjP7lCVQYb2hyphenhyphenf_c36HzN7hrIAGCWMQ9dl5Yx7_t8ju-DZgPqSojXo72IZ5hZpjOVaC0CT5JKX_DEx_HdhbUnOhA02e69bfE0obHnhqwrC7_y4O4vfLQFRI3G8/s1600/mdp_states.png&quot; data-original-width=&quot;507&quot; data-original-height=&quot;230&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
$A$ is the set of actions we can take in each state; in my example, $A = \{ \text{Eat}, \text{Drink} \}$.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjixsGkANTuYXqYVgj2C4_n_WokYI8gOpbu9DF8iMbvK0zy7RhrIe6GVm784HFaTFP-1cvTq78yS-JKn6ogM0sxIrMn4-Nojhyphenhyphen85P9YZOG7-e7UtjT94FvXgl8xWujAPrve3X1CRhoO3U4/s1600/mdp_actions.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjixsGkANTuYXqYVgj2C4_n_WokYI8gOpbu9DF8iMbvK0zy7RhrIe6GVm784HFaTFP-1cvTq78yS-JKn6ogM0sxIrMn4-Nojhyphenhyphen85P9YZOG7-e7UtjT94FvXgl8xWujAPrve3X1CRhoO3U4/s1600/mdp_actions.png&quot; data-original-width=&quot;508&quot; data-original-height=&quot;371&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
$P_a$ is the collection of all transition probabilities. $P_a(s, s&#39;) = P(s_{t+1} = s&#39; | s_t = s, a_t = a)$ is the probability that we change to state $s&#39;$ if we used action $a$ when we were in state $s$. In our notation, $s_t$ is the state we are in at time step $t$ and $a_t$ is the action performed when in time step $t$. In the example (check the figure below) we have $P_E(H, T) = P_D(T, H) = 0.9$ (if we are Thirsty and Drink/if we are Hungry and Eat there is a $90\%$ chance we flip states); $P_E(H, H) = P_D(T, T) = 0.1$ (if we Eat when Hungry/Drink when Thirsty there is a $10\%$ chance we don&#39;t satisfy our needs); $P_E(T, T) = P_D(H, H) = 1$ (if we Drink when Hungry/Eat when Thirsty we end up exactly as we started).&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0zen9xAEaVtzhAGNWyc2Jrkx0RwS8YcKLCdcZHujqTkBBEYD_D7XlQpea5uGJzYxB1m4saORk72K944nACuAnW4fi_MAWjUqoe4A-XAE3huDhAx7Br8f9ITjy7qij8YN1zp_IsJN3ECA/s1600/mdp_transitions.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0zen9xAEaVtzhAGNWyc2Jrkx0RwS8YcKLCdcZHujqTkBBEYD_D7XlQpea5uGJzYxB1m4saORk72K944nACuAnW4fi_MAWjUqoe4A-XAE3huDhAx7Br8f9ITjy7qij8YN1zp_IsJN3ECA/s1600/mdp_transitions.png&quot; data-original-width=&quot;529&quot; data-original-height=&quot;371&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
$R_a$ is the collection of all immediate rewards. $R_a(s, s&#39;)$ is a numerical value representing the reward we get when we reach state $s&#39;$ by using action $a$ when in state $s$. Notice that the reward may be good, if $R_a(s, s&#39;) &gt; 0$, or it may be bad, if $R_a(s, s&#39;) &lt; 0$. In our example the rewards won&#39;t depend on $s&#39;$; for example, if we are Hungry and we Eat we get the exact same reward regardless of the state we go to: $R_E(H,H) = R_E(H,T) = R_D(T,T) = R_D(T,H) = +1$, i.e. trying to meet my needs gives a $+1$ reward, while $R_E(T,T) = R_D(H,H) = 0$, i.e. ignoring my needs isn&#39;t rewarded nor penalized.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6OBhKfdXsArFKXGc-GO74nRTOOPf0CTj4w-GjzIGz0KjLfyyKY9Uat63lJQpgx7gcIggj483ByvJTShZXIJFG1pI6gI1Z3Z9irmNSaQs3DzfeXnyyz7PrdPXVDoazWJk19JpXsVNiDyM/s1600/mdp_rewards.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6OBhKfdXsArFKXGc-GO74nRTOOPf0CTj4w-GjzIGz0KjLfyyKY9Uat63lJQpgx7gcIggj483ByvJTShZXIJFG1pI6gI1Z3Z9irmNSaQs3DzfeXnyyz7PrdPXVDoazWJk19JpXsVNiDyM/s1600/mdp_rewards.png&quot; data-original-width=&quot;541&quot; data-original-height=&quot;375&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Finally, $\gamma \in [0, 1]$ is the discount factor, which can be thought of as an exchange rate: it says that getting a $+1$ right now is as good as getting $+1/\gamma$ in the next time step. For example, if $\gamma = 0.5$, then getting a $+2$ in the next time step would be as good as getting a $+1$ in this time step. When we are trying to predict what is the best action to take at a given point, we need to consider the rewards of the possible actions &lt;b&gt;BUT&lt;/b&gt; we should also try to see some steps ahead, and take into account what are the possible rewards of the future actions that will become available. The bigger $\gamma$ is, the more importance we are giving to future rewards. When $\gamma$ is small, it is as if we don&#39;t really care much about what is going to happen in the future, we only care about getting rewards now. The two limits are $\gamma = 0$ and $\gamma = 1$. When $\gamma = 0$, we care &lt;b&gt;nothing&lt;/b&gt; about the future; when $\gamma = 0$, a reward of $+1$ now is better than any reward you can be offered in the next time step. When $\gamma = 1$, &lt;b&gt;all&lt;/b&gt; future rewards are &lt;b&gt;equally&lt;/b&gt; important, whether they are promised to you in the next time step or in $1000000$ time steps.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAG_2IOPsbeJDZ_IJT0OlfTB6ZXDUXC2j90ci7kN-QUs9sZg1sweoZ71yH9rdCPKTX4A84BRPW2sy4NgX-dOh6MZ9jPnZu0tIgFjAh0rSMvcV35yeydcT1EvaBy-EiJ1Hj-kiq5XfwIuA/s1600/mdp_discount.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAG_2IOPsbeJDZ_IJT0OlfTB6ZXDUXC2j90ci7kN-QUs9sZg1sweoZ71yH9rdCPKTX4A84BRPW2sy4NgX-dOh6MZ9jPnZu0tIgFjAh0rSMvcV35yeydcT1EvaBy-EiJ1Hj-kiq5XfwIuA/s1600/mdp_discount.png&quot; data-original-width=&quot;549&quot; data-original-height=&quot;398&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Now that we defined an MDP, what do we do? Usually one is looking for a &lt;i&gt;strategy&lt;/i&gt; to employ that maximizes its rewards. Think of the MDP as a game and suppose the rewards are your points. Whenever you are in a state you must choose an action and then your points will change according to the reward. Your task is to find the best possible strategy for the game. In this context, we usually call &lt;i&gt;policy&lt;/i&gt; to our &quot;winning strategy&quot;. Commonly represented as $\pi$, the policy is a function $\pi: S \to A$ that receives states and outputs actions: when we are in a state $s \in S$ we should do action $\pi(s)$.
For our example it is quite clear that our winning strategy (i.e. our policy) is to Drink when we are Thirsty ($\pi(T) = D$) and to Eat when we are Hungry ($\pi(H) = E)$, right?&lt;br /&gt;
&lt;br /&gt;
How can we justify that? And for more complex examples, how do we find a winning strategy?&lt;br /&gt;
To answer the first question, a bit of maths can do the trick... as for the second question, the area of Reinforcement Learning provides us with algorithms to find the winning strategy!&lt;br /&gt;
&lt;br /&gt;
Both questions will be answered in future posts, so &lt;a href=&quot;https://eepurl.com/drHcrr&quot; target=&quot;_blank&quot;&gt;subscribe to our mailing list&lt;/a&gt;, like the &lt;a href=&quot;https://www.facebook.com/mathspp/&quot; target=&quot;_blank&quot;&gt;blog on facebook&lt;/a&gt; and follow the &lt;a href=&quot;https://www.instagram.com/mathsppblog/&quot; target=&quot;_blank&quot;&gt;blog on instagram&lt;/a&gt; so as to stay tuned!&lt;br /&gt;
&lt;br /&gt;
This post was brought to you because of the &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/pledging-to-do-100-days-of-machine.html&quot; target=&quot;_blank&quot;&gt;#100DaysofMLCode&lt;/a&gt; initiative.&lt;br /&gt;
&lt;br /&gt;
All posts on the MDP series:&lt;br /&gt;
&lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-basics.html&quot; target=&quot;_blank&quot;&gt;MDP#01 Basics&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-02-how.html&quot; target=&quot;_blank&quot;&gt;MDP#02 Discount Factor&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://mathspp.blogspot.com/2018/10/markov-decision-processes-03-optimal.html&quot; target=&quot;_blank&quot;&gt;MDP#03 Optimal Policy Variation&lt;/a&gt;&lt;br /&gt;

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;
(tradução indisponível por agora)&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/3399821072862209913'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/3399821072862209913'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/09/markov-decision-processes-basics.html' title='Markov Decision Processes 01: the basics'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAG_2IOPsbeJDZ_IJT0OlfTB6ZXDUXC2j90ci7kN-QUs9sZg1sweoZ71yH9rdCPKTX4A84BRPW2sy4NgX-dOh6MZ9jPnZu0tIgFjAh0rSMvcV35yeydcT1EvaBy-EiJ1Hj-kiq5XfwIuA/s72-c/mdp_discount.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-7426179581457261165</id><published>2018-09-24T19:43:00.000+01:00</published><updated>2018-09-26T09:38:52.700+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="astronomy"/><category scheme="http://www.blogger.com/atom/ns#" term="counterintuitive"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="exponential"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><title type='text'>Twitter proof: folding my way to the moon</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuGxJhQ3M1-mAqA_eW5_TVNTm6fT1LzoMk2l_2q4r-K4-KoLxyvBmGuMdVOzUsS1u6_536VnJkiMs1aMyumZfvMoytr-IbLrKlf8BZOWzEVG72D61UGME4kd3cOs8-GXPKgOo72HxqJVc/s1600/foldingMoon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuGxJhQ3M1-mAqA_eW5_TVNTm6fT1LzoMk2l_2q4r-K4-KoLxyvBmGuMdVOzUsS1u6_536VnJkiMs1aMyumZfvMoytr-IbLrKlf8BZOWzEVG72D61UGME4kd3cOs8-GXPKgOo72HxqJVc/s1600/foldingMoon.png&quot; data-original-width=&quot;300&quot; data-original-height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this twitter proof we will see how the exponential function can mess up with objects from our daily lives!.. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Claim:&lt;/b&gt; with less than $50$ folds, a piece of paper will be so thick that it will cover the distance from the Earth to the Moon. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Twitter proof:&lt;/b&gt; a common sheet of paper is $0.1$mm thick. If we fold it once, it becomes $0.2$mm thick. Folding twice, $0.4$mm. Folding $49$ times, the paper becomes $2^{49}\times 0.1$mm thick, which is around $5.63\times 10^{13} $mm or $5.63\times10^7$km, $141$ times the distance from the Earth to the Moon ($398818$km).

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post vamos ver como a função exponencial pode interagir com objetos do nosso quotidiano e criar resultados inesperados. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Proposição:&lt;/b&gt; com menos de $50$ dobras, uma folha de papel fica com uma grossura superior à distância da Terra à Lua.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Prova num tweet:&lt;/b&gt; uma folha de papel normal tem $0.1$mm de grossura. Se a dobrarmos uma vez, fica com $0.2$mm de grossura. Dobrando de novo, fica com $0.4$mm. Dobrando $49$ vezes, a folha fica com uma grossura de $2^{49}\times 0.1$mm, que dá aproximadamente $5.63\times 10^{13} $mm ou $5.63\times10^7$hm, $141$ vezes mais do que a distância entre a Terra e a Lua ($398818$km).

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/7426179581457261165'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/7426179581457261165'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/09/twitter-proof-folding-my-way-to-moon.html' title='Twitter proof: folding my way to the moon'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuGxJhQ3M1-mAqA_eW5_TVNTm6fT1LzoMk2l_2q4r-K4-KoLxyvBmGuMdVOzUsS1u6_536VnJkiMs1aMyumZfvMoytr-IbLrKlf8BZOWzEVG72D61UGME4kd3cOs8-GXPKgOo72HxqJVc/s72-c/foldingMoon.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-4651576777984496664</id><published>2018-09-18T17:53:00.002+01:00</published><updated>2018-09-21T18:31:18.845+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="100daysofmlcode"/><category scheme="http://www.blogger.com/atom/ns#" term="artificial intelligence"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="machine learning"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="neural networks"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><title type='text'>Twitter proof: neural networks and the linear activation function</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this post we will see why it is not helpful to have two consecutive layers of neurons with linear activation functions in neural networks. With just a bit of maths we can conclude that $n$ consecutive linear layers compute the exact same functions as $1$ single layer.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Claim:&lt;/b&gt; having two fully connected layers of neurons using linear activation functions is the same as having just one layer with a linear activation function.&lt;br /&gt;
&lt;br /&gt;
We just have to lay down some notation in order for the maths to be doable. Assume the two consecutive layers of linear neurons are preceded by a layer with $n_0$ neurons, whose outpus are $o_1, o_2, \cdots, o_{n_0}$.&lt;br /&gt;
Let us say that after that layer, there is a layer of $n_1$ neurons with linear activation functions $f_i(x) = a_ix + b_i$; the weight from neuron $t$ of the previous layer to the neuron $i$ of this layer is $w_{t,i}$.&lt;br /&gt;
The second layer of neurons has $n_2$ neurons, with linear activation functions $f_i&#39;(x) = a_i&#39;x+b_i&#39;$ and the weight from neuron $i$ of the previous layer to neuron $j$ of this layer is $w&#39;_{i,j}$.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Twitter proof:&lt;/b&gt; we will compute the outputs produced by the second layer, in terms of the values $o_1, \cdots, o_{n_0}$ of the $0$-th layer and conclude we obtain a linear function of those. The output of the $j$-th neuron will be:&lt;br /&gt;
$$\begin{align}
f&#39;_j\left[\sum_{i=1}^{n_1}w&#39;_{i,j}f_i\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right)\right] &amp;= a&#39;_j\times\left[\sum_{i=1}^{n_1}w&#39;_{i,j}f_i\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right) \right] + b&#39;_j\\
&amp;=a&#39;_j  \left[\sum_{i=1}^{n_1}w&#39;_{i,j}\left(a_i\times\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right) + b_i\right) \right] + b&#39;_j\\
&amp;=a&#39;_j  \left[\sum_{i=1}^{n_1}w&#39;_{i,j}a_i\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right) + \sum_{i=1}^{n_1}w&#39;_{i,j}b_i \right] + b&#39;_j\\
&amp;=a&#39;_j  \left[\sum_{i=1}^{n_1}w&#39;_{i,j}a_i\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right)\right] + a&#39;_j\sum_{i=1}^{n_1}w&#39;_{i,j}b_i + b&#39;_j\\
&amp;=a&#39;_j  \left[\sum_{t=1}^{n_0} \sum_{i=1}^{n_1}w&#39;_{i,j}a_i w_{t,i}o_t\right] + a&#39;_j\sum_{i=1}^{n_1}w&#39;_{i,j}b_i + b&#39;_j\\
\end{align}$$
now defining $a&#39;&#39;_j = a&#39;_j$,
$$b&#39;&#39;_j = b&#39;_j + a&#39;_j \sum_{i=1}^{n_1}w&#39;_{i,j}b_i$$
and
$$w&#39;&#39;_{t,j} = \sum_{i=1}^{n_1} w&#39;_{i,j} a_i w_{t,i}$$
we get that the output of the $j$-th neuron really is
$$f&#39;&#39;_j\left(\sum_{t=1}^{n_0} w&#39;&#39;_{t,j} o_t\right)$$
where $f&#39;&#39;_j(x) = a&#39;&#39;_jx + b&#39;&#39;_j$, a linear function. This concludes our proof!&lt;br /&gt;
&lt;br /&gt;
I wrote this post today because of the &lt;a href=&quot;https://mathspp.blogspot.com/2018/09/pledging-to-do-100-days-of-machine.html&quot; target=&quot;_blank&quot;&gt;#100DaysofMLcode&lt;/a&gt; initiative I started (yesterday!)!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post vou mostrar porque é que não é nada útil, em redes neuronais, ter duas camadas consecutivas de neurónios com função de ativação linear. De facto, $n$ camadas consecutivas de neurónios com função de ativação linear calculam exatamente as mesmas funções que apenas $1$ camada!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Proposição:&lt;/b&gt; ter duas camadas consecutivas, totalmente ligadas, cuja função de ativação é linear, é exatamente o mesmo que ter apenas uma camada com função de ativação linear.&lt;br /&gt;
&lt;br /&gt;
Para eu poder fazer as contas preciso apenas de estabelecer alguma notação. Vamos assumir que as duas camadas consecutivas de neurónios são precedidas por uma camada com $n_0$ neurónios, cujos outputs são $o_1, o_2, \cdots, o_{n_0}$.&lt;br /&gt;
Digamos que a camada seguinte é uma camada de $n_1$ neurónios que usam uma função de ativação linear $f_i(x) = a_ix + b_i$; o peso que vai do neurónio $t$ da camada anterior para o neurónio $i$ desta camada é $w_{t,i}$.&lt;br /&gt;
A segunda camada tem $n_2$ neurónios, com funções lineares de ativação $f_i&#39;(x) = a&#39;_ix + b&#39;_i$; o peso que vai do neurónio $i$ da camada anterior para o neurónio $j$ desta camada é $w&#39;_{i,j}$.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Prova num tweet:&lt;/b&gt; vamos calcular o output do $j$-ésimo neurónio desta segunda camada, em função dos outputs $o_1, \cdots, o_{n_0}$ da $0$-ésima camada, e verificar que obtemos uma expressão que depende linearmente desses valores. De facto, o output do $j$-ésimo neurónio da segunda camada vai ser:&lt;br /&gt;
$$\begin{align}
f&#39;_j\left[\sum_{i=1}^{n_1}w&#39;_{i,j}f_i\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right)\right] &amp;= a&#39;_j\times\left[\sum_{i=1}^{n_1}w&#39;_{i,j}f_i\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right) \right] + b&#39;_j\\
&amp;=a&#39;_j  \left[\sum_{i=1}^{n_1}w&#39;_{i,j}\left(a_i\times\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right) + b_i\right) \right] + b&#39;_j\\
&amp;=a&#39;_j  \left[\sum_{i=1}^{n_1}w&#39;_{i,j}a_i\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right) + \sum_{i=1}^{n_1}w&#39;_{i,j}b_i \right] + b&#39;_j\\
&amp;=a&#39;_j  \left[\sum_{i=1}^{n_1}w&#39;_{i,j}a_i\left(\sum_{t=1}^{n_0} w_{t,i}o_t\right)\right] + a&#39;_j\sum_{i=1}^{n_1}w&#39;_{i,j}b_i + b&#39;_j\\
&amp;=a&#39;_j  \left[\sum_{t=1}^{n_0} \sum_{i=1}^{n_1}w&#39;_{i,j}a_i w_{t,i}o_t\right] + a&#39;_j\sum_{i=1}^{n_1}w&#39;_{i,j}b_i + b&#39;_j\\
\end{align}$$
definindo agora $a&#39;&#39;_j = a&#39;_j$,
$$b&#39;&#39;_j = b&#39;_j + a&#39;_j \sum_{i=1}^{n_1}w&#39;_{i,j}b_i$$
e
$$w&#39;&#39;_{t,j} = \sum_{i=1}^{n_1} w&#39;_{i,j} a_i w_{t,i}$$
verificamos que o output do $j$-ésimo neurónio é
$$f&#39;&#39;_j\left(\sum_{t=1}^{n_0} w&#39;&#39;_{t,j} o_t\right)$$
onde $f&#39;&#39;_j(x) = a&#39;&#39;_jx + b&#39;&#39;_j$ é uma função linear. Isto conclui a nossa prova!&lt;br /&gt;
&lt;br /&gt;
Escrevi este post hoje por causa da iniciativa &lt;a href=&quot;https://mathspp.blogspot.com/2018/09/pledging-to-do-100-days-of-machine.html&quot; target=&quot;_blank&quot;&gt;#100DaysofMLcode&lt;/a&gt; que comecei (ontem!)!

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/4651576777984496664'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/4651576777984496664'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/09/twitter-proof-neural-networks-and.html' title='Twitter proof: neural networks and the linear activation function'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-6406935270545644874</id><published>2018-09-17T23:27:00.000+01:00</published><updated>2019-03-06T20:32:51.769+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="100daysofmlcode"/><category scheme="http://www.blogger.com/atom/ns#" term="algorithms"/><category scheme="http://www.blogger.com/atom/ns#" term="artificial intelligence"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="machine learning"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><title type='text'>Pledging to do 100 days of Machine Learning and progress log!</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDiKgXkKRpTiMYI1sRwp59G9njZ1JUXz5lQi8MO6rBZuG1kpI6a_tGeKmqFi9zXgClXNrDCnaYSckzgLw2S5ro9fHTjvt2QHIhZpGxKF_MO-sDoYRMJLQcNy0dJBJ2O82UXBqafQ5Z_Jc/s1600/100daysofmlcode.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDiKgXkKRpTiMYI1sRwp59G9njZ1JUXz5lQi8MO6rBZuG1kpI6a_tGeKmqFi9zXgClXNrDCnaYSckzgLw2S5ro9fHTjvt2QHIhZpGxKF_MO-sDoYRMJLQcNy0dJBJ2O82UXBqafQ5Z_Jc/s320/100daysofmlcode.png&quot; width=&quot;320&quot; height=&quot;74&quot; data-original-width=&quot;942&quot; data-original-height=&quot;219&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

&lt;h3&gt;It is a shame but I kind of dropped this when I was $41\%$ done...&lt;/h3&gt;
I hope I man up and finish this in the near future.&lt;br /&gt;
&lt;br /&gt;
After watching &lt;a href=&quot;https://www.youtube.com/watch?v=cuQMBj1cWPo&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt; video from Siraj Raval, I decided to jump right on board of the #100daysofMLcode initiative! (even though I am something like 73 days late...) The goal here is to devote (at least) 1h every day, for the next 100 days, to studying ML or writing code!&lt;br /&gt;
&lt;br /&gt;
According to the &lt;i&gt;rules&lt;/i&gt; posted by Siraj, I must:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Make a public pledge for this, which this post is;&lt;/li&gt;
&lt;li&gt;Make a log of everything, which this post will also be;&lt;/li&gt;
&lt;li&gt;Whenever I see something related to this #100DaysofMLCode, be supportive!&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;h2&gt;Progress log&lt;/h2&gt;
For the day $0$ I wrote this post and spent quite some time thinking about what I will do throughout. I am thinking of studying several topics about ML and then writing educative posts here, for the blog.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt; For today I wrote &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/twitter-proof-neural-networks-and.html&quot; target=&quot;_blank&quot;&gt;this twitter proof&lt;/a&gt;, tackling a mathematical property of neural networks with linear activation functions.&lt;/li&gt;
&lt;li&gt;Started reading about Reinforcement Learning and Markov Decision Processes; already imagined a nice example I will be using when writing about this... it will involve cake, lemonade and eventually a stomach ache. &lt;/li&gt;
&lt;li&gt;I have been reading more about MDPs, and I found &lt;a href=&quot;https://stats.stackexchange.com/questions/145122/real-life-examples-of-markov-decision-processes&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt; answer on Cross Validated specially enlightening. &lt;/li&gt;
&lt;li&gt;Reading more about the functioning of MDPs in &lt;a href=&quot;https://towardsdatascience.com&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt; blog (which seems to have taken inspiration from &lt;a href=&quot;http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching_files/MDP.pdf&quot; target=&quot;_blank&quot;&gt;these&lt;/a&gt; slides for &lt;a href=&quot;https://towardsdatascience.com/reinforcement-learning-demystified-markov-decision-processes-part-1-bf00dda41690&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt; particular blog post).&lt;/li&gt;
&lt;li&gt;Kept reading the resources from above; started sketching an example MDP to be used in my next blog post.&lt;/li&gt;
&lt;li&gt;Finished sketching the example MDP and did some calculations related to it; started writing the first blog post about this and created a representation of the MDP for the post.&lt;/li&gt;
&lt;li&gt;Finished writing and published &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-basics.html&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt; post on the basics of Markov Decision Processes.&lt;/li&gt;
&lt;li&gt;Started writing the second post on MDPs, where we will explore how the changes in $\gamma $ and the transition probabilities affect the policies.&lt;/li&gt;
&lt;li&gt;I wrote &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-02-how.html&quot; target=&quot;_blank&quot;&gt;another post&lt;/a&gt; on MDPs, this time about the discount factor $\gamma$.&lt;/li&gt;
&lt;li&gt;Following up on the last post, I wrote &lt;a href=&quot;http://mathspp.blogspot.com/2018/10/markov-decision-processes-03-optimal.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; about how the optimal policy can change when the discount factor changes.&lt;/li&gt;
&lt;li&gt;Decided to use the Hanoi Towers as a model problem and started encoding it as an MDP; wrote some helper code for that and you can find such code &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Kept writing the code from the previous day and applied the algorithm of value iteration to the Hanoi Towers, solving them. The code is in &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;this GitHub repo&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Wrote &lt;a href=&quot;http://mathspp.blogspot.com/2018/10/markov-decision-processes-04-encoding.html&quot; target=&quot;_blank&quot;&gt;this post&lt;/a&gt; on how to encode the problem of the Tower of Hanoi into an MDP.&lt;/li&gt;
&lt;li&gt;Wrote the code for the policy iteration algorithm to solve the Tower of Hanoi; the code is in &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;my GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Today I tried implementing Q-learning to solve the Tower of Hanoi. It isn&#39;t learning properly yet, so I decided not to upload the code to GitHub.&lt;/li&gt;
&lt;li&gt;For today I have been all over the internet to try and find the reason why my Q-learning algorithm isn&#39;t working... Still haven&#39;t succeeded.&lt;/li&gt;
&lt;li&gt;Because Q-learning wasn&#39;t working I tried to implement double Q-learning, just to be sure my problem wasn&#39;t one of bias. At first double Q-learning wasn&#39;t working as well, but now both algorithms are working just fine! They have been &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;uploaded to GitHub&lt;/a&gt; now.&lt;/li&gt;
&lt;li&gt;Started writing a Python notebook where I will explain the algorithms and show how to use them to solve the Tower of Hanoi. Those explanations will also be put here in the blog as they are written. The notebook can be found in &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;my GitHub&lt;/a&gt; as well.&lt;/li&gt;
&lt;li&gt;Kept on working on the notebook! Practically finished the section on value iteration.&lt;/li&gt;
&lt;li&gt;I had to stop a bit; sorry for that! I am back and I have been reading about ML on financial markets and have been taking an online course about data science. It isn&#39;t exactly the same as ML, but knowing how to handle data ought to make me better at ML, right?&lt;/li&gt;
&lt;li&gt;Kept taking the course Data Science: Visualization on edX.&lt;/li&gt;
&lt;li&gt;Today I read about using machine learning for text translation.&lt;/li&gt;
&lt;li&gt;Advanced a lot in one of the modules of the Data Science course...&lt;/li&gt;
&lt;li&gt;And today I finished it!&lt;/li&gt;
&lt;li&gt;I started the module on probability...&lt;/li&gt;
&lt;li&gt;And today I kept going...&lt;/li&gt;
&lt;li&gt;And finished it today!&lt;/li&gt;
&lt;li&gt;Today I resumed my work on the Hanoi RL notebook.&lt;/li&gt;
&lt;li&gt;Wrote about Q-learning and double Q-learning on my notebook.&lt;/li&gt;
&lt;li&gt;Started the new module of the Data Science course.&lt;/li&gt;
&lt;li&gt;Kept learning!&lt;/li&gt;
&lt;li&gt;Today I kept learning for the course I am taking.&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;For the past days I have been studying for my online course... I think I have done around 2/3 of the course by now.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;Are you into #100DaysofMLCode as well? Let me know in the comments what you have been doing!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

&lt;h3&gt;Perdi-me quando estava a $41\%$ desta tarefa, o que é um pouco vergonhoso...&lt;/h3&gt;
Espero decidir voltar a isto em breve.&lt;br /&gt;
&lt;br /&gt;
Depois de ter visto &lt;a href=&quot;https://www.youtube.com/watch?v=cuQMBj1cWPo&quot; target=&quot;_blank&quot;&gt;este&lt;/a&gt; vídeo do Siraj Raval, decidi fazer parte do &lt;i&gt;movimento&lt;/i&gt; #100DaysofMLCode! (apesar de já vir uns 73 dias atrasado...) O objetivo desta iniciativa é dedicar (pelo menos) 1h por dia, durante os próximos 100 dias, à aprendizagem automática (ML): quer estudando, quer escrevendo código.&lt;br /&gt;
&lt;br /&gt;
De acordo com as regras que o Siraj publicou, devo:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Comprometer-me publicamente a levar esta iniciativa até ao fim (e a fazer &quot;figura de urso&quot; se me perder a meio);&lt;/li&gt;
&lt;li&gt;Registar publicamente os meus progressos diários;&lt;/li&gt;
&lt;li&gt;Quando eu vir alguma coisa marcada com o hashtag #100DaysofMLCode, devo encorajar os autores.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;h2&gt;Registo diário&lt;/h2&gt;
Para o dia $0$ escrevi este post e gastei algum tempo a pensar sobre o que vou fazer. Tenciono ir estudando tópicos diversos e escrever posts educativos aqui no blog.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt; Hoje escrevi &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/twitter-proof-neural-networks-and.html&quot; target=&quot;_blank&quot;&gt;esta prova num tweet&lt;/a&gt;, sobre uma curiosidade matemática relacionada com redes neuronais e a função de ativação linear. &lt;/li&gt;
&lt;li&gt;Comecei a ler sobre Reinforcement Learning e Markov Decision Processes. Também já imaginei um pequeno exemplo que vou usar para explicar estas noções; vai involver bolo, limonada e, quando chegar a altura, dores de barriga. &lt;/li&gt;
&lt;li&gt;Continuei a ler sobre MDPs e &lt;a href=&quot;https://stats.stackexchange.com/questions/145122/real-life-examples-of-markov-decision-processes&quot; target=&quot;_blank&quot;&gt;esta&lt;/a&gt; resposta no Cross Validated foi particularmente esclarecedora... ou se calhar foi só porque finalmente tudo fez &quot;clique&quot;!&lt;/li&gt;
&lt;li&gt;Ler mais sobre o modo como MDPs funcionam &lt;a href=&quot;https://towardsdatascience.com&quot; target=&quot;_blank&quot;&gt;neste&lt;/a&gt; blog (que parece ter-se inspirado &lt;a href=&quot;http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching_files/MDP.pdf&quot; target=&quot;_blank&quot;&gt;nestes&lt;/a&gt; slides para &lt;a href=&quot;https://towardsdatascience.com/reinforcement-learning-demystified-markov-decision-processes-part-1-bf00dda41690&quot; target=&quot;_blank&quot;&gt;este&lt;/a&gt; post em particular).&lt;/li&gt;
&lt;li&gt;Continuei a ler os recursos disponíveis aqui em cima; comecei a rascunhar um MDP que vou usar no meu próximo post.&lt;/li&gt;
&lt;li&gt;Acabei o rabisco do MDP e fiz umas contas com ele; comecei a escrever o primeiro post do blog e criei uma representação esquemática do MDP para vos apresentar.&lt;/li&gt;
&lt;li&gt;Acabei de escrever e publiquei &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-basics.html&quot; target=&quot;_blank&quot;&gt;este&lt;/a&gt; post sobre Markov Decision Processes.&lt;/li&gt;
&lt;li&gt;Comecei a escrever o próximo post sobre MDPs, um post onde se vão explorar os efeitos de alterar o factor $\gamma $ e as probabilidades de transição.&lt;/li&gt;
&lt;li&gt;Escrevi &lt;a href=&quot;http://mathspp.blogspot.com/2018/09/markov-decision-processes-02-how.html&quot; target=&quot;_blank&quot;&gt;outro post&lt;/a&gt; sobre MDPs, desta vez sobre o factor de desconto $\gamma$.&lt;/li&gt;
&lt;li&gt;No seguimento do último post, escrevi &lt;a href=&quot;http://mathspp.blogspot.com/2018/10/markov-decision-processes-03-optimal.html&quot; target=&quot;_blank&quot;&gt;aqui&lt;/a&gt; sobre como a melhor estratégia pode variar quando o factor $\gamma$ varia.&lt;/li&gt;
&lt;li&gt;Decidi que o problema das Torres de Hanoi vai ser o meu problema exemplo e comecei a codificá-lo num MDP; escrevi algum código para me ajudar nessa tarefa e o dito código pode ser encontrado &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;aqui&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Acabei o código do dia anterior e usei o algoritmo de &quot;value iteration&quot; no problema das Torres de Hanoi, resolvendo-o. O código está todo &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;neste repositório do GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Escrevi &lt;a href=&quot;http://mathspp.blogspot.com/2018/10/markov-decision-processes-04-encoding.html&quot; target=&quot;_blank&quot;&gt;este post&lt;/a&gt; sobre como transformar o problema da Torre de Hanoi num MDP.&lt;/li&gt;
&lt;li&gt;Escrevi o código para resolver a Torre de Hanoi com o algoritmo da policy iteration; o código está &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;no meu GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Hoje implementei o algoritmo de Q-learning para resolver a Torre de Hanoi. O código ainda não está a funcionar e por isso ainda não fiz o upload do ficheiro para o GitHub.&lt;/li&gt;
&lt;li&gt;Andei por todo o lado na internet a tentar descobrir porque é que o meu algoritmo de Q-learning não está a funcionar... Por enquanto, sem sucesso.&lt;/li&gt;
&lt;li&gt;O algoritmo de Q-learning não estava a funcionar e eu achei que pudesse ser um problema de bias, então tentei implementar double Q-learning. Primeiro, nenhum dos dois estava a funcionar, depois consegui pôr os dois a funcionar corretamente! Já fiz o upload do código para &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;o meu GitHub&lt;/a&gt; now.&lt;/li&gt;
&lt;li&gt;Comecei a escrever um notebook de Python onde vou explicar os algoritmos que implementei e onde mostro como usá-los para resolver a Torre de Hanoi. Essas explicações também vão sendo postas aqui no blog à medida que forem concluídas. O notebook também pode ser encontrado no &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/HanoiRL&quot; target=&quot;_blank&quot;&gt;meu GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Continuei a trabalhar no notebook e a secção sobre o algoritmo de value iteration está praticamente concluída.&lt;/li&gt;
&lt;li&gt;Infelizmente parei um par de dias, mas estou de volta! Tenho lido um pouco sobre ML nos mercados financeiros e tenho continuado um curso sobre ciência de dados que comecei no Verão. Eu sei que ML e ciência de dados não são a mesma coisa, mas saber mexer em dados há de me ser favorável, não?&lt;/li&gt;
&lt;li&gt;Continuei o curso sobre visualização de dados no edX.&lt;/li&gt;
&lt;li&gt;Hoje li sobre como usar ML para traduzir textos.&lt;/li&gt;
&lt;li&gt;Fiz grandes progressos num dos módulos do curso sobre ciência de dados...&lt;/li&gt;
&lt;li&gt;E hoje acabei-o!&lt;/li&gt;
&lt;li&gt;Hoje comecei o módulo sobre probabilidade.&lt;/li&gt;
&lt;li&gt;E hoje continuei-o...&lt;/li&gt;
&lt;li&gt;E acabei-o hoje!&lt;/li&gt;
&lt;li&gt;Hoje dei continuidade ao trabalho que já tinha feito no notebook sobre RL aplicado à Torre de Hanoi.&lt;/li&gt;
&lt;li&gt;Escrevi sobre Q-learning e double Q-learning no meu notebook.&lt;/li&gt;
&lt;li&gt;Comecei o módulo seguinte do curso de ciência de dados.&lt;/li&gt;
&lt;li&gt;Continuei a aprender.&lt;/li&gt;
&lt;li&gt;Hoje dei continuidade ao curso que estou a fazer.&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;Nos últimos dias tenho estudado para o curso online. Acho que por esta altura já acabei 2/3 do curso.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;Há aqui algum leitor envolvido com o #100DaysofMLCode? Digam nos comentários o que andam a fazer!

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6406935270545644874'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/6406935270545644874'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/09/pledging-to-do-100-days-of-machine.html' title='Pledging to do 100 days of Machine Learning and progress log!'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDiKgXkKRpTiMYI1sRwp59G9njZ1JUXz5lQi8MO6rBZuG1kpI6a_tGeKmqFi9zXgClXNrDCnaYSckzgLw2S5ro9fHTjvt2QHIhZpGxKF_MO-sDoYRMJLQcNy0dJBJ2O82UXBqafQ5Z_Jc/s72-c/100daysofmlcode.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-394685047272357656</id><published>2018-09-16T19:59:00.000+01:00</published><updated>2018-09-16T20:02:14.327+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bfs"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="games"/><category scheme="http://www.blogger.com/atom/ns#" term="graphs"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="permutations"/><category scheme="http://www.blogger.com/atom/ns#" term="processing"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="puzzle"/><title type='text'>MatchWalker, a puzzle game of shape and colour</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguR2L9aOFAeZaWFBiH51plcneoefOkRIo6dcN_8kqmssLSRrPCsNOAUE8jcAc_njolr1iVwnZN_eQQ-sh7lYeRvbm8OeJeU1dJ0FzSnTqz4mcrQX-4qSbFEDh_5v7IWaThS4jvKsFFih0/s1600/matchwalker_screenshot.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguR2L9aOFAeZaWFBiH51plcneoefOkRIo6dcN_8kqmssLSRrPCsNOAUE8jcAc_njolr1iVwnZN_eQQ-sh7lYeRvbm8OeJeU1dJ0FzSnTqz4mcrQX-4qSbFEDh_5v7IWaThS4jvKsFFih0/s320/matchwalker_screenshot.png&quot; width=&quot;320&quot; height=&quot;250&quot; data-original-width=&quot;817&quot; data-original-height=&quot;638&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In today&#39;s post I will be sharing a game I made with just under $400$ lines in Processing, a wrapper for Java that makes drawing to the screen really easy.&lt;br /&gt;
&lt;br /&gt;
The goal of the game is really simple: go from the cell you are standing on (marked with the black outline of the ellipse, in the screenshot) to the cell that is framed in white. To do that, you can move a &quot;cursor&quot; (the black frame) with the $AWSD$ keys to choose the next cell you want to go to. To move, press the space bar. There are a couple of rules to moving, though:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;You can only move to the selected cell if it is in the same row or same column as the cell you are in;&lt;/li&gt;
&lt;li&gt;You can only move to the selected cell if it has the same colour or the same shape as the cell you are in.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
Rule number $1$ says you can only go in the directions these orange arrows cover:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1BkL6SlR4jhVNu7NFp3bAo_khFUCMC687Hm_iB458OejGHR7HYlXDyV0_BJ5Oei3a9npjh95qjJQXHCDNvDiSo1ART7PKzJtLB8dQIr1YJrZ4o4xVm039m1lGa9zq8D65baOzY00a86I/s1600/matchwalker_rule1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1BkL6SlR4jhVNu7NFp3bAo_khFUCMC687Hm_iB458OejGHR7HYlXDyV0_BJ5Oei3a9npjh95qjJQXHCDNvDiSo1ART7PKzJtLB8dQIr1YJrZ4o4xVm039m1lGa9zq8D65baOzY00a86I/s320/matchwalker_rule1.png&quot; width=&quot;320&quot; height=&quot;250&quot; data-original-width=&quot;554&quot; data-original-height=&quot;433&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Rule number $2$ says that, from the cells specified by the above rule, you can only go to the white circle, diamond or vertical ellipse (precisely because they are white) or to the orange horizontal ellipse, because it has the same shape as the cell you are in (a horizontal white ellipse).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpsfu6y8CeHkvRQJugoIZn-RR2nt31gmxQMQ2oPgF2_uIKhUyQ8_3g65BDcxSdk_G3IubstXyqxglT1BKeGFc4XqcnaHQ14mb7JboiiLRDqfKGxAhij82qAtCdS7HvQuO_CesgNaHFItI/s1600/matchwalker_rule2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpsfu6y8CeHkvRQJugoIZn-RR2nt31gmxQMQ2oPgF2_uIKhUyQ8_3g65BDcxSdk_G3IubstXyqxglT1BKeGFc4XqcnaHQ14mb7JboiiLRDqfKGxAhij82qAtCdS7HvQuO_CesgNaHFItI/s320/matchwalker_rule2.png&quot; width=&quot;320&quot; height=&quot;250&quot; data-original-width=&quot;555&quot; data-original-height=&quot;434&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
With these rules in mind, one possible way to finish the puzzle from the screenshot would be to follow these arrows:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiCzTUXZ1PzBY5l3DlihuV_6PZJSywXDow55NW30zy4ENL9C8IN70jWPyGg5z0awoqX1rlRKTtz8hwdTMVS2dtWZ4DidrMWjnJ1F-kSrU9O7f9MhTCdzmXPSbmlHyvktT4_1QcsCWYpJQ/s1600/matchwalker_validpath.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiCzTUXZ1PzBY5l3DlihuV_6PZJSywXDow55NW30zy4ENL9C8IN70jWPyGg5z0awoqX1rlRKTtz8hwdTMVS2dtWZ4DidrMWjnJ1F-kSrU9O7f9MhTCdzmXPSbmlHyvktT4_1QcsCWYpJQ/s320/matchwalker_validpath.png&quot; width=&quot;320&quot; height=&quot;249&quot; data-original-width=&quot;555&quot; data-original-height=&quot;432&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
The path being: first you go down to the &lt;b&gt;white&lt;/b&gt; diamond and then up to the orange &lt;b&gt;diamond&lt;/b&gt;; after that you go right to the &lt;b&gt;orange&lt;/b&gt; circle, up to the &lt;b&gt;orange&lt;/b&gt; vertical ellipse and then left to your final destination, the &lt;b&gt;orange&lt;/b&gt; square.&lt;br /&gt;
&lt;br /&gt;
When a given target cell is giving you too much trouble, you can press $Q$ to select a new target (i.e. the white frame chooses another cell for you to go to).&lt;br /&gt;
&lt;br /&gt;
If any of you wants to contribute, there is one improvement I think could be made to the way the board is generated. As of now, I hard-coded four $3\times 3$ pieces and whenever the game starts, I shuffle them into the four corners and then randomly rotate them, thus creating the illusion of having a &quot;new, random board&quot; every time you start:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSCiAMkfN2ZuWciPzBsTHYgqP2dCc7He14zG_9EG7fE05zNlAv_GCqHEVg1Z13E_m_I5-XIikld8AuK_t2zZfDp0u99YPneZm2Y9-BXlbuBst5gwBuoE1qJPOjGXwaZvnebPIBSdte2vY/s1600/matchwalker_screenshot2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSCiAMkfN2ZuWciPzBsTHYgqP2dCc7He14zG_9EG7fE05zNlAv_GCqHEVg1Z13E_m_I5-XIikld8AuK_t2zZfDp0u99YPneZm2Y9-BXlbuBst5gwBuoE1qJPOjGXwaZvnebPIBSdte2vY/s320/matchwalker_screenshot2.png&quot; width=&quot;320&quot; height=&quot;250&quot; data-original-width=&quot;816&quot; data-original-height=&quot;638&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
The board can, however be created in another way: just randomly assign each piece to a position of the board and then use a simple algorithm like a breadth-first or depth-first search, to ensure the graph induced by the pieces is connected. If it is not, just shuffle everything again.&lt;br /&gt;
&lt;br /&gt;
The code is hosted in &lt;a href=&quot;https://github.com/RojerGS/games&quot; target=&quot;_blank&quot;&gt;my GitHub repo&lt;/a&gt;; feel free to fork the repo and fiddle with the code! If you manage to find a more elegant way to create the game board, just make a pull request! You can also find Windows and Linux executables &lt;a href=&quot;https://drive.google.com/open?id=1sNfTE9xIWCMTVeaEDOTN7ESgGxarHv1O&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Play a bit and let me know what you think!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

No post de hoje vou partilhar um jogo que escrevi em Processing e em menos de $400$ linhas de código. Para quem não sabe, programar em Processing é essencialmente programar em Java, mas com umas funcionalidades extra que facilitam a criação de componentes gráficos.&lt;br /&gt;
&lt;br /&gt;
O objetivo do jogo é simples: ir de um quadrado em que estamos (marcado pelo contorno preto à volta da elipse branca) para um quadrado que está marcado a branco. Para o fazer, podemos mexer o nosso cursor (o quadrado preto) com as teclas AWSD para escolher um novo quadrado de destino. Depois de escolhido, podemos mudar a nossa localização carregando no espaço. No entanto, há um par de regras que determinam como nos podemos mexer:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Só nos podemos mudar para um novo quadrado que esteja na mesma linha ou coluna do que aquele onde estamos;&lt;/li&gt;
&lt;li&gt;Só nos podemos mexer se o novo quadrado tiver a mesma cor ou a mesma forma do que o quadrado em que estamos.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
A regra $1$ diz que só poderíamos ir para quadrados cobertos pelas setas cor-de-laranja:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1BkL6SlR4jhVNu7NFp3bAo_khFUCMC687Hm_iB458OejGHR7HYlXDyV0_BJ5Oei3a9npjh95qjJQXHCDNvDiSo1ART7PKzJtLB8dQIr1YJrZ4o4xVm039m1lGa9zq8D65baOzY00a86I/s1600/matchwalker_rule1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1BkL6SlR4jhVNu7NFp3bAo_khFUCMC687Hm_iB458OejGHR7HYlXDyV0_BJ5Oei3a9npjh95qjJQXHCDNvDiSo1ART7PKzJtLB8dQIr1YJrZ4o4xVm039m1lGa9zq8D65baOzY00a86I/s320/matchwalker_rule1.png&quot; width=&quot;320&quot; height=&quot;250&quot; data-original-width=&quot;554&quot; data-original-height=&quot;433&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
E a regra $2$ diz que, desses, só podemos ir para os quadrados brancos com o círculo, o losango ou a elipse vertical (precisamente porque são brancos) ou então para a elipse horizontal laranja, porque tem a mesma forma do que o quadrado em que estamos (que tem uma elipse horizontal branca).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpsfu6y8CeHkvRQJugoIZn-RR2nt31gmxQMQ2oPgF2_uIKhUyQ8_3g65BDcxSdk_G3IubstXyqxglT1BKeGFc4XqcnaHQ14mb7JboiiLRDqfKGxAhij82qAtCdS7HvQuO_CesgNaHFItI/s1600/matchwalker_rule2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpsfu6y8CeHkvRQJugoIZn-RR2nt31gmxQMQ2oPgF2_uIKhUyQ8_3g65BDcxSdk_G3IubstXyqxglT1BKeGFc4XqcnaHQ14mb7JboiiLRDqfKGxAhij82qAtCdS7HvQuO_CesgNaHFItI/s320/matchwalker_rule2.png&quot; width=&quot;320&quot; height=&quot;250&quot; data-original-width=&quot;555&quot; data-original-height=&quot;434&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Tendo estas regras em conta, um caminho possível para o puzzle da imagem em cima seria o seguinte:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiCzTUXZ1PzBY5l3DlihuV_6PZJSywXDow55NW30zy4ENL9C8IN70jWPyGg5z0awoqX1rlRKTtz8hwdTMVS2dtWZ4DidrMWjnJ1F-kSrU9O7f9MhTCdzmXPSbmlHyvktT4_1QcsCWYpJQ/s1600/matchwalker_validpath.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiCzTUXZ1PzBY5l3DlihuV_6PZJSywXDow55NW30zy4ENL9C8IN70jWPyGg5z0awoqX1rlRKTtz8hwdTMVS2dtWZ4DidrMWjnJ1F-kSrU9O7f9MhTCdzmXPSbmlHyvktT4_1QcsCWYpJQ/s320/matchwalker_validpath.png&quot; width=&quot;320&quot; height=&quot;249&quot; data-original-width=&quot;555&quot; data-original-height=&quot;432&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
O caminho é, portanto: descer para o losango &lt;b&gt;branco&lt;/b&gt; e depois subir para o &lt;b&gt;losango&lt;/b&gt; cor-de-laranja; depois, ir para a direita para o círculo &lt;b&gt;laranja&lt;/b&gt;, depois subir para a elipse vertical &lt;b&gt;laranja&lt;/b&gt; e finalmente ir para a esquerda para o destino final, o quadrado &lt;b&gt;laranja&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Se chegar a um determinado quadrado estiver a ser muito difícil, pode mudar-se o quadrado alvo carregando no $Q$ (i.e. o destino marcado a branco passa a ser outro).&lt;br /&gt;
&lt;br /&gt;
Se algum encarecido leitor quiser contribuir, acho que há uma pequena melhoria que pode ser feita ao modo como o &quot;tabuleiro&quot; é gerado. Por agora, tenho quatro quadrados $3\times 3$ explicitamente programados, e de cada vez que o jogo começa, esses quatro bocados de tabuleiro são distribuídos aleatoriamente e rodados: isto dá a ilusão de que temos um tabuleiro novo de cada vez que jogamos:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSCiAMkfN2ZuWciPzBsTHYgqP2dCc7He14zG_9EG7fE05zNlAv_GCqHEVg1Z13E_m_I5-XIikld8AuK_t2zZfDp0u99YPneZm2Y9-BXlbuBst5gwBuoE1qJPOjGXwaZvnebPIBSdte2vY/s1600/matchwalker_screenshot2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSCiAMkfN2ZuWciPzBsTHYgqP2dCc7He14zG_9EG7fE05zNlAv_GCqHEVg1Z13E_m_I5-XIikld8AuK_t2zZfDp0u99YPneZm2Y9-BXlbuBst5gwBuoE1qJPOjGXwaZvnebPIBSdte2vY/s320/matchwalker_screenshot2.png&quot; width=&quot;320&quot; height=&quot;250&quot; data-original-width=&quot;816&quot; data-original-height=&quot;638&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
O tabuleiro poderia ser criado de outra maneira: baralhamos as $36$ peças de jogo e depois usamos um algoritmo de pesquisa, tipo pesquisa em largura ou pesquisa em profundidade, para garantir que o grafo induzido pela distribuição das peças é conexo. Se não for, baralhamos tudo e repetimos.&lt;br /&gt;
&lt;br /&gt;
O código está todo no &lt;a href=&quot;https://github.com/RojerGS/games&quot; target=&quot;_blank&quot;&gt;meu repositório do GitHub&lt;/a&gt;; estejam à vontade para ir ver o código e alterá-lo! Se conseguirem arranjar uma maneira mais elegante de gerar os novos tabuleiros, criem um &quot;pull request&quot;! Também tenho executáveis Windows e Linux &lt;a href=&quot;https://drive.google.com/open?id=1sNfTE9xIWCMTVeaEDOTN7ESgGxarHv1O&quot; target=&quot;_blank&quot;&gt;aqui&lt;/a&gt;, para que todos possam jogar.&lt;br /&gt;
&lt;br /&gt;
Joguem e digam-me o que acham!

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/394685047272357656'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/394685047272357656'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/09/matchwalker-colourful-puzzle-game.html' title='MatchWalker, a puzzle game of shape and colour'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguR2L9aOFAeZaWFBiH51plcneoefOkRIo6dcN_8kqmssLSRrPCsNOAUE8jcAc_njolr1iVwnZN_eQQ-sh7lYeRvbm8OeJeU1dJ0FzSnTqz4mcrQX-4qSbFEDh_5v7IWaThS4jvKsFFih0/s72-c/matchwalker_screenshot.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-8882271708687540312</id><published>2018-09-12T23:59:00.000+01:00</published><updated>2018-09-12T23:59:18.939+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="counterintuitive"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="intuition"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="probability"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><title type='text'>Pocket maths: your verification code is 446267</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}

table, th, td, tr {
    border: 1px solid black;
    padding: 10px;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRVzTmUTBVR5o85lTi9RyEcRuxoxK1SwzgG3zCee-yh6sf2HQhxWCtwnZLCSxCLCIbsgOqd1CammUVN7fq_fJZG3Gp3AG3fgEFrO2V3vgeHnd94JkRXa7x-us9-U_qxceRnqANgVlYhQY/s1600/Untitled.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRVzTmUTBVR5o85lTi9RyEcRuxoxK1SwzgG3zCee-yh6sf2HQhxWCtwnZLCSxCLCIbsgOqd1CammUVN7fq_fJZG3Gp3AG3fgEFrO2V3vgeHnd94JkRXa7x-us9-U_qxceRnqANgVlYhQY/s1600/Untitled.png&quot; data-original-width=&quot;720&quot; data-original-height=&quot;134&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;p style=font-size:small&gt;&lt; change language&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

It has become quite common for online services to provide some form of 2-factor authentication when logging in from unknown devices. For example, whenever I try to access my Gmail account from a computer I never used, I get a text message with a one-time use 6-digit code.&lt;br /&gt;
&lt;br /&gt;
One day I was using that same service to log in into my email, when I noticed that one of the digits in the security code appeared twice, like the $1$ in $315641$. But when I read the other text messages from Google, I noticed that there were plenty more security codes with repeated digits than security codes that had six different digits. I found that weird and then decided to compute the probabilities of these events, just to check whether my intuition was tricking me or not...&lt;br /&gt;
&lt;br /&gt;
We are about to compute some probabilities regarding these $6$-digit codes - which I will start calling &lt;i&gt;PINs&lt;/i&gt; for the sake of brevity - with the rather intuitive formula
$$P(\text{some property}\ A) = \frac{\text{# PINs that satisfy property}}{\text{# of existing PINs}}$$
It is easy to see that there are a total of $10^6$ valid PINs, so for the different properties we only need to compute the total number of PINs that satisfy it.&lt;br /&gt;
&lt;br /&gt;
Below you can find a table with some properties listed and the probability that the next PIN you will receive on your cellphone satisfies that probability.&lt;br /&gt;
(if you find any mistake on the calculations, suspect one of the numbers is wrong or want to know how I computed a specific probability, leave a comment below!)&lt;br /&gt;
&lt;br /&gt;
&lt;table style=&quot;margin:auto&quot;&gt;
  &lt;tr&gt;
    &lt;th&gt;Property&lt;/th&gt;
    &lt;th&gt;Probability (up to $2$ decimal places)&lt;/th&gt;
  &lt;tr&gt;
    &lt;td&gt;$6$ unique digits (e.g. 123456)&lt;/td&gt;
    &lt;td&gt;$15.12\%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$5$ or less unique digits (e.g. 525678)&lt;/td&gt;
    &lt;td&gt;$84.88\%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$5$ unique digits, repeated digit is consecutive (e.g. 551234)&lt;/td&gt;
    &lt;td&gt;$18.14\%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$5$ unique digits, no restrictions on repeated digit (e.g. 024328)&lt;/td&gt;
    &lt;td&gt;$45.36 \%$ &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$4$ or less unique digits (e.g. 235293)&lt;/td&gt;
    &lt;td&gt;$39.52 \%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$4$ unique digits, repeated ones are together (e.g. 226997)&lt;/td&gt;
    &lt;td&gt;$3.02 \%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$3$ or less unique digits (e.g. 123231)&lt;/td&gt;
    &lt;td&gt;$6.76 \%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$2$ or less unique digits (e.g. 111331)&lt;/td&gt;
    &lt;td&gt;$0.28 \%$&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
After all, having a 6-digit code with a repeated digit is much more common than having a 6-digit code where every digit is different!!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Nos dias que correm já é comum os serviços online oferecerem alguma forma de autenticação a dois passos para proteger as nossas contas. Por exemplo, sempre que tento aceder à minha conta Google a partir de um computador que nunca usei, recebo um sms com um código único de 6 dígitos.&lt;br /&gt;
&lt;br /&gt;
Numa das vezes em que usei esse serviço, reparei que o meu código tinha um dígito repetido, tal como o $1$ em $315641$. Quando olhei para os códigos que já tinha usado em vezes anteriores, reparei que na verdade isso acontecia bastantes mais vezes do que eu estaria à espera. Isto pareceu-me estranho e portanto decidi calcular as probabilidades desses eventos, verificando assim se a minha intuição me estava a pregar partidas ou não...&lt;br /&gt;
&lt;br /&gt;
Vou mostrar uma tabela com probabilidades de várias propriedades destes códigos de $6$ dígitos - a que vou chamar &lt;i&gt;PINs&lt;/i&gt; por comodidade minha - com a fórmula intuitiva usual:
$$P(\text{some property}\ A) = \frac{\text{# PINs that satisfy property}}{\text{# of existing PINs}}$$
É fácil de ver que há um total de $10^6$ PINs válidos, portanto para cada propriedade que eu escolha só vou ter de calcular o número de PINs que a satisfazem.&lt;br /&gt;
&lt;br /&gt;
A tabela que se segue contém algumas propriedades com as respetivas probabilidades: o próximo PIN que eu receber no meu telemóvel vai satisfazer a propriedade descrita com uma probabilidade igual à indicada.&lt;br /&gt;
(se encontrarem erros, se acharem que algum dos números está mal ou se quiserem saber como calculei alguma probabilidade específica, deixem um comentário!)&lt;br /&gt;
&lt;br /&gt;
&lt;table style=&quot;margin:auto&quot;&gt;
  &lt;tr&gt;
    &lt;th&gt;Property&lt;/th&gt;
    &lt;th&gt;Probability (up to $2$ decimal places)&lt;/th&gt;
  &lt;tr&gt;
    &lt;td&gt;$6$ dígitos únicos (e.g. 123456)&lt;/td&gt;
    &lt;td&gt;$15.12\%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$5$ ou menos dígitos únicos (e.g. 525678)&lt;/td&gt;
    &lt;td&gt;$84.88\%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$5$ dígitos únicos, os repetidos estão juntos (e.g. 551234)&lt;/td&gt;
    &lt;td&gt;$18.14\%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$5$ dígitos únicos sem restrições no dígito repetido (e.g. 024328)&lt;/td&gt;
    &lt;td&gt;$45.36 \%$ &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$4$ ou menos dígitos únicos (e.g. 235293)&lt;/td&gt;
    &lt;td&gt;$39.52 \%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$4$ dígitos únicos, os repetidos estão juntos (e.g. 226997)&lt;/td&gt;
    &lt;td&gt;$3.02 \%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$3$ ou menos dígitos únicos (e.g. 123231)&lt;/td&gt;
    &lt;td&gt;$6.76 \%$&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;$2$ ou menos dígitos únicos (e.g. 111331)&lt;/td&gt;
    &lt;td&gt;$0.28 \%$&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Afinal de contas é muito mais comum aparecer um código com um dígito repetido do que um código onde todos os dígitos são diferentes!!

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/8882271708687540312'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/8882271708687540312'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/09/pocket-maths-your-verification-code-is.html' title='Pocket maths: your verification code is 446267'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRVzTmUTBVR5o85lTi9RyEcRuxoxK1SwzgG3zCee-yh6sf2HQhxWCtwnZLCSxCLCIbsgOqd1CammUVN7fq_fJZG3Gp3AG3fgEFrO2V3vgeHnd94JkRXa7x-us9-U_qxceRnqANgVlYhQY/s72-c/Untitled.png" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-2412494261359894927</id><published>2018-08-20T11:45:00.004+01:00</published><updated>2018-08-20T15:06:49.376+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="artificial intelligence"/><category scheme="http://www.blogger.com/atom/ns#" term="decision trees"/><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="genetic algorithms"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="machine learning"/><category scheme="http://www.blogger.com/atom/ns#" term="processing"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="project"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="simulation"/><title type='text'>Teaching a robot how to vacuum clean with genetic algorithms!</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;script async src=&quot;https://c6.patreon.com/becomePatronButton.bundle.js&quot;&gt;&lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;
&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz9mlyqEj6DRxZB_N1t2qJzrpT7ihZl4ENeRo58xnnkRQFk_zYCdNX-XHndd6K3Ju8NmT3MY73vqUZo_HkGbEovaGTdAEouQeTWKv1Aa6rU1WytP5n2mosheLKjfY9mxOoDl-Ynsixt3E/s1600/vacuum_short_animation.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz9mlyqEj6DRxZB_N1t2qJzrpT7ihZl4ENeRo58xnnkRQFk_zYCdNX-XHndd6K3Ju8NmT3MY73vqUZo_HkGbEovaGTdAEouQeTWKv1Aa6rU1WytP5n2mosheLKjfY9mxOoDl-Ynsixt3E/s1600/vacuum_short_animation.gif&quot; data-original-width=&quot;400&quot; data-original-height=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;br /&gt;
&lt;div style=&quot;font-size: small;&quot;&gt;
&amp;lt; change language&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;
In this post I want to showcase the beginning of what I think will be a really cool project. After reading a really nice book (that Bill Gates himself recommends) on machine learning, I decided to experiment with genetic algorithms.&lt;br /&gt;
&lt;br /&gt;
For that matter, the main goal here will be to develop a genetic algorithm that teaches a vacuum cleaner how it should move in a dirty room to clean it in the best way possible (that is what is happening in the animation above). The first step is to define what I mean by &lt;i&gt;room&lt;/i&gt;: a &lt;i&gt;room&lt;/i&gt; will be a rectangular grid where each cell has a number from $0$ to $1$. A cell with a $0$ is perfectly clean and a cell with a number $1$ is as dirty as a piece of floor can get. Below we see a $5\times 5$ room with a robot (in red) already in the middle of the room:&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq23XlHGN7ErE2R5XCy1e_RcJeBtgcT-7JByFrtHoG4Y09exeVyksE36UOnf6yeHSQ2cSo0e7S64lgaoCLw6D6FEFC3v6u5_02qglyUlV_GASoDaAaU_1IS8RgHazZnVijDGyYb9XbZ5I/s1600/vacuum_robot_in_room.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq23XlHGN7ErE2R5XCy1e_RcJeBtgcT-7JByFrtHoG4Y09exeVyksE36UOnf6yeHSQ2cSo0e7S64lgaoCLw6D6FEFC3v6u5_02qglyUlV_GASoDaAaU_1IS8RgHazZnVijDGyYb9XbZ5I/s1600/vacuum_robot_in_room.png&quot; data-original-width=&quot;103&quot; data-original-height=&quot;103&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

As I read in &lt;i&gt;The Master Algorithm&lt;/i&gt; (and frankly I found it very enlightening), when one is going to use genetic algorithms we must previously define the structure of the solution and then the genetic algorithm will fill in the parameters for us.&lt;br /&gt;
&lt;br /&gt;
Having said so, the genetic algorithm will try to learn a &lt;i&gt;decision tree&lt;/i&gt;, which will be a binary tree where each node can be of one of two types:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Action&lt;/b&gt; node: an action node is always a leaf in our decision tree. If we reach an action node, the robot will move according to the &lt;i&gt;action&lt;/i&gt; value of that node;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Sensing&lt;/b&gt; node: a sensing node is never a leaf in our decision tree. It has a relative position, to which the robot will look, and a threshold. If the level of dirt in the node we looked at is below the threshold, we will follow the left subtree of this node; otherwise we will follow the right subtree of this node.&lt;/li&gt;
&lt;/ul&gt;

As an example, consider the tree with only $3$ nodes, such that the root is a sensing node $(RIGHT+UP, 1/3)$ with left subtree an action node $(LEFT)$ and right subtree another action node $(UP)$. Say the robot is the red square on the image above. To decide where he will move next he traverses its decision tree: the root is a sensing node and so it will look to where the node says (RIGHT and UP) and will notice that there is a very dirty square. The level of dirt of that square is certainly bigger than $1/3$ which is the node threshold, so we proceed to the right subtree. The right subtree is just an action node and so we perform its action, deciding to go UP.&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAWecBAqP2fZVBihsHlS9tGRAYwW0BeGHtd5Tk1EO5HAl_67rLoV3RkueTHv8ksEoCToySdgTGf_WZYD6nlKPAYC2UmFDxXukXueMcEToS1smJ7OKtHWJheoDJuxVDMr3RKOD7uOeAH9k/s1600/vacuum_robot_deciding.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAWecBAqP2fZVBihsHlS9tGRAYwW0BeGHtd5Tk1EO5HAl_67rLoV3RkueTHv8ksEoCToySdgTGf_WZYD6nlKPAYC2UmFDxXukXueMcEToS1smJ7OKtHWJheoDJuxVDMr3RKOD7uOeAH9k/s1600/vacuum_robot_deciding.png&quot; data-original-width=&quot;161&quot; data-original-height=&quot;161&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

All robots in a population will start with random decision trees and then the genetic algorithm will keep mutating the trees! To create a random decision tree I used a recursive approach. We start by deciding if the root node is going to be an action node or a sensing node. Either way, the parameters of the node are filled in randomly. After that, if we created a sensing node we create two random decision trees and set them as the left and right subtrees of this node, but with a twist! The deeper we go, the less likely we are to create another sensing node and the more likely we are to create an action node. This is so that, in general, starting random trees are small.&lt;br /&gt;
&lt;br /&gt;
With this set in place, mutating a decision tree is also simple (please bear in mind that the mutation events that I am going to describe happen with probabilities that were chosen rather arbitrarily). Again, we do this recursively by traversing the tree and deciding to mutate, or not, each node:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;If the node is a sensing node and we are going to mutate it, we can either:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Amputate its subtrees and turn this node into an action node;&lt;/li&gt;
&lt;li&gt;Swap the left and right subtrees;&lt;/li&gt;
&lt;li&gt;Pick another value as threshold;&lt;/li&gt;
&lt;li&gt;Change the square to which we look when we reach this node.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;If the node is an action node and we are going to mutate it, we can either:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Expand this node into a sensing node and set random decision trees as the child;&lt;/li&gt;
&lt;li&gt;Change the square to which we will move when we reach this node.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

Having defined these behaviours, carrying out the simulation is easy: we create a starting population with $N$ individuals and a set of $K$ random rooms per generation. We make each robot clean each room and store their score, which will just be the sum of the cells they cleaned. We then pick the top performing $45\%$ robots. Those will proceed to the next generation and each one of them is also going to be copied and then mutated. The remaining $10\%$ of the next generation is created randomly from scratch.&lt;br /&gt;
Notice that this differs a bit from what I used to find on the internet in the sense that the first $45\%$ aren&#39;t mutated nor bred together, while the second $45\%$ are &lt;b&gt;forced&lt;/b&gt; to be mutated. I took this approach because it was a bit easier than implementing a crossover algorithm for the decision trees, but I might do it as well in the future.&lt;br /&gt;
&lt;br /&gt;
Either way this algorithm performs really nicely! In the end of the post you will find an animation of the best performing robot after a simulation with $100$ generations.&lt;br /&gt;
&lt;br /&gt;
All the code I wrote (and am still writing) for this is available in my &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/VacuumCleaner&quot; target=&quot;_blank&quot;&gt;GitHub repo&lt;/a&gt;. There you can also find a &lt;a href=&quot;https://github.com/RojerGS/AIML/blob/master/VacuumCleaner/WBasicSimulator.jar&quot; target=&quot;_blank&quot;&gt;small Java application&lt;/a&gt; for you to train your own generations of robots! You can choose the number of robots, the number of rooms each robot trains in and the number of generations. In the end it displays the animation of the best robot in a random room! Here is a screenshot of the app:&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPMGyxFc-PaRWtf5y6Yf4CJm7nRTjmA5a7GM_3BOtkh95U8VihGyPuBLMIHEAbPLpt_aZh7PogdITCCQSM8mIZV78sjACxm4MqerHIZIFnDxWc9LA2sk15pqD98251bvII2zUqc2Ryi6k/s1600/vacuum_app_screenshot.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPMGyxFc-PaRWtf5y6Yf4CJm7nRTjmA5a7GM_3BOtkh95U8VihGyPuBLMIHEAbPLpt_aZh7PogdITCCQSM8mIZV78sjACxm4MqerHIZIFnDxWc9LA2sk15pqD98251bvII2zUqc2Ryi6k/s1600/vacuum_app_screenshot.png&quot; data-original-width=&quot;870&quot; data-original-height=&quot;439&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;br /&gt;
I am thinking of writing a series of blog posts as a &quot;tutorial&quot; on how to code all this. Would it be interesting? Let me know!!&lt;br /&gt;
&lt;br /&gt;
Also, consider &lt;a href=&quot;patreon.com/mathspp&quot; target=&quot;_blank&quot;&gt;supporting me on Patreon&lt;/a&gt; if you like my content and would like extra benefits!

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post quero mostrar uma fase inicial daquilo que está a sre um projeto super interessante. Depois de ter lido um livro bestial sobre aprendizagem automática [ou machine learning], que o próprio Bill Gates recomenda, fiquei com imensa vontade de experimentar usar algoritmos genéticos para alguma coisa.&lt;br /&gt;
&lt;br /&gt;
Foi assim que estabeleci o seguinte objetivo: desenvolver um algoritmo genético que ensina um robot a aspirar o chão de uma sala (é isso que está a acontecer na animação do início do post). O primeiro passo é definir o que é uma &lt;i&gt;sala&lt;/i&gt;: uma &lt;i&gt;sala&lt;/i&gt; é uma grelha retangular onde cada célula tem um número entre $0$ e $1$. Uma célula com o número $0$ está perfeitamente limpa e uma célula com o número $1$ está tão suja quanto é possível e imaginável. De seguida vemos uma imagem de uma sala $5\times 5$ com um robot (a vermelho) no centro: &lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq23XlHGN7ErE2R5XCy1e_RcJeBtgcT-7JByFrtHoG4Y09exeVyksE36UOnf6yeHSQ2cSo0e7S64lgaoCLw6D6FEFC3v6u5_02qglyUlV_GASoDaAaU_1IS8RgHazZnVijDGyYb9XbZ5I/s1600/vacuum_robot_in_room.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq23XlHGN7ErE2R5XCy1e_RcJeBtgcT-7JByFrtHoG4Y09exeVyksE36UOnf6yeHSQ2cSo0e7S64lgaoCLw6D6FEFC3v6u5_02qglyUlV_GASoDaAaU_1IS8RgHazZnVijDGyYb9XbZ5I/s1600/vacuum_robot_in_room.png&quot; data-original-width=&quot;103&quot; data-original-height=&quot;103&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

Quando li &lt;i&gt;A Revolução do Algoritmo Mestre&lt;/i&gt; (que achei francamente esclarecedor), percebi que quando usamos algoritmos genéticos temos de definir, à priori, a estrutura da solução de que estamos à procura; os algoritmos genéticos só preenchem os parâmetros.&lt;br /&gt;
&lt;br /&gt;
Tendo percebido isso, decidi que o algoritmo genético ia tentar aprender uma &lt;i&gt;árvore de decisão&lt;/i&gt;, que para este projeto seria uma árvore binária onde cada nó é de um de dois tipos:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Nó de ação&lt;/b&gt;: um nó de ação é sempre uma folha na nossa árvore de decisão. Se chegarmos a um nó de ação, o robot limita-se a deslocar-se para a posição indicada nesse nó.;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Nó com sensor&lt;/b&gt;: um nó com sensor nunca é uma folha. Tem indicada uma posição - para onde o robot vai olhar - e um valor numérico que serve de bitola. Se o nível de sujidade da célula para onde olhámos estiver abaixo da bitola, seguimos pela a sub-árvore esquerda, caso contrário seguimos pela sub-árvore direita.&lt;/li&gt;
&lt;/ul&gt;

Tome-se como exemplo uma árvore com $3$ nós apenas, onde a raíz é o nó com sensor $(DIREITA+CIMA, 1/3)$, onde a sub-árvore esquerda é o nó de ação $(ESQUERDA)$ e onde a sub-árvore direita é o nó com ação $(CIMA)$. Suponhamos que o robot é o quadrado vermelho da imagem em cima. Para decidir para onde vai temos de atravessar a árvore de decisão: a raíz é um nó com sensor, portanto olhamos para o quadrado em CIMA e à DIREITA (célula com rebordo encarnado) e notamos que é uma célula bastante escura (muito suja). O nível de sujidade dessa célula é certamente maior que $1/3$, que era a bitola da raíz da árvore. Por causa disso, seguimos para a sub-árvore direita onde encontramos um nó com ação que nos manda seguir para CIMA.&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAWecBAqP2fZVBihsHlS9tGRAYwW0BeGHtd5Tk1EO5HAl_67rLoV3RkueTHv8ksEoCToySdgTGf_WZYD6nlKPAYC2UmFDxXukXueMcEToS1smJ7OKtHWJheoDJuxVDMr3RKOD7uOeAH9k/s1600/vacuum_robot_deciding.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAWecBAqP2fZVBihsHlS9tGRAYwW0BeGHtd5Tk1EO5HAl_67rLoV3RkueTHv8ksEoCToySdgTGf_WZYD6nlKPAYC2UmFDxXukXueMcEToS1smJ7OKtHWJheoDJuxVDMr3RKOD7uOeAH9k/s1600/vacuum_robot_deciding.png&quot; data-original-width=&quot;161&quot; data-original-height=&quot;161&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

Todos os robots numa população começam com árvores de decisão aleatórias e depois o algoritmo genético vai ter a árdua tarefa de induzir mutações! Para criar árvores de decisão aleatórias usei um método recursivo. Começamos por decidir o tipo de nó da raíz e depois escolhemos os seus parâmetros aleatoriamente. Se o nó for do tipo com sensor, criamos outras duas árvores de decisão aleatórias e usamo-las como sub-árvores esquerda e direita do nó que acabámos de criar. Há apenas um pequeno detalhe: quanto mais &quot;fundo&quot; estivermos na árvore, mais provável é que um nó seja um nó de ação e menos provável é que seja um nó com sensor. Fazemos isto para que, em geral, as árvores aleatórias não sejam grandes.&lt;br /&gt;
&lt;br /&gt;
Com tudo isto já definido é relativamente fácil de induzir as mutações nas árvores (note-se que as mutações que vou descrever acontecem com probabilidades que eu escolhi de forma relativamente arbitrária). Usamos de novo uma metodologia recursiva: atravessamos a árvore, tentando induzir mutações em cada nó:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Se o nó for um nó com sensor, podemos:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Amputar as suas sub-árvores e transformá-lo num nó com ação;&lt;/li&gt;
&lt;li&gt;Trocar as sub-árvores esquerda e direita;&lt;/li&gt;
&lt;li&gt;Escolher uma nova bitola;&lt;/li&gt;
&lt;li&gt;Mudar a célula para onde temos de olhar.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Se o nó for um nó com ação, podemos:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Transformar o nó num nó com sensor e atribuir árvores aleatórias como sub-árvores;&lt;/li&gt;
&lt;li&gt;Mudar a célula para onde nos deslocamos quando chegamos a este nó.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

Com estes comportamentos definidos só falta a estrutura da simulação: criamos uma população inicial com $N$ indivíduos e para cada geração criamos $K$ salas aleatórias. Pomos cada robot a limpar cada sala e damos uma pontuação que vai ser o somatório dos valores das células que foram limpas. Da população toda, escolhemos o top $45\%$. Esses seguem para a próxima geração; são também copiados - para perfazerem outros $45\%$ da próxima geração - e nas cópias induzimos mutações. Os $10\%$ que faltam são compostos por robots novos aleatórios.&lt;br /&gt;
Repare-se que isto é um pouco diferente daquilo a que eu estava habituado a ver na internet: os primeiros $45\%$ não são mutados nem se reproduzem entre si, ao passo que os segundos $45\%$ são &lt;b&gt;necessariamente&lt;/b&gt; alterados. Segui esta via porque achei um pouco mais simples do que implementar um algoritmo para reproduzir árvores de decisão... talvez o faça no futuro.&lt;br /&gt;
&lt;br /&gt;
De qualquer das maneiras o algoritmo funciona bastante bem! No fim do post encontram uma animação do melhor robot de uma das simulações que fiz.&lt;br /&gt;
&lt;br /&gt;
Todo o código que escrevi (e ainda estou a escrever) para isto pode ser encontrado &lt;a href=&quot;https://github.com/RojerGS/AIML/tree/master/VacuumCleaner&quot; target=&quot;_blank&quot;&gt;neste repo do GitHub&lt;/a&gt;. Também encontram lá um &lt;a href=&quot;https://github.com/RojerGS/AIML/blob/master/VacuumCleaner/WBasicSimulator.jar&quot; target=&quot;_blank&quot;&gt;pequeno executável em Java&lt;/a&gt; para poderem fazer as vossas próprias simulações! Pode escolher-se o número de robots na população, o número de salas em que cada geração treina e o número de gerações da simulação! No fim o programa mostra uma animação do melhor robot numa sala criada aleatoriamente. De seguida encontram uma captura de ecrã do programa:&lt;br /&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPMGyxFc-PaRWtf5y6Yf4CJm7nRTjmA5a7GM_3BOtkh95U8VihGyPuBLMIHEAbPLpt_aZh7PogdITCCQSM8mIZV78sjACxm4MqerHIZIFnDxWc9LA2sk15pqD98251bvII2zUqc2Ryi6k/s1600/vacuum_app_screenshot.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPMGyxFc-PaRWtf5y6Yf4CJm7nRTjmA5a7GM_3BOtkh95U8VihGyPuBLMIHEAbPLpt_aZh7PogdITCCQSM8mIZV78sjACxm4MqerHIZIFnDxWc9LA2sk15pqD98251bvII2zUqc2Ryi6k/s1600/vacuum_app_screenshot.png&quot; data-original-width=&quot;870&quot; data-original-height=&quot;439&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;br /&gt;
Estou a pensar escrever uma série de posts em formato de &quot;tutorial&quot; sobre como programar isto. Parece-vos interessante? Dêem-me o vosso feedback!!&lt;br /&gt;
&lt;br /&gt;
Já agora, considerem &lt;a href=&quot;patreon.com/mathspp&quot; target=&quot;_blank&quot;&gt;apoiar-me através do Patreon&lt;/a&gt; se gostam do meu conteúdo e se querem benefícios extra!

&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicqFb-fj-ZUlbtLe83mbiX7uOeNAU6fyaGv7_SmK_2WTj3xGB29TxU6-vLU26VpC8ZETQW_xlPK-WlPKNXnRbw7owR-XyKJ1NJJ9vg-xRXHgyGl8MCfj0U_vHgcq_xIyQPRHQancxohEA/s1600/vacuum_small_long_animation.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicqFb-fj-ZUlbtLe83mbiX7uOeNAU6fyaGv7_SmK_2WTj3xGB29TxU6-vLU26VpC8ZETQW_xlPK-WlPKNXnRbw7owR-XyKJ1NJJ9vg-xRXHgyGl8MCfj0U_vHgcq_xIyQPRHQancxohEA/s1600/vacuum_small_long_animation.gif&quot; data-original-width=&quot;200&quot; data-original-height=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
  - RGS&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://www.patreon.com/bePatron?u=13009744&quot; data-patreon-widget-type=&quot;become-patron-button&quot;&gt;Become a Patron!&lt;/a&gt;
&lt;div style=&quot;background-color: #333333; padding: 10px; text-align: center;&quot;&gt;
&lt;button class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot; type=&quot;button&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/2412494261359894927'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/2412494261359894927'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/08/teaching-robot-how-to-vacuum-clean-with.html' title='Teaching a robot how to vacuum clean with genetic algorithms!'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz9mlyqEj6DRxZB_N1t2qJzrpT7ihZl4ENeRo58xnnkRQFk_zYCdNX-XHndd6K3Ju8NmT3MY73vqUZo_HkGbEovaGTdAEouQeTWKv1Aa6rU1WytP5n2mosheLKjfY9mxOoDl-Ynsixt3E/s72-c/vacuum_short_animation.gif" height="72" width="72"/></entry><entry><id>tag:blogger.com,1999:blog-5337060275163361458.post-1336813728340515795</id><published>2018-08-18T12:32:00.000+01:00</published><updated>2018-08-18T12:32:47.143+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="en"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematics"/><category scheme="http://www.blogger.com/atom/ns#" term="pigeonhole principle"/><category scheme="http://www.blogger.com/atom/ns#" term="proof"/><category scheme="http://www.blogger.com/atom/ns#" term="pt"/><category scheme="http://www.blogger.com/atom/ns#" term="twitter proof"/><title type='text'>Twitter proof: not too hairy</title><content type='html'>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [[&#39;$&#39;,&#39;$&#39;], [&#39;\\(&#39;,&#39;\\)&#39;]]}}); &lt;/script&gt; &lt;script src=&quot;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML,Safe&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;
&lt;style&gt;
body {font-family: Arial;}

/* Style the tab */
.tab {
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
    background-color: inherit;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 14px 16px;
    transition: 0.3s;
    font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
    background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
    background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
    display: none;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-top: none;
}
&lt;/style&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqpr0pu8itiEGG-0jVLUre8YbD9ko_o3wC8esXofLQ0l1evCOS16Gig8HI1fradNnRtybRJd-2RjFHz-rlqyyC-ORAxN_I4qjZ_UzeEtKlD67tnnD6g5hGOSCXmNRQZ1H1NOioBEnOqQE/s1600/pigeons_london.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqpr0pu8itiEGG-0jVLUre8YbD9ko_o3wC8esXofLQ0l1evCOS16Gig8HI1fradNnRtybRJd-2RjFHz-rlqyyC-ORAxN_I4qjZ_UzeEtKlD67tnnD6g5hGOSCXmNRQZ1H1NOioBEnOqQE/s1600/pigeons_london.jpg&quot; data-original-width=&quot;640&quot; data-original-height=&quot;238&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;br /&gt;
&lt;div class=&quot;tab&quot;&gt;
&lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;portugues&#39;)&quot;&gt;Pt&lt;/button&gt;
  &lt;button class=&quot;tablinks&quot; onclick=&quot;openTab(event, &#39;english&#39;)&quot;&gt;En&lt;/button&gt;
&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;english&quot;&gt;

In this post I will show that some londoners share more than their native language and their propension to get sunburnt. For that we need to notice that there are more than $8.5$ million londoners and that the average human has $100,000$ hairs in the head.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Assertion&lt;/b&gt;: there are, at least, $9$ londoners with the exact same number of hairs in their head. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Twitter proof&lt;/b&gt;: given the facts above, there are more than $8$ million londoners with less than $1$ million hairs in their head. By the pigeonhole principle this means at least $9$ londoners have the exact same number of hairs.

&lt;/div&gt;
&lt;div class=&quot;tabcontent&quot; id=&quot;portugues&quot;&gt;

Neste post vamos mostrar que alguns londrinos partilham mais do que o inglês como língua materna e a propensão para apanhar escaldões. Para isso é preciso notar que há mais de $8.5$ milhões de londrinos e que o ser humano médio tem $100,000$ cabelos na sua cabeça.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Asserção&lt;/b&gt;: há pelo menos $9$ londrinos com &lt;i&gt;exatamente&lt;/i&gt; o mesmo número de cabelos na cabeça. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Prova num tweet&lt;/b&gt;: pelos factos acima, extistem mais de $8$ milhões de londrinos com menos de $1$ milhão de cabelos na cabeça. Assim, pelo princípio do pombal há pelo menos $9$ londrinos com o mesmo número de cabelos.

&lt;/div&gt;&lt;br /&gt;
&amp;nbsp&amp;nbsp- RGS&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align:center;background-color:#333333;padding:10px&quot;&gt;
    &lt;button type=&quot;button&quot; class=&quot;subscribe-button pill-button&quot; onclick=&quot;location.href=&#39;https://eepurl.com/drHcrr&#39;&quot;&gt;join the mathspp mailing list
&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
function openTab(evt, language) {
    var i, tabcontent, tablinks;
    tabcontent = document.getElementsByClassName(&quot;tabcontent&quot;);
    for (i = 0; i &lt; tabcontent.length; i++) {
        tabcontent[i].style.display = &quot;none&quot;;
    }
    tablinks = document.getElementsByClassName(&quot;tablinks&quot;);
    for (i = 0; i &lt; tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(&quot; active&quot;, &quot;&quot;);
    }
    document.getElementById(language).style.display = &quot;block&quot;;
    evt.currentTarget.className += &quot; active&quot;;
}
openTab(0, &quot;english&quot;);
&lt;/script&gt;
&lt;!-- using highlight.js to highlight code
&lt;link rel=&quot;stylesheet&quot;
      href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt; --&gt;</content><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/1336813728340515795'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5337060275163361458/posts/default/1336813728340515795'/><link rel='alternate' type='text/html' href='https://mathspp.blogspot.com/2018/08/twitter-proof-not-too-hairy.html' title='Twitter proof: not too hairy'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqpr0pu8itiEGG-0jVLUre8YbD9ko_o3wC8esXofLQ0l1evCOS16Gig8HI1fradNnRtybRJd-2RjFHz-rlqyyC-ORAxN_I4qjZ_UzeEtKlD67tnnD6g5hGOSCXmNRQZ1H1NOioBEnOqQE/s72-c/pigeons_london.jpg" height="72" width="72"/></entry></feed>