<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Michael Muratov</title><link>https://michaelmuratov.ca/tags/python/</link><description>Recent content on Michael Muratov</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sat, 11 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://michaelmuratov.ca/tags/python/index.xml" rel="self" type="application/rss+xml"/><item><title>LLM Tool Calling</title><link>https://michaelmuratov.ca/blog/artifacts/guides/calculator-tool-call/</link><pubDate>Sat, 11 Jul 2026 00:00:00 +0000</pubDate><guid>https://michaelmuratov.ca/blog/artifacts/guides/calculator-tool-call/</guid><description>&lt;h3 id="simple-math-is-actually-hard"&gt;Simple Math is actually Hard?&lt;/h3&gt;
&lt;p&gt;A very simple problem with large language models, which frequently gets highlighted, is their poor ability to accurately do simple grade school math. Something that would be easy for human beings, even just in their head, can be surprisingly difficult for these models to do reliably.&lt;/p&gt;
&lt;p&gt;There are many benchmarks for model performance on simple math problems, and their results are often disappointing. This isn&amp;rsquo;t that surprising, given that their training is based on next token prediction, which isn&amp;rsquo;t as well suited to number crunching as a calculator. Computers though, should be very good at number crunching. &lt;strong&gt;If we could just hook up LLMs to a calculator, we could fix this problem.&lt;/strong&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<h3 id="simple-math-is-actually-hard">Simple Math is actually Hard?</h3>
<p>A very simple problem with large language models, which frequently gets highlighted, is their poor ability to accurately do simple grade school math. Something that would be easy for human beings, even just in their head, can be surprisingly difficult for these models to do reliably.</p>
<p>There are many benchmarks for model performance on simple math problems, and their results are often disappointing. This isn&rsquo;t that surprising, given that their training is based on next token prediction, which isn&rsquo;t as well suited to number crunching as a calculator. Computers though, should be very good at number crunching. <strong>If we could just hook up LLMs to a calculator, we could fix this problem.</strong></p>
<h3 id="llm-tool-calls">LLM Tool Calls</h3>
<p>If we can get the LLM to output something that <em>looks</em> like a function call, we can provide some parsing logic, actually execute the request deterministically, and provide the final answer back to the model. This way the model is only concerned with providing the right inputs, for which it can leverage its next token prediction, and then we can be certain that with the right inputs we will also be getting the right outputs.</p>
<h3 id="calculator-example">Calculator Example</h3>
<p>Let&rsquo;s write the simplest possible LLM tool call for a calculator. We can use Python for this.
A similar example is also provided by OpenAI&rsquo;s <a href="https://developers.openai.com/api/docs/guides/function-calling#function-tool-example">function calling</a> page.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">  1</span><span class="cl"><span class="kn">from</span> <span class="nn">openai</span> <span class="kn">import</span> <span class="n">OpenAI</span>
</span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="kn">import</span> <span class="nn">json</span>
</span></span><span class="line"><span class="ln">  3</span><span class="cl">
</span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="n">client</span> <span class="o">=</span> <span class="n">OpenAI</span><span class="p">(</span><span class="n">api_key</span><span class="o">=</span><span class="s2">&#34;your_api_key_here&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">  5</span><span class="cl">
</span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="c1"># 1. Define a list of callable tools for the model</span>
</span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="n">tools</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">  8</span><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="ln">  9</span><span class="cl">        <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;function&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 10</span><span class="cl">        <span class="s2">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;calculate&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl">        <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Execute a simple arithmetic operation on two integers.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 12</span><span class="cl">        <span class="s2">&#34;parameters&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 13</span><span class="cl">            <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;object&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 14</span><span class="cl">            <span class="s2">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 15</span><span class="cl">                <span class="s2">&#34;first&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 16</span><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;integer&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 17</span><span class="cl">                    <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;First number&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 19</span><span class="cl">                <span class="s2">&#34;second&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 20</span><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;integer&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">                    <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Second number&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">                <span class="s2">&#34;sign&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 24</span><span class="cl">                    <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;string&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">                    <span class="s2">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;Symbol to execute the operation&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 26</span><span class="cl">                <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 27</span><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">            <span class="s2">&#34;required&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;first&#34;</span><span class="p">,</span> <span class="s2">&#34;second&#34;</span><span class="p">,</span> <span class="s2">&#34;sign&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln"> 29</span><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 31</span><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 32</span><span class="cl">
</span></span><span class="line"><span class="ln"> 33</span><span class="cl"><span class="c1">#2. Define the function logic that will execute when the model calls the tool</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl"><span class="k">def</span> <span class="nf">calculate</span><span class="p">(</span><span class="n">first</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">second</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">sign</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">    <span class="k">if</span> <span class="n">sign</span> <span class="o">==</span> <span class="s1">&#39;+&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 36</span><span class="cl">        <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">first</span> <span class="o">+</span> <span class="n">second</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 37</span><span class="cl">    <span class="k">elif</span> <span class="n">sign</span> <span class="o">==</span> <span class="s1">&#39;-&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 38</span><span class="cl">        <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">first</span> <span class="o">-</span> <span class="n">second</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 39</span><span class="cl">    <span class="k">elif</span> <span class="n">sign</span> <span class="o">==</span> <span class="s1">&#39;*&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 40</span><span class="cl">        <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">first</span> <span class="o">*</span> <span class="n">second</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">    <span class="k">elif</span> <span class="n">sign</span> <span class="o">==</span> <span class="s1">&#39;/&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">        <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">first</span> <span class="o">/</span> <span class="n">second</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 43</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Unknown sign: </span><span class="si">{</span><span class="n">sign</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">
</span></span><span class="line"><span class="ln"> 46</span><span class="cl"><span class="c1"># Create a running input list we will add to over time</span>
</span></span><span class="line"><span class="ln"> 47</span><span class="cl"><span class="n">input_list</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">    <span class="p">{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;What is 221 * 645?&#34;</span><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 49</span><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">
</span></span><span class="line"><span class="ln"> 51</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;User Question:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;What is 221 * 645?&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">
</span></span><span class="line"><span class="ln"> 55</span><span class="cl"><span class="c1"># 3. Prompt the model with tools defined</span>
</span></span><span class="line"><span class="ln"> 56</span><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">responses</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;gpt-4.1-mini&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">    <span class="n">tools</span><span class="o">=</span><span class="n">tools</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">    <span class="nb">input</span><span class="o">=</span><span class="n">input_list</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">
</span></span><span class="line"><span class="ln"> 62</span><span class="cl"><span class="c1"># Save function call outputs for subsequent requests</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl"><span class="n">input_list</span> <span class="o">+=</span> <span class="n">response</span><span class="o">.</span><span class="n">output</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">
</span></span><span class="line"><span class="ln"> 65</span><span class="cl"><span class="c1"># 4. If the function call is present in the model&#39;s response, attempt to execute it</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl"><span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">output</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">    <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;function_call&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Model Output:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;========LLM Invoked Function Call============&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 71</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Function Call: </span><span class="si">{</span><span class="n">item</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Arguments: </span><span class="si">{</span><span class="n">item</span><span class="o">.</span><span class="n">arguments</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">        <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">&#34;calculate&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">            <span class="c1"># 5. Execute the function logic for calculate</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">            <span class="n">first</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">arguments</span><span class="p">)[</span><span class="s2">&#34;first&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">            <span class="n">second</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">arguments</span><span class="p">)[</span><span class="s2">&#34;second&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">            <span class="n">sign</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">arguments</span><span class="p">)[</span><span class="s2">&#34;sign&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 78</span><span class="cl">            <span class="n">result</span> <span class="o">=</span> <span class="n">calculate</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="n">second</span><span class="p">,</span> <span class="n">sign</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">            
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">            <span class="c1"># 6. Provide function call results to the model</span>
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">            <span class="n">input_list</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">                <span class="s2">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;function_call_output&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">                <span class="s2">&#34;call_id&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">call_id</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">                <span class="s2">&#34;output&#34;</span><span class="p">:</span> <span class="n">result</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">            <span class="p">})</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Function Call Output: </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=============================================&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">
</span></span><span class="line"><span class="ln"> 91</span><span class="cl"><span class="c1"># 5. Prompt the model again with function call outputs for final answer</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">responses</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">    <span class="n">model</span><span class="o">=</span><span class="s2">&#34;gpt-4.1-mini&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">    <span class="n">instructions</span><span class="o">=</span><span class="s2">&#34;Respond only with the full answer in plain text format.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 95</span><span class="cl">    <span class="n">tools</span><span class="o">=</span><span class="n">tools</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">    <span class="nb">input</span><span class="o">=</span><span class="n">input_list</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 97</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">
</span></span><span class="line"><span class="ln"> 99</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;========LLM Recieved Call Answer============&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Final output:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">output_text</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;============================================&#34;</span><span class="p">)</span></span></span></code></pre></div>

  <div class="admonition important">
    <div class="admonition-header">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/></svg>
      <span>Important</span>
    </div>
      <div class="admonition-content">
        <p>Step 1 in the above code defined what calling the calculate function would require:</p>
<ol>
<li><strong>Type:</strong> function_call</li>
<li><strong>Name:</strong> calculate</li>
<li><strong>Parameters:</strong> first, second, sign</li>
</ol>
      </div>
  </div>
<p>When the model registers that calculate would be useful it sends a response to us that looks like this:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="ln">1</span><span class="cl"><span class="o">[</span>ResponseFunctionToolCall<span class="o">(</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">  <span class="nv">type</span><span class="o">=</span><span class="s1">&#39;function_call&#39;</span>, 
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="nv">name</span><span class="o">=</span><span class="s1">&#39;calculate&#39;</span>,
</span></span><span class="line"><span class="ln">4</span><span class="cl">  <span class="nv">arguments</span><span class="o">=</span><span class="s1">&#39;{&#34;first&#34;:221,&#34;second&#34;:645,&#34;sign&#34;:&#34;*&#34;}&#39;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="o">)]</span></span></span></code></pre></div>
<p>At <strong>step 4</strong> in our code we check for any responses with type <strong>function_call</strong>. If we find one we parse out the function name. We use the provided paramters to run the appropriate function as a <code>&quot;tool call&quot;</code>. Then we simply provide the result of the function to our chat history for the model to observe.</p>
<p>The last part is simply asking the model to format the function&rsquo;s output as a complete sentence which it can easily do.</p>
<p>Here is the full print output of the code block:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="err">User</span> <span class="err">Question:</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="err">What</span> <span class="err">is</span> <span class="mi">221</span> <span class="err">*</span> <span class="mi">645</span><span class="err">?</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="err">Model</span> <span class="err">Output:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="err">ResponseFunctionToolCall(arguments=&#39;</span><span class="p">{</span><span class="nt">&#34;first&#34;</span><span class="p">:</span><span class="mi">221</span><span class="p">,</span><span class="nt">&#34;second&#34;</span><span class="p">:</span><span class="mi">645</span><span class="p">,</span><span class="nt">&#34;sign&#34;</span><span class="p">:</span><span class="s2">&#34;*&#34;</span><span class="p">}</span><span class="err">&#39;,</span> <span class="err">call_id=&#39;call_IA</span><span class="mi">3</span><span class="err">XFzdm</span><span class="mi">5</span><span class="err">YcamN</span><span class="mi">26</span><span class="err">Nd</span><span class="mi">7</span><span class="err">WeISX&#39;,</span> <span class="err">name=&#39;calculate&#39;,</span> <span class="err">type=&#39;function_call&#39;,</span> <span class="err">id=&#39;fc_</span><span class="mi">088</span><span class="err">a</span><span class="mi">460995856027006</span><span class="err">a</span><span class="mi">51</span><span class="err">ee</span><span class="mi">403</span><span class="err">ea</span><span class="mi">081929</span><span class="err">c</span><span class="mi">055</span><span class="err">bb</span><span class="mi">039</span><span class="err">b</span><span class="mi">6</span><span class="err">a</span><span class="mi">32</span><span class="err">c&#39;,</span> <span class="err">caller=None,</span> <span class="err">namespace=None,</span> <span class="err">status=&#39;completed&#39;)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="err">========LLM</span> <span class="err">Invoked</span> <span class="err">Function</span> <span class="err">Call============</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="err">Function</span> <span class="err">Call:</span> <span class="err">calculate</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="err">Arguments:</span> <span class="p">{</span><span class="nt">&#34;first&#34;</span><span class="p">:</span><span class="mi">221</span><span class="p">,</span><span class="nt">&#34;second&#34;</span><span class="p">:</span><span class="mi">645</span><span class="p">,</span><span class="nt">&#34;sign&#34;</span><span class="p">:</span><span class="s2">&#34;*&#34;</span><span class="p">}</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="err">Function</span> <span class="err">Call</span> <span class="err">Output:</span> <span class="mi">142545</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="err">=============================================</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="err">========LLM</span> <span class="err">Recieved</span> <span class="err">Call</span> <span class="err">Answer============</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="err">Final</span> <span class="err">output:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="mi">221</span> <span class="err">multiplied</span> <span class="err">by</span> <span class="mi">645</span> <span class="err">is</span> <span class="mi">142</span><span class="err">,</span><span class="mi">545</span><span class="err">.</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="err">============================================</span></span></span></code></pre></div>

  <div class="admonition note">
    <div class="admonition-header">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M0 64C0 28.7 28.7 0 64 0L224 0l0 128c0 17.7 14.3 32 32 32l128 0 0 125.7-86.8 86.8c-10.3 10.3-17.5 23.1-21 37.2l-18.7 74.9c-2.3 9.2-1.8 18.8 1.3 27.5L64 512c-35.3 0-64-28.7-64-64L0 64zm384 64l-128 0L256 0 384 128zM549.8 235.7l14.4 14.4c15.6 15.6 15.6 40.9 0 56.6l-29.4 29.4-71-71 29.4-29.4c15.6-15.6 40.9-15.6 56.6 0zM311.9 417L441.1 287.8l71 71L382.9 487.9c-4.1 4.1-9.2 7-14.9 8.4l-60.1 15c-5.5 1.4-11.2-.2-15.2-4.2s-5.6-9.7-4.2-15.2l15-60.1c1.4-5.6 4.3-10.8 8.4-14.9z"/></svg>
      <span>Summary</span>
    </div>
      <div class="admonition-content">
        <p>By providing function calls to the model we can leverage our ability to execute functions reliably so long as the model is able to correctly identify when functions can be invoked and use the right arguments.</p>
      </div>
  </div>
<h3 id="generating-testing-values">Generating Testing Values</h3>
<p>In order to test how well a model can predict random arithmetic operations we have to first generate a few random values so that we can compare the results with and without tool calls. We will be using a more difficult examples with decimal points to stress test the model. I picked two ways of generating values randomly:</p>
<ol>
<li>For a <strong>linear</strong> approach we pick a random magnitude from -5 to 5 as the exponent and a random value from -1 to 1 and we get a random value back of value × 10<sup>exp</sup></li>
<li>For a <strong>gaussian</strong> approach we use a normal distribution with a set standard deviation. This ensures that our values are a bit closer to what we would consider normal, from around 100 to 0.001 with a low chance of outliers.</li>
</ol>
<p>Both distributions can be seen visualized below for 100 distinct values.</p>

<div><img src="/blog/artifacts/guides/calculator-tool-call/value_distribution_hu_4326a58299a6741a.webp" srcset="/blog/artifacts/guides/calculator-tool-call/value_distribution_hu_4326a58299a6741a.webp 1x, /blog/artifacts/guides/calculator-tool-call/value_distribution_hu_2d35f0eece1be3b7.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="800" height="400" style="width: min(100%, 800px); aspect-ratio: 800 / 400; object-fit: contain;">
</div>

<p>We can also heatmap the values into a 2D grid to see where the values are concentrated. The heatmaps show the values for both the linear and gaussian distributions.</p>

<div><img src="/blog/artifacts/guides/calculator-tool-call/distribution_heatmaps_hu_977868f2050ce5b9.webp" srcset="/blog/artifacts/guides/calculator-tool-call/distribution_heatmaps_hu_977868f2050ce5b9.webp 1x, /blog/artifacts/guides/calculator-tool-call/distribution_heatmaps_hu_745576354c7383c9.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="800" height="400" style="width: min(100%, 800px); aspect-ratio: 800 / 400; object-fit: contain;">
</div>

<div style="display: flex; column-gap: 1rem; row-gap: 0.1rem; flex-wrap: wrap; justify-content: left;">
    
<a
  class="file-download"
  href="/blog/artifacts/guides/calculator-tool-call/log_distribution.py"
  download="log_distribution.py"
  aria-label="Download PY: log_distribution.py"
>
  <span class="file-download-icon" aria-hidden="true">
    <svg viewBox="0 0 24 24" focusable="false">
      <path d="M12 3v11m0 0 4-4m-4 4-4-4M5 18v2h14v-2" />
    </svg>
  </span>
  <span class="file-download-name">log_distribution.py</span>
</a>

<a
  class="file-download"
  href="/blog/artifacts/guides/calculator-tool-call/plot_log_chart.py"
  download="plot_log_chart.py"
  aria-label="Download PY: plot_log_chart.py"
>
  <span class="file-download-icon" aria-hidden="true">
    <svg viewBox="0 0 24 24" focusable="false">
      <path d="M12 3v11m0 0 4-4m-4 4-4-4M5 18v2h14v-2" />
    </svg>
  </span>
  <span class="file-download-name">plot_log_chart.py</span>
</a>

<a
  class="file-download"
  href="/blog/artifacts/guides/calculator-tool-call/plot_distribution_heatmaps.py"
  download="plot_distribution_heatmaps.py"
  aria-label="Download PY: plot_distribution_heatmaps.py"
>
  <span class="file-download-icon" aria-hidden="true">
    <svg viewBox="0 0 24 24" focusable="false">
      <path d="M12 3v11m0 0 4-4m-4 4-4-4M5 18v2h14v-2" />
    </svg>
  </span>
  <span class="file-download-name">plot_distribution_heatmaps.py</span>
</a>


  </div>

<p>We&rsquo;ll use both of these distributions to generate random values for testing the model&rsquo;s ability to do simple math with and without tool calls. The next step is to run a series of tests using these generated values and compare the results.</p>
<h3 id="testing-the-model-without-tool-calls">Testing the Model without Tool Calls</h3>
<p>With the test data we have available we can pick two random values and a random operator and ask the model to calculate the result without using tool calls. We can then compare the model&rsquo;s output with the actual result of the operation and see how well it performs.</p>
<p>Here are the results for the linear distribution of input data using the <code>gpt4.1 mini</code> model, as it yielded the most interesting results.</p>

<div><img src="/blog/artifacts/guides/calculator-tool-call/tool_call_statistics_hu_422ede033ffe2b27.webp" srcset="/blog/artifacts/guides/calculator-tool-call/tool_call_statistics_hu_422ede033ffe2b27.webp 1x, /blog/artifacts/guides/calculator-tool-call/tool_call_statistics_hu_b94cfa665e15d6d7.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="800" height="400" style="width: min(100%, 800px); aspect-ratio: 800 / 400; object-fit: contain;">

  <figcaption class="figure-caption">
    generate_graph.py
  </figcaption>
</div>

<p>The mini model performed reasonably on its own, getting a 77.2% accuracy without any tool calling. However with tool calling this number shot up to 99.4% with the only errors coming from the model confusing a negative operator as belonging to the operator itself as well as the second number.</p>
<p>We can also compare the tokens required, time taken and estimated cost for both approaches.</p>

<div><img src="/blog/artifacts/guides/calculator-tool-call/tool_call_analysis_hu_fab3de7deeeb7b7e.webp" srcset="/blog/artifacts/guides/calculator-tool-call/tool_call_analysis_hu_fab3de7deeeb7b7e.webp 1x, /blog/artifacts/guides/calculator-tool-call/tool_call_analysis_hu_751b4563b5eee8f6.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="800" height="400" style="width: min(100%, 800px); aspect-ratio: 800 / 400; object-fit: contain;">
</div>

<p>Click on the images to open in a new tab to see the full detailed stats.
The results are also temporarily available at this <a href="https://arithmetic-model-test-results.kalatostack.chatgpt.site"><strong>website</strong></a>.</p>
<h3 id="summary">Summary</h3>
<p>Adding the calculator made a large difference in these tests. On the log-uniform questions, the pass rate went from <strong>78.2%</strong> to <strong>99.8%</strong>. On the log-Gaussian questions, <strong>all</strong> 1,000 calculator-assisted answers passed. That improvement came with a second model request and roughly 7x to 8x the total tokens.</p>

  <div class="admonition important">
    <div class="admonition-header">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/></svg>
      <span>Important</span>
    </div>
      <div class="admonition-content">
        <p>Due to the small model used, in 2 instances the model changed the sign of an input before calling the calculator. Once that happened, the calculator had no way of knowing it was answering a different question.</p>
      </div>
  </div>
<p>These results are specific to this model, these generated questions, and the way I compared answers at their returned precision. They were enough to answer the question I started with: <strong>a calculator tool call helped substantially, but it came at a cost of more time, tokens and money, without a 100% reliability guarantee.</strong></p>
]]></content:encoded></item><item><title>Binary Search in Python</title><link>https://michaelmuratov.ca/blog/artifacts/guides/binary-search-python/</link><pubDate>Sun, 27 Jun 2021 00:00:00 +0000</pubDate><guid>https://michaelmuratov.ca/blog/artifacts/guides/binary-search-python/</guid><description>&lt;p&gt;I always get anxious when I see a problem that involves a sorted list because I know that it’ll inevitably involve using binary search.&lt;/p&gt;
&lt;p&gt;This fear is completely irrational, and I always kick myself for feeling this way because binary search is beautiful. Given a sorted list you can find the index of any value in log(N) time because you get to cut your search space in half with every lookup.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I always get anxious when I see a problem that involves a sorted list because I know that it’ll inevitably involve using binary search.</p>
<p>This fear is completely irrational, and I always kick myself for feeling this way because binary search is beautiful. Given a sorted list you can find the index of any value in log(N) time because you get to cut your search space in half with every lookup.</p>

<div><img src="/blog/artifacts/guides/binary-search-python/table_hu_a840df75ab69cb98.webp" srcset="/blog/artifacts/guides/binary-search-python/table_hu_a840df75ab69cb98.webp 1x, /blog/artifacts/guides/binary-search-python/table_hu_1e005a1359d6855a.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="800" height="400" style="width: min(100%, 800px); aspect-ratio: 800 / 400; object-fit: contain;">

  <figcaption class="figure-caption">
    geeksforgeeks.org/binary-search
  </figcaption>
</div>

<p>Precisely this operation allows sorted lists to be very space and time efficient at solving problems requiring lookups as well as determining how many entries are greater or less than your target.</p>
<p>Now if you want to take advantage of your sorted lists you may be tempted to write your own binary search and insert functions like I’ve been doing so far and inevitably it takes a few tries to actually get it working right. Thankfully there’s a built in library that already does the same thing, in a single line and a lot faster too.</p>
<h3 id="bisect">Bisect</h3>
<p>The bisect library is a tiny one, but it does two things and it does them well; <strong>search</strong> and <strong>insert</strong>.</p>
<p>For search we have <strong>bisect_left</strong> and <strong>bisect_right</strong> which perform binary search to find where to insert a value right before our target on either the left or right. In the case of <strong>bisect_right</strong> it will overshoot by one index to show you where you should insert your new value to maintain order.</p>
<p>list: [1,2,3,4,5], target = 4</p>
<ul>
<li><strong>bisect_left</strong>: [1,2,3, _ , 4,5] index= 3</li>
<li><strong>bisect_right</strong>: [1,2,3,4, _ ,5] index= 3+1</li>
</ul>
<p>For insertion we have <strong>insort_left</strong> and <strong>insort_right</strong> which perform binary insert to actually insert our value on either the left or the right of our target and manipulates our list inplace.</p>
<ul>
<li><strong>insort_left</strong>: [1,2,3, 4 ,4,5] inserted index= 3</li>
<li><strong>insort_right</strong>: [1,2,3,4, 4 ,5] inserted index= 3+1</li>
</ul>
<p>Apart from <strong>bisect</strong> and insort which are equivalent in function to <strong>bisect_right</strong> and <strong>insort_right</strong> respectivly, these are the only functions available in this library. However they completely replace the need to write your own functions for lookups and inserts.</p>
<h3 id="bisect-is-fast">Bisect is Fast</h3>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">def</span> <span class="nf">binary_search</span><span class="p">(</span><span class="n">lst</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">lst</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="k">while</span> <span class="n">start</span> <span class="o">&lt;=</span> <span class="n">end</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="n">middle</span> <span class="o">=</span> <span class="p">(</span><span class="n">end</span><span class="o">+</span><span class="n">start</span><span class="p">)</span><span class="o">//</span><span class="mi">2</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="k">if</span> <span class="n">target</span> <span class="o">&gt;</span> <span class="n">lst</span><span class="p">[</span><span class="n">middle</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">            <span class="n">start</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="k">elif</span> <span class="n">target</span> <span class="o">&lt;</span> <span class="n">lst</span><span class="p">[</span><span class="n">middle</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">            <span class="n">end</span> <span class="o">=</span> <span class="n">middle</span> <span class="o">-</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">            <span class="k">return</span> <span class="n">middle</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span></span></span></code></pre></div>
<p>And here’s a binary race between it and bisect. We’ll be looking for value 0 because ironically it will take the longest to find with binary search since 0 is never in the middle of anything.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">#list and target</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">input_list</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1000000</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">target</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1">#my binary search</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">index</span> <span class="o">=</span> <span class="n">binary_search</span><span class="p">(</span><span class="n">input_list</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">duration</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;search found </span><span class="si">{}</span><span class="s2"> at index </span><span class="si">{}</span><span class="s2"> in </span><span class="si">{}</span><span class="s2"> seconds&#34;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">target</span><span class="p">,</span><span class="n">index</span><span class="p">,</span><span class="n">duration</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1">#bisect binary search</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">index</span> <span class="o">=</span> <span class="n">bisect</span><span class="o">.</span><span class="n">bisect_left</span><span class="p">(</span><span class="n">input_list</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="k">if</span> <span class="n">index</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">input_list</span><span class="p">)</span> <span class="ow">or</span> <span class="n">input_list</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">!=</span> <span class="n">target</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">index</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="n">duration</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;bisect found </span><span class="si">{}</span><span class="s2"> at index </span><span class="si">{}</span><span class="s2"> in </span><span class="si">{}</span><span class="s2"> seconds&#34;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">target</span><span class="p">,</span><span class="n">index</span><span class="p">,</span><span class="n">duration</span><span class="p">))</span></span></span></code></pre></div>
<ul>
<li>search found 0 at index 0 in <strong>1.6927719116210938e-05 seconds</strong></li>
<li>bisect found 0 at index 0 in <strong>2.6226043701171875e-06 seconds</strong></li>
</ul>
<p>Here we can see that bisect is <strong>6</strong> times faster than my implementation</p>
<p>Because bisect is implemented in C it is much faster, though both functions use the exact same algorithm. Python is just a lot slower at adding numbers than C because all numbers in Python are actually Integer classes which in turn take time to call their addition functions whereas in C integers are just 4 byte data types and are processed very efficiently by the CPU. The difference in time can start to compound into a tangible boost in performance when you start doing many lookups or insertions sequentially.</p>
<h3 id="conclusion">Conclusion</h3>
<p>Bisect is a small but useful library that helps maintain sorted order in lists as well as providing lookups in a quick and efficient way. Knowing about its existence can save on both implementation and runtime and it is an indespensible tool for many coding interviews where questions about sorted lists tend to crop up from time to time.</p>
]]></content:encoded></item><item><title>Solving for Recursive Complexity</title><link>https://michaelmuratov.ca/blog/artifacts/guides/solving-recursive-complexity/</link><pubDate>Tue, 19 May 2020 00:00:00 +0000</pubDate><guid>https://michaelmuratov.ca/blog/artifacts/guides/solving-recursive-complexity/</guid><description>&lt;p&gt;A few days ago I bumped into a question on &lt;a href="https://leetcode.com/"&gt;LeetCode&lt;/a&gt; where I saw a bunch of people scratching their heads. It was question number 10 titled Regular Expression Matching with the difficulty label Hard. The solution to the exercise itself was not intuitive, requiring effective use of previously solved subproblems, but that wasn’t what everyone in the comments were interested in. After all the solution was available for everyone to see.&lt;/p&gt;</description><content:encoded><![CDATA[<p>A few days ago I bumped into a question on <a href="https://leetcode.com/">LeetCode</a> where I saw a bunch of people scratching their heads. It was question number 10 titled Regular Expression Matching with the difficulty label Hard. The solution to the exercise itself was not intuitive, requiring effective use of previously solved subproblems, but that wasn’t what everyone in the comments were interested in. After all the solution was available for everyone to see.</p>
<p>The real intrigue was the calculated but unexplained time complexity for one of the inefficient solutions which only used recursion, minus the dynamic programming. After all, <a href="https://en.wikipedia.org/wiki/Dynamic_programming">dynamic programming</a> makes time and space complexity fairly easy to compute, as long as the solution is correct, it cannot exceed the complexity of all possible subproblems. Before I can get ahead of myself though here’s the outline of the original problem which can also be found here <a href="https://leetcode.com/problems/regular-expression-matching/">https://leetcode.com/problems/regular-expression-matching/</a></p>
<p>If at some point I lose you during the explanation please leave a comment so I can make a revision.</p>
<h3 id="the-problem">The Problem:</h3>
<p>Given an input string (<code>s</code>) and a pattern (<code>p</code>), implement regular expression matching with support for <code>'.'</code> and <code>'*'</code>.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="ln">1</span><span class="cl">&#39;.&#39; Matches any single character.
</span></span><span class="line"><span class="ln">2</span><span class="cl">&#39;*&#39; Matches zero or more of the preceding element.</span></span></code></pre></div>
<p>The matching should cover the <strong>entire</strong> input string (not partial).</p>
<p>Note:</p>
<ul>
<li><code>s</code> could be empty and contains only lowercase letters <code>a-z</code>.</li>
<li><code>p</code> could be empty and contains only lowercase letters <code>a-z</code>, and characters like <code>.</code> or <code>*</code>.</li>
</ul>
<h3 id="some-examples">Some Examples:</h3>
<h4 id="example-1">Example 1</h4>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln">1</span><span class="cl">Input:
</span></span><span class="line"><span class="ln">2</span><span class="cl">s = &#34;abcda&#34;
</span></span><span class="line"><span class="ln">3</span><span class="cl">p = &#34;ab.d&#34;
</span></span><span class="line"><span class="ln">4</span><span class="cl">Output: false
</span></span><span class="line"><span class="ln">5</span><span class="cl">Explanation: The . matches the c but the pattern ends before matching to the entire text.</span></span></code></pre></div>
<h4 id="example-2">Example 2</h4>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln">1</span><span class="cl">Input:
</span></span><span class="line"><span class="ln">2</span><span class="cl">s = &#34;aab&#34;
</span></span><span class="line"><span class="ln">3</span><span class="cl">p = &#34;c*a*b&#34;
</span></span><span class="line"><span class="ln">4</span><span class="cl">Output: true
</span></span><span class="line"><span class="ln">5</span><span class="cl">Explanation: c can be repeated 0 times, a can be repeated 2 times. Therefore, it matches &#34;aab&#34;.</span></span></code></pre></div>
<h4 id="example-3">Example 3</h4>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln">1</span><span class="cl">Input:
</span></span><span class="line"><span class="ln">2</span><span class="cl">s = &#34;ab&#34;
</span></span><span class="line"><span class="ln">3</span><span class="cl">p = &#34;.*&#34;
</span></span><span class="line"><span class="ln">4</span><span class="cl">Output: true
</span></span><span class="line"><span class="ln">5</span><span class="cl">Explanation: &#34;.*&#34; means &#34;zero or more (*) of any character (.)&#34;.</span></span></code></pre></div>
<p>The examples above summarize the kind of cases you can expect to be dealing with during testing. Because the title of the article is “Solving for Recursive Complexity” and not “How to Solve Recursive Problems” I won’t be going too deeply into how to solve this kind of problem. Instead I will resort to flashing a piece of pseudo code that explains the 3 recursive gates that our algorithm will be passing through on its journey to the end of the piece of text. I’d recommend trying to solve this problem on your own by going to the link I included above, and coming back here once you’ve gained a level of appreciation for this problem, because I’m about to spoil it for you.</p>
<h3 id="solution-pseudo-code">Solution Pseudo-code:</h3>
<p><img src="/blog/artifacts/guides/solving-recursive-complexity/pseudocode_hu_478c572cc4862fa3.webp" width="635" height="417"
  alt="alt text" loading="lazy" decoding="async"></p>
<h3 id="quick-explanation">Quick Explanation</h3>
<p>If you’re not very familiar with recursion, this code block might still look very intimidating. The gist is that we’re only doing two things:</p>
<ol>
<li>
<p>checking if the current character of the text matches the pattern and</p>
</li>
<li>
<p>asking if the pattern will match the text if we modify the text a bit or the pattern a bit or both for the remaining characters.</p>
</li>
</ol>
<p>**Line 12: <code>keep_asterisk_match</code> is true if we don’t change the pattern but move along the length of the text (<strong>text[1:]</strong>). This is how <code>*</code> is dealt with in recursion, we simply move on to the next character of the text like the current one never existed and keep the asterisk in the pattern.</p>
<p><strong>Line 17:</strong> <code>skip_asterisk_match</code> is true if the text matches the pattern without the asterisk (<strong>pattern[2:]</strong>) i.e if we match 0 of the preceding element. Remember in Example 2 where c* didn’t have to match anything, and this is also how we jump out of the <code>keep_asterisk_match</code> trap that we made for ourselves earlier.</p>
<p><strong>Line 20</strong>: Once we get an answer for whether we get a match when keeping or skipping the asterisk after <code>keep_asterisk_match</code> and <code>skip_asterisk_match</code> are run we return the result as shown in the OR table below.</p>

<div><img src="/blog/artifacts/guides/solving-recursive-complexity/logic_table_hu_e986b99d589d7369.webp"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">

  <figcaption class="figure-caption">
    (https://dyclassroom.com/logic-gate/universal-logic-gate-nor)
  </figcaption>
</div>

<p><strong>Line 24</strong>: If we don’t see an asterisk we check if that first character matched the pattern with <code>character_match</code> and we keep recusing by reducing the input text and pattern by that first matched character (<strong>text[1:], pattern[1:]</strong>) and recursively check if the rest of the string matches.</p>
<p><strong>Line 4</strong>: The final part of recursion which ironically is usually defined at the top of the function, is our recursion rock bottom. If we have an empty pattern and an empty string as our inputs, we have the divine knowledge that the pattern will match the string because empty matches empty for sure. If only one of them is empty we know that there’s no match.</p>
<h3 id="considering-the-complexity">Considering the Complexity</h3>
<p>The time complexity for this question appears to be difficult to pin down. After all, there are two points of recursion and one full stop. And like I said before, the answer to the complexity is given in the solutions with no further explanations. For text of length T and pattern of length P, with the text being indexed at text[i:] and pattern[2j:], the time complexity for this question is….<strong>drum roll</strong></p>
\[
  \sum_{i=0}^{T}\sum_{j=0}^{P/2}\binom{i+j}{i} \space O(T-i) +  \space  O(P-2j)
\]<p>Well, that’s quite something.</p>
<p>Normally you’d expect something like O(T*P) or anything else to that effect and in fact, the solutions do propose a more concise upper bound, again without any explanations (not surprisingly), but we’ll get to that later. For now we have enough on our hands as it is with this piece of work.</p>
<h3 id="linear-vs-exponential-complexity">Linear vs Exponential Complexity</h3>
<p>The reason why the complexity isn’t as simple as it is for something like <a href="https://en.wikipedia.org/wiki/Bubble_sort">bubble sort</a>, is because we’re not making linear passes over our text and pattern. Instead we’re doing things recursively, diving deeper and deeper through sections of our text and pattern and revisiting the same sub problems for what can feel like an arbitrary number of times. The reason I bring up bubble sort, which has O(n²) complexity, is because its complexity decreases in the shape of a pyramid as we sort more and more digits.</p>

<div><img src="/blog/artifacts/guides/solving-recursive-complexity/pyramid_hu_2ef47b53ef93d968.webp" srcset="/blog/artifacts/guides/solving-recursive-complexity/pyramid_hu_2ef47b53ef93d968.webp 1x, /blog/artifacts/guides/solving-recursive-complexity/pyramid_hu_14b59de11eab56cf.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">
</div>

<p>On the other hand, recursion has the classic shape of a tree due to the multiple places where the function can call itself.</p>

<div><img src="/blog/artifacts/guides/solving-recursive-complexity/tree_hu_214180711025b3b4.webp" srcset="/blog/artifacts/guides/solving-recursive-complexity/tree_hu_214180711025b3b4.webp 1x, /blog/artifacts/guides/solving-recursive-complexity/tree_hu_cef87cad80234fba.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">
</div>

<p>The structures look deceptively similar but the crucial difference is that where the pyramid decreases linearly, the tree grows exponentially. This creates a world of a difference when analyzing time and space complexity.</p>
<h3 id="our-worst-case">Our Worst Case</h3>
<p>When analyzing worst case complexity we have to think of the worst case input. Because we have two inputs, text and pattern, I will focus on the pattern because one depends on the other and at least for me it’s easier to think of the rules rather than the results. In this question each new character we add to our pattern can be either a <code>.*</code> or <code>.</code> where <code>.</code> can be any character. From the code it should be pretty clear which choice causes more computation. If we include the <code>*</code> character, our code splits into two streams which must both be computed until inevitably they should return whether there’s a match, meanwhile if we are matching a single character the fun stops pretty quickly as we are only taking a single route, linearly.</p>
<p><img src="/blog/artifacts/guides/solving-recursive-complexity/pseudocode2_hu_6b334d00e3d809aa.webp" width="602" height="294"
  alt="alt text" loading="lazy" decoding="async"></p>
<p>It looks pretty clear that a worst case pattern would consist of many .* to create as many diverging paths as possible, with a final text character which does or doesn’t match the pattern.</p>
<p><strong>Text: aaaaaaaaaab</strong></p>
<p><strong>Pattern: a*a*a*a*a*a*a*a*a*a*</strong></p>
<p>In this scenario we must get both to the end of the pattern and to the end of the string to determine that there is no match, while branching 2¹⁰ number of times starting from the first index of the text.</p>
<h3 id="visualizing-the-computation">Visualizing the Computation</h3>
<p>In order to figure out the time complexity we have to find how many times each sub-problem had to be computed. Because we are not saving the result like in dynamic programming this will largely contribute to the exploding runtime. Each sub-problem consists of answering whether text[i:] and pattern[2j:] are a match. We use pattern[2j:] because we are using <code>.*</code> repeatedly in our pattern for the worst case, every time we take the <strong>skip_asterisk_matched</strong> path we skip one of the <code>.*</code> which take up two spaces. In order to visualize the two branches of <strong>skip_asterisk_matched</strong> and <strong>keep_asterisk_matched</strong> we will draw a tree diagram to illustrate all the visited sub-problems. Each node will have the format (i,j) for where the text and pattern are indexed at each point in time.</p>

<div><img src="/blog/artifacts/guides/solving-recursive-complexity/tree_combos_hu_8f2e1118ef7d2895.webp" srcset="/blog/artifacts/guides/solving-recursive-complexity/tree_combos_hu_8f2e1118ef7d2895.webp 1x, /blog/artifacts/guides/solving-recursive-complexity/tree_combos_hu_df7c282ff256fbf8.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">
</div>

<p>A quick side note on this, when performing recursion, the algorithm will perform a <a href="https://en.wikipedia.org/wiki/Depth-first_search">depth-first search</a> by taking the left path first on each iteration. This doesn’t make much of a difference though because in the worst case we’ll have to traverse the entire tree anyways. Let’s take an example sub-problem where we want to see if text[2:] and pattern[2:] were a match. This will appear as (2,1) on our tree:</p>
<p>i=2 because we are at text[2:] for the text
j=1 because we are at pattern[2:] which in the worst case means we have only a single <code>.*</code> asterisk that takes up two spaces. Following pattern[2j:] means j=1.</p>

<div><img src="/blog/artifacts/guides/solving-recursive-complexity/tree_path_hu_b3903f2366039ddf.webp" srcset="/blog/artifacts/guides/solving-recursive-complexity/tree_path_hu_b3903f2366039ddf.webp 1x, /blog/artifacts/guides/solving-recursive-complexity/tree_path_hu_7429c6856c547e97.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">
</div>

<p>We can see that this sub-problem had been encountered 3 times during computation. The tree format is good for seeing when these sub-problems will be encountered but it’s not very good at determining how many times that will happen.</p>
<h3 id="combinations">Combinations</h3>
<p>The way to systematically consider how many times a sub-problem will be encountered is to consider how come these sub-problems tend to repeat themselves in the first place. In order to arrive at (2,1) on our tree we have to take two lefts and one right.</p>
<p><img src="/blog/artifacts/guides/solving-recursive-complexity/tree_pathing_hu_a3fbb0faeaf19402.webp" srcset="/blog/artifacts/guides/solving-recursive-complexity/tree_pathing_hu_a3fbb0faeaf19402.webp 1x, /blog/artifacts/guides/solving-recursive-complexity/tree_pathing_hu_3c070bdd253cb6f2.webp 2x" width="800" height="600"
  alt="alt text" loading="lazy" decoding="async"></p>
<p>As we can see this can happen in three ways, if we traverse the tree in the sequence LLR, LRL and RLL.</p>
<p><img src="/blog/artifacts/guides/solving-recursive-complexity/path_block_hu_af57b28da4eb112f.webp" width="504" height="301"
  alt="alt text" loading="lazy" decoding="async"></p>
<p>In the example of (2,1) we know that we will have 2+1=3 place holders where 2 of the placeholders will be an L and 1 will be an R. In order to find how many combinations are possible we can simply compute 3C2 where out of 3 place holders we will choose 2 to be an L and the rest will automatically be Rs.</p>
<p>That means that for sub-problem (i,j) we have i+j placeholders with i of those being the left side and j being on the right side. This is why the solutions include the combinations symbol for the number of encountered sub-problems (i,j) with (i+j choose i).</p>
\[
  \binom{i+j}{i}
\]<p>Incidentally this is also equivalent to (i+j choose j) because it does not matter whether you are picking which i increments are on the left or instead picking which j increments are on the right, the number of distinct combinations will be the same.</p>
\[
  \binom{i+j}{j}
\]<h3 id="sub-problem-complexity">Sub-Problem Complexity</h3>
<p>Now that we know how many sub-problems of each kind we will encounter, we should figure out how long those individual sub-problem will take to complete. This sort of thing tends to be very easy to do with recursive problems, like in this case where we only really do one thing, compare a single character and store the result in character_match. This might lead you to believe that the runtime for each sub-problem is constant O(1), but in order to call the function we must first supply text[i] and pattern[j:] arguments. If the strings are long, this procedure is not trivial, especially in python where in order to pass in a sub-string a new string must be created. Therefore for each sub-problem there is a constant time O(1) for checking that the character matched, an O(T-i) for passing in the part of the string that we don’t know is a match yet, and an O(P-2j) for passing in the part of the pattern that we don’t know is a match yet. Adding everything together we arrive at the complexity given in the solution.</p>
\[
  \sum_{i=0}^{T}\sum_{j=0}^{P/2}\binom{i+j}{i} \space O(T-i) +  \space  O(P-2j)
\]<h3 id="the-concise-solution">The Concise Solution</h3>
<p>Remember earlier when I said that the solution proposed a more general bound, without the complex combination notation and sigma signs.</p>
<p>Well here it is.</p>
\[
  O((T+P) * 2^{T+\frac{P}{2}})
\]<p>Let’s go through the idea behind this one before we wrap up.</p>
<p>The idea behind making the time complexity into this simplified form is to go overkill on both how many sub problems we could encounter and how long we plan on those sub problems taking to compute.</p>
<h4 id="number-of-sub-problems">Number of Sub-problems</h4>
<p>Instead of using combinations to compute precisely how many sub problems we will encounter, which based on our combinations calculation will be only a portion of our tree’s leaf nodes, let’s just take the entire bottom level of the tree.</p>
<p>Let’s also make the tree completely full with a depth of the maximum number that \(i+j\) can take, which is \((T+\frac{P}{2})\).</p>
<ul>
<li>
<p>T for the length of the text and \(\frac{P}{2}\) for all <code>.*</code> instances in our worst case pattern</p>
</li>
<li>
<p>A tree of depth \((T+\frac{P}{2})\) will have \(2^{(T+\frac{P}{2})}\) nodes at the lowest level.</p>
</li>
</ul>
<p><img src="/blog/artifacts/guides/solving-recursive-complexity/depth_hu_f8ea76dd7057fdd9.webp" width="700" height="524"
  alt="alt" loading="lazy" decoding="async"></p>
<p>In the image we can see the previous example of text[2:] and pattern[2:] being computed \(\binom{2+1}{2}\) = 3 times, but since we know that all these examples happen on the same level (because # of Ls+ # of Rs is always 3) we can compute the number of all sub problems on that level which is \(2^{(2+\frac{2}{2})}\) = 2³ = 8.</p>
<p>The number of nodes on the entire level (8 in this case) will always be larger than the \(\binom{i+j}{j}\) nodes (3 in this case), so we can use this calculation in our more general upper bound. So we have determined that our upper bound will assume that we will go through \(2^{(T+\frac{P}{2})}\) subproblems, even though we really never will, but it does make our formula more concise.</p>
<h4 id="sub-problem-complexity-1">Sub-problem Complexity</h4>
<p>Instead of computing how large the arguments will be before we pass them in, let’s just assume we are passing in the entire strings for both the text and pattern. This will give us <strong>O(T+P)</strong> time complexity for each sub-problem, eliminating the need to compute what O(T-i) and O(P-2j) are at every step.</p>
<h4 id="final-answer">Final Answer</h4>
<p>Multiplying the Sub-problem complexity by the number of sub-problems gives us the final answer of:</p>
\[
  O((T+P) * 2^{T+\frac{P}{2}})
\]<h3 id="a-case-for-dynamic-programming">A Case for Dynamic Programming</h3>
<p>This was all incredibly tedious and time consuming on both ours and the computer’s part. At some point you probably thought that computing the same problem (i+j choose i ) times was a bit wasteful and if we just stored that result it would save us a lot of trouble. You’d be right.</p>
<p>There’s only T*P distinct combinations of (i,j), and each takes only constant time to verify, so simply storing all of them in a grid will bump our computation down to a whopping.</p>
\[
  O(TP)
\]<p>I hope you enjoyed this exercise in computational complexity. Seeing as you got to the very end, do give yourself a pat on the back because you deserve it.</p>
]]></content:encoded></item><item><title>Toy Car Reinforcement Learning</title><link>https://michaelmuratov.ca/blog/artifacts/builds/toy-car-ml/</link><pubDate>Sun, 11 Aug 2019 00:00:00 +0000</pubDate><guid>https://michaelmuratov.ca/blog/artifacts/builds/toy-car-ml/</guid><description>&lt;h3 id="introduction"&gt;Introduction&lt;/h3&gt;
&lt;p&gt;As a team of three undergraduate students, we were tasked with building a concept self driving car in our winter semester. Not having much experience in data science or machine learning meant that the production process was a mess, although looking back we probably could have made the same amount of progress in a fraction of the time.&lt;/p&gt;
&lt;p&gt;This article is for those who are interested in what it takes to build a functioning self driving car in record time, on a budget, without the headaches that we had to go through! I don’t go too much in depth on all the details but there are a few snippets of code to spice things up. Also if you are interested in the code you can help yourself to our Github page, &lt;a href="https://github.com/RoboticsCourse"&gt;https://github.com/RoboticsCourse&lt;/a&gt;, but be warned that it’s not documented and was not created for general use.&lt;/p&gt;</description><content:encoded><![CDATA[<h3 id="introduction">Introduction</h3>
<p>As a team of three undergraduate students, we were tasked with building a concept self driving car in our winter semester. Not having much experience in data science or machine learning meant that the production process was a mess, although looking back we probably could have made the same amount of progress in a fraction of the time.</p>
<p>This article is for those who are interested in what it takes to build a functioning self driving car in record time, on a budget, without the headaches that we had to go through! I don’t go too much in depth on all the details but there are a few snippets of code to spice things up. Also if you are interested in the code you can help yourself to our Github page, <a href="https://github.com/RoboticsCourse">https://github.com/RoboticsCourse</a>, but be warned that it’s not documented and was not created for general use.</p>
<h3 id="what-well-need">What We’ll Need:</h3>
<ul>
<li><a href="https://www.amazon.com/dp/B09YTG1LFD/ref=sspa_dk_detail_3?psc=1&amp;pd_rd_i=B09YTG1LFD&amp;pd_rd_w=3pESF&amp;content-id=amzn1.sym.386c274b-4bfe-4421-9052-a1a56db557ab&amp;pf_rd_p=386c274b-4bfe-4421-9052-a1a56db557ab&amp;pf_rd_r=6RPTHKRZEY7TXSRJBBEG&amp;pd_rd_wg=7xuuP&amp;pd_rd_r=24695953-241e-4d3d-9f00-f71d2b63e104&amp;s=toys-and-games&amp;sp_csd=d2lkZ2V0TmFtZT1zcF9kZXRhaWxfdGhlbWF0aWM">Remote Control/Demo Car</a></li>
<li><a href="https://www.amazon.com/gp/product/B008GRTSV6/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=B008GRTSV6&amp;linkCode=as2&amp;tag=michaelmurato-20&amp;linkId=5f8175e1eb6844326ad63db3658f1215">Arduino Uno board</a></li>
<li><a href="https://www.amazon.com/gp/product/B00PUTH3B0/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=B00PUTH3B0&amp;linkCode=as2&amp;tag=michaelmurato-20&amp;linkId=11c76b435eb0e749b7ecf059377394c2">Motor Shield</a></li>
<li><a href="https://www.amazon.com/gp/product/B01HN72K14/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=B01HN72K14&amp;linkCode=as2&amp;tag=michaelmurato-20&amp;linkId=2419b3f00601a89ef9ec37ea1cad1ecf">Bluetooth BLE Module</a></li>
<li>2 Mobile Devices</li>
</ul>
<h3 id="cars-are-meant-for-driving">Cars are meant for driving</h3>
<p>First of all, we wanted to finely control the motion of the car, and the best way to do that was to throw away the controller that came with the original car and instead use an Arduino board. Since they’re programmable and compatible with a whole suite of additional modules which we could buy online for cheap, it was amazing for prototyping. The board we used was the Arduino UNO Rev3 which you can get for $20.</p>
<p>Now to actually be able to control the car via the Arduino board we had to hook it up to a Motor Shield which is a useful little add-on that gives you the ability to power a variety of motors from your Arduino board with just a few lines of code. The snippet bellow shows a simple implementation.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kt">void</span> <span class="n">Navigation</span><span class="o">::</span><span class="n">goForward</span><span class="p">(</span><span class="kt">int</span> <span class="n">speed</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">frontMotor</span><span class="o">-&gt;</span><span class="n">setSpeed</span><span class="p">(</span><span class="n">speed</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">frontMotor</span><span class="o">-&gt;</span><span class="n">run</span><span class="p">(</span><span class="n">FORWARD</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">rearMotor</span><span class="o">-&gt;</span><span class="n">setSpeed</span><span class="p">(</span><span class="n">speed</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">rearMotor</span><span class="o">-&gt;</span><span class="n">run</span><span class="p">(</span><span class="n">FORWARD</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="kt">void</span> <span class="n">Navigation</span><span class="o">::</span><span class="n">goBackward</span><span class="p">(</span><span class="kt">int</span> <span class="n">speed</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">frontMotor</span><span class="o">-&gt;</span><span class="n">setSpeed</span><span class="p">(</span><span class="n">speed</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="n">frontMotor</span><span class="o">-&gt;</span><span class="n">run</span><span class="p">(</span><span class="n">BACKWARD</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">rearMotor</span><span class="o">-&gt;</span><span class="n">setSpeed</span><span class="p">(</span><span class="n">speed</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">rearMotor</span><span class="o">-&gt;</span><span class="n">run</span><span class="p">(</span><span class="n">BACKWARD</span><span class="p">);</span>   
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="kt">void</span> <span class="n">Navigation</span><span class="o">::</span><span class="n">SteerSpeed</span><span class="p">(</span><span class="kt">int</span> <span class="n">speed</span><span class="p">){</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="k">if</span><span class="p">(</span><span class="n">speed</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="n">turnMotor</span><span class="o">-&gt;</span><span class="n">run</span><span class="p">(</span><span class="n">FORWARD</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">  <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="n">speed</span> <span class="o">*=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="n">turnMotor</span><span class="o">-&gt;</span><span class="n">run</span><span class="p">(</span><span class="n">BACKWARD</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">  <span class="n">turnMotor</span><span class="o">-&gt;</span><span class="n">setSpeed</span><span class="p">(</span><span class="n">speed</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="p">}</span></span></span></code></pre></div>
<p>An important implementation challenge was that there is no way to specify distances that the motor will be doing useful work over but instead you must pass in the speed the motor will turn at and the time interval. This means that deepening on the amount of power supplied by the motor, you are responsible for fine tuning these measurements.</p>
<p>Ours ran three DC Motors which were well supported by our Motor Shield. This setup guide really helped us set up and run this configuration.</p>

<div><img src="/blog/artifacts/builds/toy-car-ml/arduino_hu_13b8f3a559eb3d0f.webp" srcset="/blog/artifacts/builds/toy-car-ml/arduino_hu_13b8f3a559eb3d0f.webp 1x, /blog/artifacts/builds/toy-car-ml/arduino_hu_a22460cf1df44b9b.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">
</div>

<p>Now that the Arduino + Motor Shield were all hooked up, and the motors were buzzing we gained the ability to control the car through its new small Arduino brain. However this early in the project it could only follow pre-programmed instructions in a loop and it was time to test what we’ve built.</p>
<h3 id="manual-control">Manual Control</h3>
<p>The next step was to hook up a way to control the car manually, which turned out to be really useful in the training phase. A really handy module available in the Arduino arsenal is the Bluetooth Low Energy chip (BLE). The setup is quick and there’s available example source code for mobile devices to BLE connection so it only took us some minor tweaking to get the board connected to one of our phones.</p>
<p>We used an Android phone to interface with the chip, the the help of this <a href="https://github.com/googlearchive/android-BluetoothLeGatt">BLE Android project</a>. That sample code is an example of Bluetooth text messaging which is very similar to what we’ll be doing to communicate with the car, in fact our implementation will be even simpler.</p>
<p>All it takes is to scan for local Bluetooth devices and connect to the chip, after which we can start sending and receiving messages in a few lines of code! This gave us the freedom to go wild with the input type for the car controller, with my preference being a simple joystick. By sending messages such as S10 (Steer Left at speed 10) or F -100 (Go backwards at speed 100), with S representing the steering motor and F representing the front and back motors, we could encode directions for the car in just a few bytes.</p>

<div><img src="/blog/artifacts/builds/toy-car-ml/android_hu_ea37c0ace66a6c3f.webp"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">
</div>

<p>The latency between the controller and the car proved to be nonexistent and even worked for up to 10m away with no issues. At this point the car was controllable in the same way it was before, if not better. The next step was to actually make car drive on its own and after a few failed attempts at coming up with logic for the car, we turned to neural networks.</p>
<h3 id="machine-learning-needs-data">Machine Learning Needs Data</h3>
<p>Since with neural networks we really can’t get anywhere without gathering a large data set, it’s time to roll out the car and gather sweet data. Like any explorer venturing out into the unknown, our car will want to record all of its experiences for future self reflection. This means that we’ll need one mobile device to drive the car (from the implementation above), and another device with a camera strapped to the front of the car.</p>

<div><img src="/blog/artifacts/builds/toy-car-ml/train_process_hu_9fd3b30cdd8a5982.webp" srcset="/blog/artifacts/builds/toy-car-ml/train_process_hu_9fd3b30cdd8a5982.webp 1x, /blog/artifacts/builds/toy-car-ml/train_process_hu_6d36588a28bf30b0.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="150" height="100" style="width: min(100%, 150px); aspect-ratio: 150 / 100; object-fit: contain;">

  <figcaption class="figure-caption">
    Mobile devices in red
  </figcaption>
</div>

<p>Because our budget was small we strapped a second phone to the car to record video as the car drove around. The input data we could collect was what the camera on the car can see and the logs left by the controller app as a human pilots the car with the other phone. As it turns out, this setup we had now, was the bare minimum required to train a neural network, featuring the input set and a label set.</p>
<p>The input set was the data captured by the camera on the car, and the label set was the input of the human driver piloting the remote car. Now how does that second set work as a label set exactly?</p>
<h3 id="imitation-learning">Imitation Learning</h3>
<p>Do you remember the very first steps you took as a child? Chances are you did not. Even before conscious thought develops in the brain, its capacity to imitate the actions of other people are baked into the wiring of our brains and it allows for learning at an astonishing rate. Our car can’t “walk” yet but just like in the case of the baby, it’s our job to give it an example to follow.</p>
<p>By having a method of controlling the car and logging the input from the human, our car can learn what input it should supply to itself over time and become as good as the pilot.</p>

<div><img src="/blog/artifacts/builds/toy-car-ml/test_process_hu_99edb005a677e29.webp" srcset="/blog/artifacts/builds/toy-car-ml/test_process_hu_99edb005a677e29.webp 1x, /blog/artifacts/builds/toy-car-ml/test_process_hu_53044a38567120b7.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="150" height="100" style="width: min(100%, 150px); aspect-ratio: 150 / 100; object-fit: contain;">

  <figcaption class="figure-caption">
    Celebrate while you still can, human
  </figcaption>
</div>

<h3 id="gathering-the-data">Gathering the Data</h3>
<p>We created a diagram of extreme values for the joystick. The first coordinate value being the degree of steering (x axis) and the second value being the amount of motion (y axis). Having a line of (0,0) cut through the middle of the joystick allowed for a gradient of speed between moving full force forward and moving full force backwards, reducing the wear and tear on our motors, and with maximum steering at 45 degree angles.</p>

<div><img src="/blog/artifacts/builds/toy-car-ml/input_hu_9ee9af2cf77d583a.webp" srcset="/blog/artifacts/builds/toy-car-ml/input_hu_9ee9af2cf77d583a.webp 1x, /blog/artifacts/builds/toy-car-ml/input_hu_6a1b4ce0b62b2566.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">
</div>

<p>Below is the trigonometry that constrains the input joystick to a circle</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kt">float</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">event</span><span class="p">.</span><span class="na">getX</span><span class="p">()</span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="n">circle</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kt">float</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">event</span><span class="p">.</span><span class="na">getY</span><span class="p">()</span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="n">circle</span><span class="p">.</span><span class="na">getHeight</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="kt">double</span><span class="w"> </span><span class="n">distance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">sqrt</span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="na">pow</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">2</span><span class="p">)</span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">pow</span><span class="p">(</span><span class="n">y</span><span class="p">,</span><span class="n">2</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="kt">double</span><span class="w"> </span><span class="n">angle</span><span class="w">  </span><span class="o">=</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">atan2</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">distance</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">circle</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="o">/</span><span class="n">2</span><span class="p">){</span><span class="w"> </span><span class="c1">//if outside the joystick</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">    </span><span class="n">cursorX</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="w"> </span><span class="p">((</span><span class="n">circle</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="o">/</span><span class="n">2</span><span class="p">)</span><span class="o">*</span><span class="n">Math</span><span class="p">.</span><span class="na">sin</span><span class="p">(</span><span class="n">angle</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">    </span><span class="n">cursorY</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="w"> </span><span class="p">((</span><span class="n">circle</span><span class="p">.</span><span class="na">getHeight</span><span class="p">()</span><span class="o">/</span><span class="n">2</span><span class="p">)</span><span class="o">*</span><span class="n">Math</span><span class="p">.</span><span class="na">cos</span><span class="p">(</span><span class="n">angle</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">    </span><span class="n">cursorX</span><span class="o">+=</span><span class="n">circle</span><span class="p">.</span><span class="na">getX</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">circle</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="n">control</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">    </span><span class="n">cursorY</span><span class="o">+=</span><span class="n">circle</span><span class="p">.</span><span class="na">getY</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">circle</span><span class="p">.</span><span class="na">getHeight</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="n">control</span><span class="p">.</span><span class="na">getHeight</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="k">else</span><span class="p">{</span><span class="w"> </span><span class="c1">//if inside the joystick</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">    </span><span class="n">cursorX</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="o">+</span><span class="n">circle</span><span class="p">.</span><span class="na">getX</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">circle</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="n">control</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">    </span><span class="n">cursorY</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">y</span><span class="o">+</span><span class="n">circle</span><span class="p">.</span><span class="na">getY</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">circle</span><span class="p">.</span><span class="na">getHeight</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="n">control</span><span class="p">.</span><span class="na">getHeight</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="n">control</span><span class="p">.</span><span class="na">setX</span><span class="p">(</span><span class="n">cursorX</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="n">control</span><span class="p">.</span><span class="na">setY</span><span class="p">(</span><span class="n">cursorY</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">vector_X</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">circle</span><span class="p">.</span><span class="na">getX</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">circle</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="o">/</span><span class="n">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">control</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="o">/</span><span class="n">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">cursorX</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">255</span><span class="o">/</span><span class="p">(</span><span class="n">circle</span><span class="p">.</span><span class="na">getWidth</span><span class="p">()</span><span class="o">/</span><span class="n">2</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">vector_Y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)(</span><span class="n">circle</span><span class="p">.</span><span class="na">getY</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">circle</span><span class="p">.</span><span class="na">getHeight</span><span class="p">()</span><span class="o">/</span><span class="n">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">control</span><span class="p">.</span><span class="na">getHeight</span><span class="p">()</span><span class="o">/</span><span class="n">2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">cursorY</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">255</span><span class="o">/</span><span class="p">(</span><span class="n">circle</span><span class="p">.</span><span class="na">getHeight</span><span class="p">()</span><span class="o">/</span><span class="n">2</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="kt">int</span><span class="w"> </span><span class="n">final_distance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">dist</span><span class="o">*</span><span class="n">distance</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">vector_X</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">0</span><span class="p">){</span><span class="w">
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="w">      </span><span class="n">final_distance</span><span class="w"> </span><span class="o">*=</span><span class="w"> </span><span class="o">-</span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="n">distance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">sqrt</span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="na">pow</span><span class="p">(</span><span class="n">vector_Y</span><span class="p">,</span><span class="w"> </span><span class="n">2</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">pow</span><span class="p">(</span><span class="n">vector_X</span><span class="p">,</span><span class="w"> </span><span class="n">2</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1">//get scaled values between -255 and 255 for X and between -150 and 150 for Y</span><span class="w">
</span></span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="kt">float</span><span class="w"> </span><span class="n">dist</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="k">if</span><span class="p">(</span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">vector_X</span><span class="p">)</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">vector_Y</span><span class="p">)){</span><span class="w">
</span></span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="w">    </span><span class="k">if</span><span class="p">(</span><span class="n">vector_X</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">0</span><span class="p">){</span><span class="w">
</span></span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="w">        </span><span class="n">dist</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">vector_Y</span><span class="p">)</span><span class="o">/</span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">vector_X</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="k">else</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="w">    </span><span class="k">if</span><span class="p">(</span><span class="n">vector_Y</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="w">        </span><span class="n">dist</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">vector_X</span><span class="p">)</span><span class="o">/</span><span class="n">Math</span><span class="p">.</span><span class="na">abs</span><span class="p">(</span><span class="n">vector_Y</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">45</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="kt">int</span><span class="w"> </span><span class="n">final_distance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">dist</span><span class="o">*</span><span class="n">distance</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">47</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">48</span><span class="cl"><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">final_X</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">final_distance</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="ln">49</span><span class="cl"><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">final_Y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">vector_Y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">150</span><span class="o">/</span><span class="n">255</span><span class="p">;</span></span></span></code></pre></div>
<p>The result was an input range of -150 and 150 for Y and between -255 and 255 for X, the values for Y were smaller because we didn’t want the car to move too fast but a full range of steering was crucial. Below are the results of a training session.</p>

<div><img src="/blog/artifacts/builds/toy-car-ml/training_data_hu_81fe1d0f7b717226.webp" srcset="/blog/artifacts/builds/toy-car-ml/training_data_hu_81fe1d0f7b717226.webp 1x, /blog/artifacts/builds/toy-car-ml/training_data_hu_d515f62049abb67a.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">
</div>

<p>Each dot on the above graph represent the location of the finger on the trackpad at the time that a training image was sliced from the video. The top part represents forward motion, the bottom backwards motion and when the car steered it produced dots that form the diagonals of this hourglass shaped graph. We cut the data into a few logical sectors,</p>
<ol>
<li>
<p>Forward</p>
</li>
<li>
<p>50% Forward</p>
</li>
<li>
<p>Forward Left</p>
</li>
<li>
<p>Forward Right</p>
</li>
<li>
<p>Backward</p>
</li>
<li>
<p>50% Backward</p>
</li>
<li>
<p>Backward Left</p>
</li>
<li>
<p>Backward Right</p>
</li>
</ol>
<p>And “Stop” which proved to be pretty disastrous because at some point the car would learn to permanently stop.</p>
<p>Collecting the image data was somewhat easier, all we had to do was record a video while the car was being driven. Here’s a link to a sample <a href="https://github.com/googlearchive/android-Camera2Video">android project</a> that records a video and saves it to storage when you’re done, we used the same code to capture our videos and even your ordinary camera app works if you don’t want to implement anything custom. The only meta data that’s required is the length of the video and when the recording was initiated.</p>
<h3 id="combining-inputs-and-labels">Combining Inputs and Labels</h3>
<p>In order to match the correct actions with what the car is actually seeing we have to bring the two data sets together. By splitting the training video captured by the front facing camera and time stamping it into separate images we can match them to the timestamp of a log from the controller’s input.</p>
<p>The video was split into 4 images per second of video, although with a 30fps recording we could have gone for a lot more detail. On the other hand our mobile device could capture hundreds of actions on the touchscreen per second, requiring us to disregard most of the data for picking one log per image from the video. Both data sets where submitted to a python script to slice the videos and create matching (image, log) pairs.</p>

<div><img src="/blog/artifacts/builds/toy-car-ml/footage_hu_b29fd406cb62df4f.webp" srcset="/blog/artifacts/builds/toy-car-ml/footage_hu_b29fd406cb62df4f.webp 1x, /blog/artifacts/builds/toy-car-ml/footage_hu_56b9d65a4ec6c8b9.webp 2x"
		 class="img-preset img-preset-md"
		 loading="lazy" decoding="async" width="600" height="400" style="width: min(100%, 600px); aspect-ratio: 600 / 400; object-fit: contain;">

  <figcaption class="figure-caption">
    Each training frame receives one direction label
  </figcaption>
</div>

<p>After driving the car around our building for a bit, we gathered close to 7000 pairs of images and associated human control label pairs. Due our small budget and running the neural network on a phone, we had to down sample our images to 50x50 pixels so that our setup had a fighting chance of working in real time.</p>
<h3 id="using-neural-networks">Using Neural Networks</h3>
<p>This was arguably the most exciting and frustrating part of the project, the machine learning. Because we wanted the car to drive on its own we wanted the on board phone to accomplish both the seeing and the steering for the car. Both were indeed possible. We fully utilized the OpenCV Android library to obtain an image for every time the camera screen was updated as well as running a separate thread to control the Bluetooth chip on the car. We used this <a href="https://medium.com/android-news/a-beginners-guide-to-setting-up-opencv-android-library-on-android-studio-19794e220f3c">android project</a> as an introduction to OpenCV and it got us to a point were we could obtain individual frames of the camera in real time. All that was left to do was to complete a forward pass on our network model with images supplied by the library’s onCameraFrame() function every time there was a new frame.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="n">Mat</span><span class="w"> </span><span class="nf">onCameraFrame</span><span class="p">(</span><span class="n">CvCameraViewFrame</span><span class="w"> </span><span class="n">inputFrame</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">  </span><span class="n">mGray</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">inputFrame</span><span class="p">.</span><span class="na">gray</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">  </span><span class="n">Mat</span><span class="w"> </span><span class="n">mEqualized</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Mat</span><span class="p">(</span><span class="n">mGray</span><span class="p">.</span><span class="na">rows</span><span class="p">(),</span><span class="w"> </span><span class="n">mGray</span><span class="p">.</span><span class="na">cols</span><span class="p">(),</span><span class="w"> </span><span class="n">mGray</span><span class="p">.</span><span class="na">type</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">  
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">  </span><span class="c1">//normalize the image</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">  </span><span class="n">Imgproc</span><span class="p">.</span><span class="na">equalizeHist</span><span class="p">(</span><span class="n">mGray</span><span class="p">,</span><span class="w"> </span><span class="n">mEqualized</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">  
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">  </span><span class="c1">//convert the frame into a scaled bitmap</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">  </span><span class="n">Bitmap</span><span class="w"> </span><span class="n">bitmap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Bitmap</span><span class="p">.</span><span class="na">createBitmap</span><span class="p">(</span><span class="n">mEqualized</span><span class="p">.</span><span class="na">cols</span><span class="p">(),</span><span class="w"> </span><span class="n">mEqualized</span><span class="p">.</span><span class="na">rows</span><span class="p">(),</span><span class="w"> </span><span class="n">Bitmap</span><span class="p">.</span><span class="na">Config</span><span class="p">.</span><span class="na">RGB_565</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">  </span><span class="n">Utils</span><span class="p">.</span><span class="na">matToBitmap</span><span class="p">(</span><span class="n">mEqualized</span><span class="p">,</span><span class="w"> </span><span class="n">bitmap</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">  </span><span class="kd">final</span><span class="w"> </span><span class="n">Bitmap</span><span class="w"> </span><span class="n">scaled_bitmap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Bitmap</span><span class="p">.</span><span class="na">createScaledBitmap</span><span class="p">(</span><span class="n">bitmap</span><span class="p">,</span><span class="w"> </span><span class="n">50</span><span class="p">,</span><span class="w"> </span><span class="n">50</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">  </span><span class="c1">//get output from the neural net model</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">  </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">shape</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">model</span><span class="p">.</span><span class="na">get_Interpreter</span><span class="p">().</span><span class="na">getInputTensor</span><span class="p">(</span><span class="n">0</span><span class="p">).</span><span class="na">shape</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">  </span><span class="kd">final</span><span class="w"> </span><span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">inferencer</span><span class="p">.</span><span class="na">multiImageInference</span><span class="p">(</span><span class="n">model</span><span class="p">,</span><span class="w"> </span><span class="n">scaled_bitmap</span><span class="p">,</span><span class="w"> </span><span class="n">shape</span><span class="o">[</span><span class="n">shape</span><span class="p">.</span><span class="na">length</span><span class="o">-</span><span class="n">1</span><span class="o">]</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">}</span></span></span></code></pre></div>
<p>At this point we could either write our own native neural network , or we could use Google’s <a href="https://ai.google.dev/edge/litert">Tensorflow Lite</a> library to load a python Keras model directly onto the phone. We went with Keras for the simplicity and existing collection of examples we could reference.</p>
<p>The only downside to this approach was that because the model file could no longer be changed on the Android phone, our car would not be able to use reinforcement learning to learn as it drove on its own. Fortunately this was a sacrifice we were willing to make.</p>
<p>With a basic Keras Sequential CNN model we pumped an input image of 2500 pixels into the series of Convolution and Max Pooling layers. We then converged the model into a dense layer at the end to give us 9 categories of output. For each output we would get a confidence value of how much the car was willing to follow any of the given directions. This was done because it’s not important for the car to make fine movements, the categories we specified above were enough.</p>
<h3 id="neural-network-architecture">Neural Network Architecture</h3>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">model</span> <span class="o">=</span> <span class="n">Sequential</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">layers</span><span class="o">.</span><span class="n">Conv2D</span><span class="p">(</span><span class="mi">32</span><span class="p">,</span> <span class="n">kernel_size</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">                 <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;relu&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">                 <span class="n">input_shape</span><span class="o">=</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span><span class="mi">50</span><span class="p">,</span><span class="mi">10</span><span class="p">),</span> 
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">                 <span class="n">name</span><span class="o">=</span><span class="s1">&#39;my_layer&#39;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">convout1</span> <span class="o">=</span> <span class="n">Activation</span><span class="p">(</span><span class="s1">&#39;relu&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">convout1</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">layers</span><span class="o">.</span><span class="n">MaxPooling2D</span><span class="p">(</span><span class="n">pool_size</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)))</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">layers</span><span class="o">.</span><span class="n">Conv2D</span><span class="p">(</span><span class="mi">64</span><span class="p">,</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;relu&#39;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">convout2</span> <span class="o">=</span> <span class="n">Activation</span><span class="p">(</span><span class="s1">&#39;relu&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">convout2</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">layers</span><span class="o">.</span><span class="n">MaxPooling2D</span><span class="p">(</span><span class="n">pool_size</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)))</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">layers</span><span class="o">.</span><span class="n">Dropout</span><span class="p">(</span><span class="mf">0.25</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">layers</span><span class="o">.</span><span class="n">Flatten</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">layers</span><span class="o">.</span><span class="n">Dense</span><span class="p">(</span><span class="mi">128</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;relu&#39;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">layers</span><span class="o">.</span><span class="n">Dropout</span><span class="p">(</span><span class="mf">0.5</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">layers</span><span class="o">.</span><span class="n">Dense</span><span class="p">(</span><span class="n">numBins</span><span class="p">,</span> <span class="n">activation</span><span class="o">=</span><span class="s1">&#39;softmax&#39;</span><span class="p">))</span></span></span></code></pre></div>
<p>Above is a Keras model we used for our car. It is relatively small and the gist of it is that it converts a 50x50 array of an input image into an array of 9 confidence outputs for each of the joystick colored sectors.</p>
<p>After a few weeks of tweaking we settled on this model that worked fairly well, giving us a 95% success rate with a sizable test set of 30% of our entire training database. The laststep was to save the Keras library as a tflite file and feed it to the Interpreter on the phone.</p>
<p>Tensorflow Lite has the amazing functionality of exporting the python written model into a tflite file which can be used by a Tensorflow Lite interpreter on any other system.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">model_json</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">to_json</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">&#34;model.json&#34;</span><span class="p">,</span> <span class="s2">&#34;w&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">json_file</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">json_file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">model_json</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">keras_file</span> <span class="o">=</span> <span class="s2">&#34;model.h5&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">model</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">keras_file</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">converter</span> <span class="o">=</span> <span class="n">lite</span><span class="o">.</span><span class="n">TFLiteConverter</span><span class="o">.</span><span class="n">from_keras_model_file</span><span class="p">(</span><span class="n">keras_file</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">tflite_model</span> <span class="o">=</span> <span class="n">converter</span><span class="o">.</span><span class="n">convert</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="nb">open</span><span class="p">(</span><span class="s2">&#34;model.tflite&#34;</span><span class="p">,</span> <span class="s2">&#34;wb&#34;</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">tflite_model</span><span class="p">)</span></span></span></code></pre></div>
<p>This model is simply loaded as a TFLite interpreter object which can then use the simple run() function on an input image to create a prediction.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="n">Interpreter</span><span class="w"> </span><span class="nf">load_internal_model</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">model_name</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">        </span><span class="n">tfliteModel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">loadModelFile</span><span class="p">(</span><span class="n">model_name</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">        </span><span class="n">tflite_interpreter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Interpreter</span><span class="p">(</span><span class="n">tfliteModel</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">tflite_interpreter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="kd">private</span><span class="w"> </span><span class="n">ByteBuffer</span><span class="w"> </span><span class="nf">loadModelFile</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">model_name</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">        </span><span class="n">AssetFileDescriptor</span><span class="w"> </span><span class="n">fileDescriptor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">activity</span><span class="p">.</span><span class="na">getAssets</span><span class="p">().</span><span class="na">openFd</span><span class="p">(</span><span class="n">model_name</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">        </span><span class="n">FileInputStream</span><span class="w"> </span><span class="n">inputStream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">FileInputStream</span><span class="p">(</span><span class="n">fileDescriptor</span><span class="p">.</span><span class="na">getFileDescriptor</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">        </span><span class="n">FileChannel</span><span class="w"> </span><span class="n">fileChannel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">inputStream</span><span class="p">.</span><span class="na">getChannel</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">        </span><span class="kt">long</span><span class="w"> </span><span class="n">startOffset</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fileDescriptor</span><span class="p">.</span><span class="na">getStartOffset</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">        </span><span class="kt">long</span><span class="w"> </span><span class="n">declaredLength</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fileDescriptor</span><span class="p">.</span><span class="na">getDeclaredLength</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">fileChannel</span><span class="p">.</span><span class="na">map</span><span class="p">(</span><span class="n">FileChannel</span><span class="p">.</span><span class="na">MapMode</span><span class="p">.</span><span class="na">READ_ONLY</span><span class="p">,</span><span class="w"> </span><span class="n">startOffset</span><span class="p">,</span><span class="w"> </span><span class="n">declaredLength</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">}</span></span></span></code></pre></div>
<p>Now taking this model we can saved it into the memory of our phone and run it with the TensorFlow Interpreter to simply do a forward pass on the model.</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kt">float</span><span class="o">[][][][]</span><span class="w"> </span><span class="n">float_pixels</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">float</span><span class="o">[</span><span class="n">1</span><span class="o">][</span><span class="n">50</span><span class="o">][</span><span class="n">50</span><span class="o">][</span><span class="n">num_saved</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kt">float</span><span class="o">[][]</span><span class="w"> </span><span class="n">outputVal</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">float</span><span class="o">[</span><span class="n">1</span><span class="o">][</span><span class="n">9</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">for</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">50</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span><span class="k">for</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">50</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="o">++</span><span class="p">){</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">        </span><span class="k">for</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">num_saved</span><span class="p">;</span><span class="w"> </span><span class="n">b</span><span class="o">++</span><span class="p">){</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">            </span><span class="n">float_pixels</span><span class="o">[</span><span class="n">0</span><span class="o">][</span><span class="n">i</span><span class="o">][</span><span class="n">j</span><span class="o">][</span><span class="n">b</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="w"> </span><span class="n">int_bitmaps</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">b</span><span class="p">)</span><span class="o">[</span><span class="n">i</span><span class="o">*</span><span class="n">50</span><span class="o">+</span><span class="n">j</span><span class="o">]/</span><span class="n">255</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="k">try</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">    </span><span class="n">tflite_interpreter</span><span class="p">.</span><span class="na">run</span><span class="p">(</span><span class="n">float_pixels</span><span class="p">,</span><span class="n">outputVal</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">}</span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">Exception</span><span class="w"> </span><span class="n">e</span><span class="p">){</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">    </span><span class="n">e</span><span class="p">.</span><span class="na">printStackTrace</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="o">//</span><span class="n">outputVal</span><span class="w"> </span><span class="n">is</span><span class="w"> </span><span class="n">now</span><span class="w"> </span><span class="n">contains</span><span class="w"> </span><span class="n">confidence</span><span class="w"> </span><span class="n">values</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">sectors</span></span></span></code></pre></div>
<p>The sector with the highest confidence was taken as the action to execute by the car and finally all the pieces were in place.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="lazy" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/F036dy1oTcA?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<h3 id="conclusion">Conclusion</h3>
<p>At this point we had the car built, data collection set up and a neural network dictating the controls. The car was driving with the expertise of a 6 year old with a controller. It can safely be said that we were not winning any Grand Prix any time soon but the car was able to drive around on its own without crashing itself, with surprising reliability.</p>
<p>In any case we were happy that something that we’ve built over a semester while taking our other classes could actually learn on its own and accomplish such a difficult task, with minimal input from us. As a first project in machine learning this was a tough one to start with but looking back at it, the approach we took was in line with any other standard machine learning task.</p>
<p>If you’re still reading, hopefully you’ve learned something new and if not at least enjoyed our amateur struggles. Again, all the code is available here <a href="https://github.com/RoboticsCourse">https://github.com/RoboticsCourse</a>, please consider starring it and checking out the contributors.</p>
]]></content:encoded></item></channel></rss>