MatteoRagni/cas-rb

View on GitHub
docs/README_md.html

Summary

Maintainability
Test Coverage
<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">

<title>README - RDoc Documentation</title>

<script type="text/javascript">
  var rdoc_rel_prefix = "./";
</script>

<script src="./js/jquery.js"></script>
<script src="./js/darkfish.js"></script>

<link href="./css/fonts.css" rel="stylesheet">
<link href="./css/rdoc.css" rel="stylesheet">



<body id="top" role="document" class="file">
<nav role="navigation">
  <div id="project-navigation">
    <div id="home-section" role="region" title="Quick navigation" class="nav-section">
  <h2>
    <a href="./index.html" rel="home">Home</a>
  </h2>

  <div id="table-of-contents-navigation">
    <a href="./table_of_contents.html#pages">Pages</a>
    <a href="./table_of_contents.html#classes">Classes</a>
    <a href="./table_of_contents.html#methods">Methods</a>
  </div>
</div>

    <div id="search-section" role="search" class="project-section initially-hidden">
  <form action="#" method="get" accept-charset="utf-8">
    <div id="search-field-wrapper">
      <input id="search-field" role="combobox" aria-label="Search"
             aria-autocomplete="list" aria-controls="search-results"
             type="text" name="search" placeholder="Search" spellcheck="false"
             title="Type to search, Up and Down to navigate, Enter to load">
    </div>

    <ul id="search-results" aria-label="Search Results"
        aria-busy="false" aria-expanded="false"
        aria-atomic="false" class="initially-hidden"></ul>
  </form>
</div>

  </div>

  
<div class="nav-section">
  <h3>Table of Contents</h3>

  <ul class="link-list" role="directory">
    <li><a href="#label-Mr.CAS">Mr.CAS</a>
    <li><a href="#label-Introduction">Introduction</a>
    <li><a href="#label-Module+Structure">Module Structure</a>
    <li><a href="#label-Example">Example</a>
    <li><a href="#label-Execution">Execution</a>
    <li><a href="#label-Installation">Installation</a>
    <li><a href="#label-Define+a+function">Define a function</a>
    <li><a href="#label-Derivatives">Derivatives</a>
    <li><a href="#label-Substitutions">Substitutions</a>
    <li><a href="#label-Meta-Programming+-28a+Newton+algorithm...-29">Meta-Programming (a Newton algorithm…)</a>
    <li><a href="#label-Disclaimer">Disclaimer</a>
    <li><a href="#label-Full+example+code">Full example code</a>
    <li><a href="#label-To+do">To do</a>
    <li><a href="#label-Simple">Simple</a>
    <li><a href="#label-Complex">Complex</a>
    <li><a href="#label-Extremely+complex">Extremely complex</a>
  </ul>
</div>


  <div id="project-metadata">
    <div id="fileindex-section" class="nav-section">
  <h3>Pages</h3>

  <ul class="link-list">
  
    <li><a href="./README_md.html">README</a>
  
  </ul>
</div>

  </div>
</nav>

<main role="main" aria-label="Page README.md">

<h1 id="label-Mr.CAS">Mr.CAS<span><a href="#label-Mr.CAS">&para;</a> <a href="#top">&uarr;</a></span></h1>

<p><a href="https://badge.fury.io/rb/Mr.CAS"><img
src="https://badge.fury.io/rb/Mr.CAS.svg"></a> <a
href="https://codeclimate.com/github/MatteoRagni/cas-rb"><img
src="https://codeclimate.com/github/MatteoRagni/cas-rb/badges/gpa.svg"></a>
<a href="https://travis-ci.org/MatteoRagni/cas-rb"><img
src="https://travis-ci.org/MatteoRagni/cas-rb.svg?branch=master"></a></p>

<h2 id="label-Introduction">Introduction<span><a href="#label-Introduction">&para;</a> <a href="#top">&uarr;</a></span></h2>

<p>An extremely simple graph, that handles only differentiation and
simplification with one step ahead in the graph.</p>

<h2 id="label-Module+Structure">Module Structure<span><a href="#label-Module+Structure">&para;</a> <a href="#top">&uarr;</a></span></h2>

<p><img
src="https://gist.githubusercontent.com/MatteoRagni/639294457d97858bbb3cee2ffaf782dc/raw/2854e8877f2106307bfa190649e4253c70282139/graphviz.png"></p>

<h2 id="label-Example">Example<span><a href="#label-Example">&para;</a> <a href="#top">&uarr;</a></span></h2>

<p>Given the function of Rosenbrock, find the optimum of such a function.</p>

<h2 id="label-Execution">Execution<span><a href="#label-Execution">&para;</a> <a href="#top">&uarr;</a></span></h2>

<h3 id="label-Installation">Installation<span><a href="#label-Installation">&para;</a> <a href="#top">&uarr;</a></span></h3>

<p>First of all is necessary to install and load the <code>Mr.CAS</code> gem.</p>

<pre class="ruby"><span class="ruby-identifier">gem</span> <span class="ruby-identifier">install</span> <span class="ruby-constant">Mr</span>.<span class="ruby-constant">CAS</span>
</pre>

<pre class="ruby"><span class="ruby-identifier">require</span> <span class="ruby-string">&#39;Mr.CAS&#39;</span>
</pre>

<h3 id="label-Define+a+function">Define a function<span><a href="#label-Define+a+function">&para;</a> <a href="#top">&uarr;</a></span></h3>

<p>Now we can define the Rosenbrock function, that has two variable
(<code>x</code> and <code>y</code>) and two constants (<code>a</code> and
<code>b</code>, with the default value on 1 and 100 in this case). The
variable <code>f</code> will contain our function:</p>

<pre class="ruby"><span class="ruby-identifier">x</span>, <span class="ruby-identifier">y</span> = <span class="ruby-constant">CAS</span><span class="ruby-operator">::</span><span class="ruby-identifier">vars</span> :<span class="ruby-identifier">x</span>, :<span class="ruby-identifier">y</span>
<span class="ruby-identifier">a</span>, <span class="ruby-identifier">b</span> = <span class="ruby-constant">CAS</span><span class="ruby-operator">::</span><span class="ruby-identifier">const</span> <span class="ruby-value">1.0</span>, <span class="ruby-value">100.0</span>

<span class="ruby-identifier">f</span> = ((<span class="ruby-identifier">a</span> <span class="ruby-operator">-</span> <span class="ruby-identifier">x</span>) <span class="ruby-operator">**</span> <span class="ruby-value">2</span>) <span class="ruby-operator">+</span> <span class="ruby-identifier">b</span> <span class="ruby-operator">*</span> ((<span class="ruby-identifier">y</span> <span class="ruby-operator">-</span> (<span class="ruby-identifier">x</span> <span class="ruby-operator">**</span> <span class="ruby-value">2</span>)) <span class="ruby-operator">**</span> <span class="ruby-value">2</span>)
</pre>

<p>We can print this function as follows:</p>

<pre class="ruby"><span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;f = #{f}&quot;</span>
<span class="ruby-comment"># =&gt; ((1.0 - x)^2 + (100.0 * (y - x^2)^2))</span>
</pre>

<h3 id="label-Derivatives">Derivatives<span><a href="#label-Derivatives">&para;</a> <a href="#top">&uarr;</a></span></h3>

<p>To find the minimum we need to find the point in which the gradient of such
a function is equal to zero</p>

<p>The two derivatives are:</p>

<pre class="ruby"><span class="ruby-identifier">dfx</span> = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">diff</span>(<span class="ruby-identifier">x</span>).<span class="ruby-identifier">simplify</span>
<span class="ruby-identifier">dfy</span> = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">diff</span>(<span class="ruby-identifier">y</span>).<span class="ruby-identifier">simplify</span>

<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;df/dx = #{dfx}&quot;</span>
<span class="ruby-comment"># =&gt; df/dx = ((((1 - x) * 2) * -1) + ((((y - x^2) * 2) * -(x * 2)) * 100.0))</span>

<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;df/dy = #{dfy}&quot;</span>
<span class="ruby-comment"># =&gt; df/dy = (((y - x^2) * 2) * 100.0)</span>
</pre>

<h3 id="label-Substitutions">Substitutions<span><a href="#label-Substitutions">&para;</a> <a href="#top">&uarr;</a></span></h3>

<p>Now, from the second it is quite evident that</p>

<pre>y = x^2 = g(x)</pre>

<p>and thus we can perform on the first a substitution:</p>

<pre class="ruby"><span class="ruby-identifier">g</span> = (<span class="ruby-identifier">x</span> <span class="ruby-operator">**</span> <span class="ruby-value">2</span>)
<span class="ruby-identifier">dfx</span> = <span class="ruby-identifier">dfx</span>.<span class="ruby-identifier">subs</span>({<span class="ruby-identifier">y</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">g</span>})

<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;df/dx = #{dfx}&quot;</span>
<span class="ruby-comment"># =&gt; df/dx = (((1 - x) * 2) * -1)</span>
</pre>

<h3 id="label-Meta-Programming+-28a+Newton+algorithm...-29">Meta-Programming (a Newton algorithm…)<span><a href="#label-Meta-Programming+-28a+Newton+algorithm...-29">&para;</a> <a href="#top">&uarr;</a></span></h3>

<p>That is something quite simple to solve (x = 1). Let&#39;s use this
formulation for some meta-programming anyway! The stationary point is in
the root of the function <code>dfx</code>, that depends only on one
variable:</p>

<pre class="ruby"><span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;Arguments: #{dfx.args}&quot;</span>
</pre>

<p>We can write a Newton method. The solution is found iteratively solving the
recursive equation:</p>

<pre>x[k + 1] = x[k] - ( f(x[k]) / f&#39;(x[k]) )</pre>

<p>Let&#39;s write an algorithm that takes the symblic expression, and creates
its own method (e.g.: using <code>Proc</code> objects). Here an example
with our function:</p>

<pre class="ruby"><span class="ruby-identifier">unused</span> = (<span class="ruby-identifier">dfx</span><span class="ruby-operator">/</span><span class="ruby-identifier">dfx</span>.<span class="ruby-identifier">diff</span>(<span class="ruby-identifier">x</span>)).<span class="ruby-identifier">simplify</span>
<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;unused(x) = #{unused}&quot;</span>
<span class="ruby-comment"># =&gt; unused(x) = ((((1 - x) * 2) * -1)) / (((-1 * 2) * -1))</span>

<span class="ruby-identifier">unused_proc</span> = <span class="ruby-identifier">unused</span>.<span class="ruby-identifier">as_proc</span>
<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;unused(12.0) = #{unused.call({&quot;x&quot; =&gt; 12.0})}&quot;</span>
<span class="ruby-comment"># =&gt; unused(12.0) = 11.0</span>
</pre>

<p>First of all, let&#39;s write a function that contains the algorithm. We
want to give as input a symbolic function of one variable, it must reply
with the value of the variable in which the function as value equal to
zero:</p>

<pre class="ruby"><span class="ruby-keyword">def</span> <span class="ruby-identifier">newton</span>(<span class="ruby-identifier">f</span>, <span class="ruby-identifier">init</span>=<span class="ruby-value">3.0</span>, <span class="ruby-identifier">tol</span>=<span class="ruby-value">1E-8</span>, <span class="ruby-identifier">kmax</span>=<span class="ruby-value">100</span>)
  <span class="ruby-identifier">k</span> = <span class="ruby-value">0</span>

  <span class="ruby-identifier">x</span>   = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">args</span>[<span class="ruby-value">0</span>]
  <span class="ruby-identifier">s</span>   = {<span class="ruby-identifier">x</span>.<span class="ruby-identifier">name</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">init</span>}      <span class="ruby-comment"># &lt;-This is the solution dictionary</span>

  <span class="ruby-identifier">fp</span>  = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">as_proc</span>             <span class="ruby-comment"># &lt;- This is a parsed object</span>
  <span class="ruby-identifier">df</span>  = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">diff</span>(<span class="ruby-identifier">x</span>).<span class="ruby-identifier">simplify</span>    <span class="ruby-comment"># &lt;- This is still symbolic</span>
  <span class="ruby-identifier">res</span> = (<span class="ruby-identifier">f</span><span class="ruby-operator">/</span><span class="ruby-identifier">df</span>).<span class="ruby-identifier">as_proc</span>        <span class="ruby-comment"># &lt;- This is a parsed object</span>

  <span class="ruby-identifier">f0</span> = <span class="ruby-identifier">fp</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">s</span>)
  <span class="ruby-identifier">k</span> = <span class="ruby-value">0</span>

  <span class="ruby-identifier">loop</span> <span class="ruby-keyword">do</span>
    <span class="ruby-comment"># Algorithm</span>
    <span class="ruby-identifier">s</span>[<span class="ruby-identifier">x</span>.<span class="ruby-identifier">name</span>] = <span class="ruby-identifier">s</span>[<span class="ruby-identifier">x</span>.<span class="ruby-identifier">name</span>] <span class="ruby-operator">-</span> <span class="ruby-identifier">res</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">s</span>)
    <span class="ruby-comment"># Tolerance check</span>
    <span class="ruby-identifier">f1</span>        = <span class="ruby-identifier">fp</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">s</span>)
    <span class="ruby-keyword">if</span> (<span class="ruby-identifier">f1</span> <span class="ruby-operator">-</span> <span class="ruby-identifier">f0</span>).<span class="ruby-identifier">abs</span> <span class="ruby-operator">&lt;</span> <span class="ruby-identifier">tol</span>
      <span class="ruby-keyword">break</span>
    <span class="ruby-keyword">else</span>
      <span class="ruby-identifier">f0</span> = <span class="ruby-identifier">f1</span>
    <span class="ruby-keyword">end</span>

    <span class="ruby-comment"># Iterations check</span>
    <span class="ruby-identifier">k</span> = <span class="ruby-identifier">k</span> <span class="ruby-operator">+</span> <span class="ruby-value">1</span>
    <span class="ruby-keyword">break</span> <span class="ruby-keyword">if</span> <span class="ruby-identifier">k</span> <span class="ruby-operator">&gt;</span> <span class="ruby-identifier">kmax</span>
  <span class="ruby-keyword">end</span>
  <span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;Solution after #{k} iterations: #{x} = #{s[x.name]}, f(#{x}) = #{f0}&quot;</span>
  <span class="ruby-keyword">return</span> <span class="ruby-identifier">s</span>[<span class="ruby-identifier">x</span>.<span class="ruby-identifier">name</span>]
<span class="ruby-keyword">end</span>
</pre>

<p><strong>Transforming the symbolic function into a <code>Proc</code> makes
the code more efficient. It is not mandatory, but higlhy suggested in case
of iterative algorithms</strong>.</p>

<p>Let&#39;s call our new function, using as argument the derivative of the
function that we want to optimize:</p>

<pre class="ruby"><span class="ruby-identifier">x_opt</span> = <span class="ruby-identifier">newton</span>(<span class="ruby-identifier">dfx</span>)
<span class="ruby-comment"># =&gt; Solution after 1 iterations: x = 1.0, f(x) = -0.0</span>
</pre>

<p>We can use the solution of <code>x</code>, to get the value of
<code>y</code>:</p>

<pre class="ruby"><span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;Optimum in #{x} = #{x_opt} and #{y} = #{g.call({x =&gt; x_opt})}&quot;</span>
<span class="ruby-comment"># =&gt; Optimum in x = 1.0 and y = 1.0</span>
</pre>

<h2 id="label-Disclaimer">Disclaimer<span><a href="#label-Disclaimer">&para;</a> <a href="#top">&uarr;</a></span></h2>

<p>This is a work in progress and mainly a proof of concept. What really is
missing is a ~~graph~~ a way to perform better simplifications.</p>

<h2 id="label-Full+example+code">Full example code<span><a href="#label-Full+example+code">&para;</a> <a href="#top">&uarr;</a></span></h2>

<pre class="ruby"><span class="ruby-identifier">require</span> <span class="ruby-string">&#39;Mr.CAS&#39;</span>

<span class="ruby-comment"># Define the function</span>
<span class="ruby-identifier">x</span>, <span class="ruby-identifier">y</span> = <span class="ruby-constant">CAS</span><span class="ruby-operator">::</span><span class="ruby-identifier">vars</span> <span class="ruby-string">&quot;x&quot;</span>, <span class="ruby-string">&quot;y&quot;</span>
<span class="ruby-identifier">a</span>, <span class="ruby-identifier">b</span> = <span class="ruby-constant">CAS</span><span class="ruby-operator">::</span><span class="ruby-identifier">const</span> <span class="ruby-value">1.0</span>, <span class="ruby-value">100.0</span>

<span class="ruby-identifier">f</span> = ((<span class="ruby-identifier">a</span> <span class="ruby-operator">-</span> <span class="ruby-identifier">x</span>) <span class="ruby-operator">**</span> <span class="ruby-value">2</span>) <span class="ruby-operator">+</span> <span class="ruby-identifier">b</span> <span class="ruby-operator">*</span> ((<span class="ruby-identifier">y</span> <span class="ruby-operator">-</span> (<span class="ruby-identifier">x</span> <span class="ruby-operator">**</span> <span class="ruby-value">2</span>)) <span class="ruby-operator">**</span> <span class="ruby-value">2</span>)

<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;f = #{f}&quot;</span>

<span class="ruby-comment"># Derivate wrt variables</span>
<span class="ruby-identifier">dfx</span> = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">diff</span>(<span class="ruby-identifier">x</span>).<span class="ruby-identifier">simplify</span>
<span class="ruby-identifier">dfy</span> = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">diff</span>(<span class="ruby-identifier">y</span>).<span class="ruby-identifier">simplify</span>

<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;df/dx = #{dfx}&quot;</span>
<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;df/dy = #{dfy}&quot;</span>

<span class="ruby-comment"># Perform substitutions</span>
<span class="ruby-identifier">g</span> = (<span class="ruby-identifier">x</span> <span class="ruby-operator">**</span> <span class="ruby-value">2</span>)
<span class="ruby-identifier">dfx</span> = <span class="ruby-identifier">dfx</span>.<span class="ruby-identifier">subs</span>({<span class="ruby-identifier">y</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">g</span>}).<span class="ruby-identifier">simplify</span>
<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;df/dx = #{dfx}&quot;</span>

<span class="ruby-comment"># Arguments of a function</span>
<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;Arguments: #{dfx.args}&quot;</span>

<span class="ruby-comment"># Metaprogramming: Create a Proc from symbolic math</span>
<span class="ruby-identifier">unused</span> = (<span class="ruby-identifier">dfx</span><span class="ruby-operator">/</span><span class="ruby-identifier">dfx</span>.<span class="ruby-identifier">diff</span>(<span class="ruby-identifier">x</span>)).<span class="ruby-identifier">simplify</span>
<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;unused(x) = #{unused}&quot;</span>
<span class="ruby-identifier">unused_proc</span> = <span class="ruby-identifier">unused</span>.<span class="ruby-identifier">as_proc</span>

<span class="ruby-comment"># Testing the Proc. The feed must have string as key to identify</span>
<span class="ruby-comment"># the variable</span>
<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;unused(12.0) = #{unused.call({&quot;x&quot; =&gt; 12.0})}&quot;</span>

<span class="ruby-comment"># We will not use this function, instead we will let the</span>
<span class="ruby-comment"># algorithm to create its own</span>


<span class="ruby-comment"># Newton algorthm on the fly, that creates its own formula!</span>
<span class="ruby-keyword">def</span> <span class="ruby-identifier">newton</span>(<span class="ruby-identifier">f</span>, <span class="ruby-identifier">init</span>=<span class="ruby-value">3.0</span>, <span class="ruby-identifier">tol</span>=<span class="ruby-value">1E-8</span>, <span class="ruby-identifier">kmax</span>=<span class="ruby-value">100</span>)
  <span class="ruby-identifier">k</span> = <span class="ruby-value">0</span>

  <span class="ruby-identifier">x</span>   = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">args</span>[<span class="ruby-value">0</span>]
  <span class="ruby-identifier">s</span>   = {<span class="ruby-identifier">x</span>.<span class="ruby-identifier">name</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">init</span>}      <span class="ruby-comment"># &lt;-This is the solution dictionary</span>

  <span class="ruby-identifier">fp</span>  = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">as_proc</span>             <span class="ruby-comment"># &lt;- This is a parsed object</span>
  <span class="ruby-identifier">df</span>  = <span class="ruby-identifier">f</span>.<span class="ruby-identifier">diff</span>(<span class="ruby-identifier">x</span>).<span class="ruby-identifier">simplify</span>    <span class="ruby-comment"># &lt;- This is still symbolic</span>
  <span class="ruby-identifier">res</span> = (<span class="ruby-identifier">f</span><span class="ruby-operator">/</span><span class="ruby-identifier">df</span>).<span class="ruby-identifier">as_proc</span>        <span class="ruby-comment"># &lt;- This is a parsed object</span>

  <span class="ruby-identifier">f0</span> = <span class="ruby-identifier">fp</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">s</span>)
  <span class="ruby-identifier">k</span> = <span class="ruby-value">0</span>

  <span class="ruby-identifier">loop</span> <span class="ruby-keyword">do</span>
    <span class="ruby-comment"># Algorithm</span>
    <span class="ruby-identifier">s</span>[<span class="ruby-identifier">x</span>.<span class="ruby-identifier">name</span>] = <span class="ruby-identifier">s</span>[<span class="ruby-identifier">x</span>.<span class="ruby-identifier">name</span>] <span class="ruby-operator">-</span> <span class="ruby-identifier">res</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">s</span>)
    <span class="ruby-comment"># Tolerance check</span>
    <span class="ruby-identifier">f1</span>        = <span class="ruby-identifier">fp</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">s</span>)
    <span class="ruby-keyword">if</span> (<span class="ruby-identifier">f1</span> <span class="ruby-operator">-</span> <span class="ruby-identifier">f0</span>).<span class="ruby-identifier">abs</span> <span class="ruby-operator">&lt;</span> <span class="ruby-identifier">tol</span>
      <span class="ruby-keyword">break</span>
    <span class="ruby-keyword">else</span>
      <span class="ruby-identifier">f0</span> = <span class="ruby-identifier">f1</span>
    <span class="ruby-keyword">end</span>

    <span class="ruby-comment"># Iterations check</span>
    <span class="ruby-identifier">k</span> = <span class="ruby-identifier">k</span> <span class="ruby-operator">+</span> <span class="ruby-value">1</span>
    <span class="ruby-keyword">break</span> <span class="ruby-keyword">if</span> <span class="ruby-identifier">k</span> <span class="ruby-operator">&gt;</span> <span class="ruby-identifier">kmax</span>
  <span class="ruby-keyword">end</span>
  <span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;Solution after #{k} iterations: #{x} = #{s[x.name]}, f(#{x}) = #{f0}&quot;</span>
  <span class="ruby-keyword">return</span> <span class="ruby-identifier">s</span>[<span class="ruby-identifier">x</span>.<span class="ruby-identifier">name</span>]
<span class="ruby-keyword">end</span>

<span class="ruby-comment"># Let&#39;s call our shining algorithm:</span>
<span class="ruby-identifier">x_opt</span> = <span class="ruby-identifier">newton</span>(<span class="ruby-identifier">dfx</span>)

<span class="ruby-comment"># Let&#39;s see the final result for both:</span>
<span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;Optimum in #{x} = #{x_opt} and #{y} = #{g.call({x =&gt; x_opt})}&quot;</span>
</pre>

<h2 id="label-To+do">To do<span><a href="#label-To+do">&para;</a> <a href="#top">&uarr;</a></span></h2>

<h4 id="label-Simple">Simple<span><a href="#label-Simple">&para;</a> <a href="#top">&uarr;</a></span></h4>
<ul><li>
<p>[ ] substitute <code>CAS::Invert</code> with <code>CAS::Neg</code></p>
</li><li>
<p>[ ] substitute <code>CAS::Condition</code> with
<code>CAS::Expression</code></p>
</li><li>
<p>[x] move code generation to external plugins that can be loaded on demand</p>
</li><li>
<p>[x] <code>CAS::Sum</code> and <code>CAS::Prod</code> inherits from
<code>CAS::NaryOp</code> instead of <code>CAS::BinaryOp</code></p>
</li></ul>

<h4 id="label-Complex">Complex<span><a href="#label-Complex">&para;</a> <a href="#top">&uarr;</a></span></h4>
<ul><li>
<p>[ ] implement <code>CAS::VectorVariable</code> and
<code>CAS::MatrixVariable</code></p>
</li><li>
<p>[ ] Replace <code>CAS::Op</code> and <code>CAS::BinaryOp</code> with a
single <code>CAS::Op</code> equal to <code>CAS::NaryOp</code></p>
</li></ul>

<h5 id="label-Extremely+complex">Extremely complex<span><a href="#label-Extremely+complex">&para;</a> <a href="#top">&uarr;</a></span></h5>
<ul><li>
<p>[ ] Implement the Risch algorithms for symbolic integrations</p>
</li></ul>
</main>



<footer id="validator-badges" role="contentinfo">
  <p><a href="http://validator.w3.org/check/referer">Validate</a>
  <p>Generated by <a href="http://docs.seattlerb.org/rdoc/">RDoc</a> 4.2.1.
  <p>Based on <a href="http://deveiate.org/projects/Darkfish-RDoc/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.
</footer>