XY (solving the x's and y's of math, programming and life )2017-07-19T16:20:23+00:00https://gxyd.github.ioGaurav Dhingragauravdhingra.gxyd@gmail.comGSoC 2017: Week 62017-07-19T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2017-week-6<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}
});
</script>
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<p>We worked on <a href="https://github.com/sympy/sympy/pull/12885">Parametric logarithmic derivative PR #12885</a> only this week. So now I will get to a few mathematical points regarding the problem of “parametric logarithmic derivative” problem (will shortly write it as <code class="highlighter-rouge">PLD</code> problem).</p>
<p>The <code class="highlighter-rouge">PLD</code> problem is, for a given hyperexponential monomial <script type="math/tex">\theta</script> over a differential field <script type="math/tex">K</script> and <script type="math/tex">f \in K</script>, to decide whether there exists <script type="math/tex">n, m \in \mathbb{Z}</script> with <script type="math/tex">n \neq 0</script>, for the equation: <script type="math/tex">nf = \frac{Dv}{v} + m\frac{D\theta}{\theta}</script>, and to find one such solution.</p>
<p>There are two versions of it, the first one being the heursitic version which is quite simple (with available pseudo code) and is already implemented in SymPy, but since it doesn’t handle all the cases, it becomes necessary to have the deterministic version of it. The deterministic version is sort of used as a fallback i.e in case the heuristic version fails (raises <code class="highlighter-rouge">NotImplementedError</code>) which isn’t quite often.</p>
<p>We already have done the basic programming of it in SymPy, so before I say any further let’s see an example.</p>
<p>A simple example of where the heuristic version fails is:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>>>> fa, fd = Poly(1, x), Poly(1, x)
>>> wa, wd = Poly(1, x), Poly(1, x)
>>> DE = DifferentialExtension(extension={'D': [Poly(1, x, domain='ZZ'), Poly(t, t, domain='ZZ')], 'exts': [None, 'exp']})
>>> parametric_log_deriv_heu(fa, fd, wa, wd, DE)
None
# while the deterministic version, runs fine
>>> parametric_log_deriv(fa, fd, wa, wd, DE)
[Matrix([[-1, 1, 0]]), Matrix([[-1, 0, 1]])] # don't worry about output type
</code></pre>
</div>
<blockquote>
<h2 id="internals-of-deterministic-version">Internals of deterministic version</h2>
</blockquote>
<p>In the deterministic version we use the Risch’s structure theorem, i.e</p>
<p><script type="math/tex">\sum_{i \in \frac{L}{C(x)}} r_i Dt_i + \sum_{i \in \frac{E}{C(x)}} r_i \frac{Dt_i}{t_i} = f</script> ( equation 1)</p>
<p>where we solve for each <script type="math/tex">r_i \in \mathbb{Q}</script>.</p>
<p>This result of structure theorem is quite useful, this same theorem can be used in the process of <code class="highlighter-rouge">DifferentialExtension</code> construction, as can be seen the section 5.2 in book (Outline and Scope of Integration Algorithm, search by section name if you have a different version of the book).</p>
<p>In <code class="highlighter-rouge">PLD</code> (deterministic) we first obtain the <script type="math/tex">Dt_i</script> and <script type="math/tex">\frac{Dt_i}{t_i}</script> parts depending on ‘log’/’exp’ extension respectively and store them in a list <code class="highlighter-rouge">F</code> (the order wouldn’t matter).</p>
<p>We reorganize this problem in a way somewhat similar to <code class="highlighter-rouge">limited_integrate</code> problem, i.e <script type="math/tex">f = Dv + c_1 w_1 + c_2 w_2 + \ldots + c_m w_m</script> , we solve the problem <script type="math/tex">Dv + c_1 w_1 + c_2 w_2 + \ldots + c_m w_m + c_{m+1}f</script> and chose the one where <script type="math/tex">c_{m + 1} = -1</script>.</p>
<p>The same thing we do here in this problem, but that does cause some problem as <script type="math/tex">f</script> may not necesarily be contained in the extension <script type="math/tex">K(\theta)</script>, and currently we are working on solving this part of the problem, Kalevi suggests to take the unfinished <code class="highlighter-rouge">DE</code> object and the extension containing <script type="math/tex">f</script> could be built on that.(No need to start from scratch.)</p>
<p>I haven’t mentioned much regarding the function that does the working for converting the relation in eq (1) over a field <script type="math/tex">K</script> to one over <script type="math/tex">\mathbb{Q}</script>. It contains <code class="highlighter-rouge">Poly</code> manipulation methods to do that. It does mathematically the same thing as “to obtain a system with coefficients in C and the same constant solutions.”</p>
<p>I’ll complete the <code class="highlighter-rouge">parametric_log_deriv</code> before the next week starts.</p>
GSoC 2017: Week 52017-07-12T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2017-week-5<p>We started working on implementation of <a href="https://github.com/sympy/sympy/pull/12885">parametric logarithmic derivative problem using Risch structure Theorem</a>. First we implemented the function <code class="highlighter-rouge">basis_Q</code>, which seems like we wouldn’t be needing no-more. While doing that it seemed like there was problem with the <code class="highlighter-rouge">.is_algebraic</code> property, as it was returning <code class="highlighter-rouge">(pi**3).is_algebraic</code> as True. This bug was fixed in the pull request <a href="https://github.com/sympy/sympy/pull/12924">#12924</a>.</p>
<p>Also a few improvements to the <a href="https::/github.com/sympy/sympy/pull/12925">integral module pull request #12925</a> was also merged.</p>
<p>I don’t have much to say for now, until I complete the parametric logarithmic derivate PR.</p>
GSoC 2017: Week 42017-07-04T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2017-week-4<p>This week we completed <b><a href="https://github.com/sympy/sympy/pull/12850" color="purple">PR #12850]()</a></b> on adding/removing variable in <code class="highlighter-rouge">DifferentialExtension</code> class for later introduction of creating extensions of <script type="math/tex">\tan</script>, <script type="math/tex">\atan</script>, and probably algebraic extensions as well. Lists like <code class="highlighter-rouge">E_K</code>, <code class="highlighter-rouge">L_K</code> and the new ones have been combined in a single list one, and the variables to record that information are <code class="highlighter-rouge">exts</code> and <code class="highlighter-rouge">extargs</code>. <code class="highlighter-rouge">exts</code> will store <code class="highlighter-rouge">str</code> instances having value in {‘exp’, ‘log’, ‘atan’, ‘tan’, ‘alg’}, so whenever we at each ‘level’ earlier we discovered the extension to be exponential we appended <code class="highlighter-rouge">level - 1</code> to the list <code class="highlighter-rouge">E_K</code> (i.e. index) or to <code class="highlighter-rouge">L_K</code> when the extension is <code class="highlighter-rouge">primitive</code> but now we will append to just a single list and i.e. to <code class="highlighter-rouge">exts</code> either <code class="highlighter-rouge">exp</code> or <code class="highlighter-rouge">log</code>/<code class="highlighter-rouge">atan</code> accordingly (Note: <script type="math/tex">\atan</script> is also a <code class="highlighter-rouge">primitive</code> until now, the only ‘primitive’ has been ‘log’). First argument of both of lists (<code class="highlighter-rouge">exts</code> and <code class="highlighter-rouge">extargs</code>) is currently kept as <code class="highlighter-rouge">None</code>(owing to keep the code clean).</p>
<p>While <code class="highlighter-rouge">extargs</code> as is clear from the name stores the argument of extension. Well, it seems odd what the meaing of <code class="highlighter-rouge">args</code> will be for the algebraic case, I am guessing a tuple (base, exp), but we needn’t worry about that for now.</p>
<p>We also have an open pull request on some re-organising of <code class="highlighter-rouge">__init__</code> of <code class="highlighter-rouge">DifferentialExtension</code> <a href="https://github.com/sympy/sympy/pull/12849">#12849</a>. It isn’t blocking anything. I think that PR is done.</p>
<blockquote>
<h3 id="key-points">Key points</h3>
</blockquote>
<p>What seems important to me is that I can list some of the discussion key points here, since I need to those issues to be solved in my mind, in particular I often go back and look at the archives of gitter discussion.</p>
<ol>
<li>
<p>Aaron mention about the issue in <code class="highlighter-rouge">is_deriv_k</code> (also present in <code class="highlighter-rouge">is_log_deriv_k_t_radical</code>), which prevent integrals of the form <script type="math/tex">\int {\exp(ax) \exp(bx)} dx</script>, and it raises <code class="highlighter-rouge">NotImplementedError: Cannot work with non-rational coefficients in this case.</code>. Now this problem can be solved with the use of Risch structure Theorem (yes, with capital <code class="highlighter-rouge">R</code>, small <code class="highlighter-rouge">s</code> and capital <code class="highlighter-rouge">T</code>, it comes to my mind whenever I see the name in the text, IIRC last time summers I was corrected Kalevi regarding <code class="highlighter-rouge">Todd Coxeter</code>, may be someone else).</p>
</li>
<li>
<p>Using the paper on “Simplification of Real Elementary Functions” (already mentioned in last blog post).</p>
</li>
</ol>
<blockquote>
<h3 id="todo">TODO</h3>
<p>Now coming to what I am currently doing is reading the text for <code class="highlighter-rouge">parametric_log_deriv</code> (there isn’t pseudo code of this). I think it would take me about 2 weeks to complete this task, by that time my next semester in university will start as well (on 15th July)</p>
</blockquote>
<p>This time I am late for my blog post, damn!. Aaron had to mail me for the post, SymPy has a Code Generation workshop in the upcoming SciPy conference (probably 9th of this month), and also we are going to have a release of SymPy 1.1 coming out soon, I guess that is handling quite a bit.</p>
<p>Oh, I forgot to mention, I passed the first evaluation as well.</p>
GSoC Week 32017-06-25T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2017-week-3<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}
});
</script>
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<blockquote>
<h2 id="rischs-structure-theorems">Risch’s structure theorem’s</h2>
</blockquote>
<p>For the next couple of weeks we will be moving to understand and implement the Risch’s structure theorem and applications that we will make use of in gsoc project. One of the application is that of “Simplification of real elementary functions”, a paper by Manuel Bronstein (in 1989)<sup>[1]</sup>. This paper by Bronstein uses Risch’s real structure theorem, the paper determines explicitly all algebraic relations among a set of real elementary functions.</p>
<blockquote>
<h3 id="simplification-of-real-elementary-functions">Simplification of Real Elementary Functions</h3>
</blockquote>
<p>Risch in 1979 gave a theorem and an algorithm that found explicitly all algebraic relations among a set of only <script type="math/tex">\log</script>’s and <script type="math/tex">\exp</script>’s. And to apply this algorithm required to convert trigonometric functions to <script type="math/tex">\log</script>’s and <script type="math/tex">\exp</script>’s.</p>
<p>Consider the integrand <script type="math/tex">f = \frac{\tan ^2(\arctan(x)/3) + 1}{x^2 + 1}</script>. For this first we make use of <script type="math/tex">\log</script> form of <script type="math/tex">\arctan</script>, i.e <script type="math/tex">\arctan(x) = \frac{1}{2I} \log(\frac{1 + Ix}{1 - Ix})</script>. Substituting it in the original expression we get <script type="math/tex">\frac{\sec^2 (\frac{1}{6I} \log(\frac{1 + Ix}{1 - Ix}))}{x^2 + 1}</script>. Now using the exponential form of <script type="math/tex">\sec</script> we get <script type="math/tex">\frac{4}{x^2 + 1} (\frac{1}{[(\frac{1 + Ix}{1 - Ix})^{1/6} + (\frac{1 + Ix}{1 - Ix})^{-1/6}]})^2</script>.
And substituting <script type="math/tex">\sqrt \alpha</script> in place of <script type="math/tex">(\frac{1 + Ix}{1 - Ix})^{1/6}</script> we get the final expression. <script type="math/tex">f = \frac{4 \alpha}{(x^2 + 1)(\alpha + 1)^2}</script>, which is a complex algebraic function.</p>
<p>All of this could be avoided since the original function <script type="math/tex">f = \frac{\tan ^2(\arctan(x)/3) + 1}{x^2 + 1}</script> is a real algebraic function. The part that could be a problem to see it is <script type="math/tex">\tan(\arctan(x)/3)</script>, which can be seen to satisfy the algebraic equation <script type="math/tex">y^3 - 3y^2 x - 3y + x = 0</script> using the formula for <script type="math/tex">\tan(3\theta)</script>. Bronstein discusses the algorithm that wouldn’t require the use of complex <script type="math/tex">\log</script>’s and <script type="math/tex">\exp</script>’s.</p>
<p>A function <script type="math/tex">\theta</script> is called real elementary over a differential field <script type="math/tex">k</script>, if for a differential extension <script type="math/tex">K</script> (<script type="math/tex">\theta \in K</script>) of <script type="math/tex">k</script>. If either <script type="math/tex">\theta</script> is algebraic over <script type="math/tex">k</script> or it is <script type="math/tex">\exp</script>, <script type="math/tex">\log</script>, <script type="math/tex">\tan</script>, <script type="math/tex">\arctan</script> of an element of <script type="math/tex">k</script> (consider this recursively).
For example: <script type="math/tex">\log(x)</script> is real elementary over <script type="math/tex">\mathbb{Q}(x)</script>, so is <script type="math/tex">\log(\log(x))</script> and <script type="math/tex">\log(\exp(x) + \tan(x))</script>.</p>
<p>Point to mention here is, we have to explicitly include <script type="math/tex">\tan</script>, <script type="math/tex">\arctan</script>, since we don’t want the function to be a complex function by re-writing <script type="math/tex">\tan(x)</script> as <script type="math/tex">\log</script>, <script type="math/tex">\exp</script> form(<script type="math/tex">\tan</script> and <script type="math/tex">\arctan</script> can be written in form of complex <script type="math/tex">\log</script> and <script type="math/tex">\exp</script> respectively), and we can write other trigonometric functions have real elementary relations with <script type="math/tex">\tan</script> and <script type="math/tex">\arctan</script>. Alone <script type="math/tex">\tan</script> or alone <script type="math/tex">\arctan</script> can’t do the job.</p>
<p>This way we can form the definition of a <em>real-elementary extension of a differential field</em> <script type="math/tex">k</script>.</p>
<blockquote>
<h3 id="functions-currently-using-approach-of-structure-theorems-in-sympy">Functions currently using approach of structure theorems in SymPy</h3>
</blockquote>
<p>Moving on, let us now look at the three functions in SymPy that use the structure theorem “approach”:</p>
<ol>
<li>
<p><code class="highlighter-rouge">is_log_deriv_k_t_radical(fa, fd, DE)</code>: Checks if <script type="math/tex">Df</script> is the logarithmic derivative of a <code class="highlighter-rouge">k(t)-radical</code>. Mathematically <script type="math/tex">Df = \frac{1}{n} \frac{Da}{a}</script> where <script type="math/tex">a \in k</script>, <script type="math/tex">n \in \mathbb{Z}</script>. In naive terms if <script type="math/tex">f = \log(\sqrt[n]{a}) \Rightarrow Df = \frac{1}{n} \frac{Da}{a}</script>. Here <code class="highlighter-rouge">k(t)-radical</code> means <code class="highlighter-rouge">n-th</code> roots of element of <script type="math/tex">k</script>. Used in process of calculating DifferentialExtension of an object where ‘case’ is ‘exp’.</p>
</li>
<li>
<p><code class="highlighter-rouge">is_log_deriv_k_t_radical_in_field(fa, fd, DE)</code>: Checks if <script type="math/tex">f</script> is the logarithmic derivative of a <code class="highlighter-rouge">k(t)-radical</code>. Mathematically <script type="math/tex">f = \frac{1}{n} \frac{Da}{a}</script> where <script type="math/tex">a \in k</script>, <script type="math/tex">n \in \mathbb{Z}</script>. It may seem like it is just the same as above with <code class="highlighter-rouge">f</code> given as input instead of having to calculate <script type="math/tex">Df</script>, but the “in_field” part in function name is important.</p>
</li>
<li>
<p><code class="highlighter-rouge">is_deriv_k</code>: Checks if <script type="math/tex">Df/f</script> is the derivative of a k(t), i.e. <script type="math/tex">Df/f = Db</script> where <script type="math/tex">b \in k(t) \Rightarrow \log(f) = b</script>.</p>
</li>
</ol>
<blockquote>
<h3 id="what-have-i-done-this-week">What have I done this week?</h3>
</blockquote>
<p>Moving onto what I have been doing for the last few days (at a very slow pace) went through a debugger for understanding the working of <code class="highlighter-rouge">DifferentialExtension(exp(x**2/2) + exp(x**2), x)</code> in which <code class="highlighter-rouge">integer_powers</code> function is currently used to determine the relation <script type="math/tex">t_{0} = \exp(x^2/2)</script> and <script type="math/tex">t_{0}^2 = \exp(x^2)</script>, instead of <script type="math/tex">t_{0} = \exp(x^2)</script> and <script type="math/tex">\sqrt {t_{0}} = \exp(x^2/2)</script>, since we can’t handle algebraic extensions currently (that will hopefully come later in my gsoc project). Similar example for <script type="math/tex">\log</script> is there in the book <script type="math/tex">f = \log(x) \log(x + 1) \log(2x^2 + 2x)</script>, though the difference is it uses the <code class="highlighter-rouge">is_deriv_k</code> (for <code class="highlighter-rouge">case == 'primitive'</code>, we have <code class="highlighter-rouge">is_log_deriv_k_t_radical</code> for case == ‘exp’) to reach the conclusion that <script type="math/tex">t_{0} = \log(x)</script>, <script type="math/tex">t_{1} = \log(x + 1)</script> and <script type="math/tex">\log(2x^2 + 2 x) = t_0 + t_1 + \log(2)</script>.</p>
<p>I still have to understand the structure theorem, for what they are? and how exactly they are used. According to Aaron, Kalevi, I should start reading the source of <code class="highlighter-rouge">is_deriv_k</code>, <code class="highlighter-rouge">is_log_deriv_k_t_radical</code> and <code class="highlighter-rouge">parametric_log_deriv</code> functions in prde.py file.</p>
<p>We worked on <a href="https://github.com/sympy/sympy/pull/12743">#12743 Liouvillian case for Parametric Risch Diff Eq.</a> this week, it handles liouvillian cancellation cases. It enables us to handle integrands like <script type="math/tex">f = \log(\frac{x}{\exp(x)} + 1)</script>.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>>>> risch_integrate(log(x/exp(x) + 1), x)
(x*log(x*exp(-x) + 1) + NonElementaryIntegral((x**2 - x)/(x + exp(x)), x))
</code></pre>
</div>
<p>earlier it used to raise error <code class="highlighter-rouge">prde_cancel()</code> not implemented. After testing it a bit I realised that part of returned answer could be further integrated instead of being returned as a <code class="highlighter-rouge">NonElementaryIntegral</code>. Consider this</p>
<div class="highlighter-rouge"><pre class="highlight"><code>In [4]: risch_integrate(x + exp(x**2), x)
Out[4]: Integral(x + exp(x**2), x)
</code></pre>
</div>
<p>as can be easily seen it can be further integrated. So Aaron opened the issue <a href="https://github.com/sympy/sympy/issues/12779">#12779 Risch algorithm could split out more nonelementary cases</a>.</p>
<p>Though I am not sure why Kalevi has still not merged the <code class="highlighter-rouge">liouvillian</code> PR (only a comment needs to be fixed <code class="highlighter-rouge">n=2</code> -> <code class="highlighter-rouge">n=5</code> in a comment), though that PR is not blocking me from doing further work.</p>
<p>Starting tomorrow (26th) we have the first evaluation of GSoC. Anyways I don’t like the idea of having 3 evaluations.</p>
<blockquote>
<h3 id="todo-for-the-next-week">TODO for the next week:</h3>
</blockquote>
<p>Figuring out and implementing the structure theorems.</p>
<blockquote>
<h3 id="references">References</h3>
</blockquote>
<ul>
<li>{1}. Simplification of real elementary functions, http://dl.acm.org/citation.cfm?id=74566</li>
</ul>
GSoC Week 22017-06-14T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2017-week-2<p>After the Kalevi’s comment</p>
<blockquote>
<p>The param-rde branch is getting inconveniently big for hunting down and reviewing small changes. I think we should create another branch that would contain my original PR plus the added limited_integrate code (and optionally something else). Then that should be merged. Thereafter it would be easier to review new additions.</p>
</blockquote>
<p>I decided to remove a few commits from top of <code class="highlighter-rouge">param-rde</code> branch and made the branch <code class="highlighter-rouge">param-rde</code> mergeable.</p>
<p>Yesterday Kalevi merged the pull request <a href="https://github.com/sympy/sympy/pull/11761">#11761, Parametric Risch differentia equation</a>, there were quite a few problems(unrelated to my work) with travis but finally it passes the tests.</p>
<p>So till now these are pull requests that have been completed/started for my project:</p>
<ul>
<li>
<font color="green">Merged:</font>
<p><a href="https://github.com/sympy/sympy/pull/11761">param-rde #11761</a>: This is the pull request that Kalevi made back in september 2016. I further made commits for <code class="highlighter-rouge">limited_integration</code> function, implementation of parametric risch differential equation, though not many tests were added in this, which should definitely be done. I haven’t been able to find tests that lead to non-cancellation cases (Kalevi mentions that we should be able to find them), so for the time being we decided to start the implementation of cancellation routines, particularly liouvillian cases (others being non-linear and hypertangent cases), there isn’t a good reason to implement the hypertangent cases right now.</p>
</li>
<li>
<font color="red">Unmerged:</font>
<p><a href="https://github.com/sympy/sympy/pull/12734">param-rde_polymatrix</a> this pull request is intended to use <code class="highlighter-rouge">PolyMatrix</code> instead of <code class="highlighter-rouge">Matrix</code> (it is <code class="highlighter-rouge">MutableDenseMatrix</code>), here is Kalevi’s comment regarding it: “It would also be possible to use from … import PolyMatrix as Matrix. That would hint that there might be a single matrix in the future.”. The reason for making is <code class="highlighter-rouge">Matrix</code> doesn’t play well with <code class="highlighter-rouge">Poly</code>(or related) elements.</p>
</li>
<li>
<font color="green">Merged:</font>
<p><a href="https://github.com/sympy/sympy/pull/12727">Change printing of DifferentialExtension object</a>, it wasn’t necessary to make this pull request, but it does help me in debugging the problems a little easier.</p>
</li>
</ul>
<p>I was hoping that I would write a bit of mathematics in my blog posts, but unfortunately things I have dealt with till now required me to focus on programming API, introducing <code class="highlighter-rouge">PolyMatrix</code> so it deals well with the elements of <code class="highlighter-rouge">Poly</code>’s, but I am thinking this week I am going to deal with more of mathematics.</p>
<blockquote>
<h2 id="todo-for-this-week">TODO for this week</h2>
</blockquote>
<ul>
<li>Complete the cancellation liouvillian cases. I just sent the pull request for it <a href="https://github.com/sympy/sympy/pull/12743">Liouvillian cases for Parametric Risch differential equation #12743</a>. I really need to catch with the core of things, do it a little quick.</li>
</ul>
<p>I hope the next blog post is going to be a good mathematical one :)</p>
GSoC 2017: Symbolic Integration2017-05-24T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2017-with-sympy<p>GSoC 2017: Symbolic Integration</p>
<p>I applied for Google Summer of Code again this year, and my project on symbolic integration has been accepted. Like last year, my mentors are <a href="https://github.com/asmeurer">Aaron Meurer</a>(SymPy lead developer) and <a href="https://github.com/jksuom">Kalevi Suominen</a>. The proposal I submitted can be found here <a href="https://github.com/sympy/sympy/wiki/GSoC-2017-Application-Gaurav-Dhingra:-Risch-algorithm-for-symbolic-integration">GSoC 2017 proposal: Symbolic Integration</a>.</p>
<ul>
<li>
<p>Aaron himself worked on Symbolic Integration in GSoC 2010, and he started the implementation of transcendental functions integration and a good part of transcendental function integration was done (main resource being <em>Symbolic Integration I: Transcendental Function by Manuel Bronstein</em>).</p>
</li>
<li>
<p>Then in the year 2013, Chetna Gupta continued work on transcendental function integration as a part of her GSoC project. And still some part of transcendental function integration remains.</p>
</li>
<li>
<p>I have liked to mention one of ‘things’ with the current integration module is sometime people get deceived with the results. Consider the integration of function <em>1/(x<strong>2 + a</strong>2)</em>. Most of would expect the output to be <em>atan(x/a)/a</em>. But with SymPy we get:</p>
</li>
</ul>
<p>Example:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>In [11]: integrate(1/(x**2 + a**2), x)
Out[11]: (-I*log(-I*a + x)/2 + I*log(I*a + x)/2)/a
</code></pre>
</div>
<p>which for a moment looks wrong, but actually the answer returned by SymPy is
not wrong (or is actually right mathematically). Since the answer returned by
SymPy is logarithmic form of <em>atan</em>.</p>
<p><code class="highlighter-rouge">$atan(x) = I*log((-I*x + 1)/(I*x + 1))/2$</code></p>
<p>Now the comes the main part, what would I be working on? The first main thing on
which I will be working on is:</p>
<ol>
<li>Completing the work on transcendental function integration: which includes</li>
</ol>
<ul>
<li>
<p>writing a lot of tests for functions present in prde.py (Parametric Risch
Differential Equation), rde.py (Risch differential equation).</p>
</li>
<li>
<p>working on trigonometric extensions.
example:</p>
</li>
</ul>
<div class="language-python highlighter-rouge"><pre class="highlight"><code>
<span class="n">In</span> <span class="p">[</span><span class="mi">1</span><span class="p">]:</span> <span class="kn">from</span> <span class="nn">sympy</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">2</span><span class="p">]:</span> <span class="kn">from</span> <span class="nn">sympy.integrals.risch</span> <span class="kn">import</span> <span class="n">risch_integrate</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">3</span><span class="p">]:</span> <span class="n">risch_integrate</span><span class="p">(</span><span class="n">sin</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">x</span><span class="p">)</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="n">File</span> <span class="s">"/home/gxyd/foss/sympy/sympy/integrals/risch.py"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1677</span><span class="p">,</span> <span class="ow">in</span> <span class="n">risch_integrate</span>
<span class="n">dummy</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">rewrite_complex</span><span class="o">=</span><span class="n">rewrite_complex</span><span class="p">)</span>
<span class="n">File</span> <span class="s">"/home/gxyd/foss/sympy/sympy/integrals/risch.py"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">234</span><span class="p">,</span> <span class="ow">in</span> <span class="n">__init__</span>
<span class="k">raise</span> <span class="nb">NotImplementedError</span><span class="p">(</span><span class="s">"Trigonometric extensions are not "</span>
<span class="nb">NotImplementedError</span><span class="p">:</span> <span class="n">Trigonometric</span> <span class="n">extensions</span> <span class="n">are</span> <span class="ow">not</span> <span class="n">supported</span> <span class="p">(</span><span class="n">yet</span><span class="err">!</span><span class="p">)</span>
</code></pre>
</div>
<p>as you can see it raises the <strong>NotImplementedError</strong>. It doesn’t mean
that SymPy can’t evaluate the integral of simple function like <em>sin(x)</em>.</p>
<div class="highlighter-rouge"><pre class="highlight"><code> ```
In 1: from sympy import *
In [2]: integrate(sin(x), x)
Out[2]: -cos(x)
```
</code></pre>
</div>
<p>Since I have started using PDb as a debugger (thanks to Kalevi) instead
of the primitive <strong>print</strong> command. I will now explain how a function like
<em>sin(x)</em> is currently integrated.</p>
<blockquote>
<h3 id="pdb-working-with-integration">Pdb working with integration</h3>
</blockquote>
<ul>
<li>First go into SymPy’s root directory and start the IPython or bin/isympy session.</li>
<li>Then import pdb module into your session with <em>import pdb</em>.</li>
<li>Import the function from the tests file which you want to debug/analyse with
command for example in my I will be importing test case from the integral module’s
test directory with <em>from sympy.integrals.tests.test_integrals import test_halo</em></li>
</ul>
<p>PDb important commands: You can use as command the word outside the bracket or
including the one outside bracket with word inside it.</p>
<p>s(tep): You can either type <em>s</em> or <em>step</em> on PDb command prompt (i.e. (Pdb)),
this command is often used to look into its execution. Whenever you find
something interesting (function or class) use this command.</p>
<p>b(reak): setting a break point. Often executed in conjunction with <em>continue</em>, it
sets a breakpoint (see wiki article for it). An example would be its usage
in seeing the execution of <i>DifferentialExtension</i> object.
Example: (Pdb) b sympy/integrals/risch.py:196
Breakpoint 1 at /home/gxyd/foss/sympy/sympy/integrals/risch.py:19</p>
<p>c(ont(inue)): Often used in conjunction with <i>break</i> command. It continues the
execution i.e. doesn’t show any command(or code) on Pdb until the Pdb
hits the set breakpoint or the function returns something to the main
IPython session as output.</p>
<p>n(ext): continue to the next line.
l(ist): shows a limited source code of current line execution.
p: prints the object. Used in printing of variable/object value.</p>
<p>There are many more commands like <i>j</i>, <i>w</i>, which I haven’t used often.
(For broader and good understanding of these commands use the trivial ?x where <i>x</i>
is the command under consideration).</p>
<blockquote>
<h4 id="an-example-session">An example session:</h4>
</blockquote>
<div class="highlighter-rouge"><pre class="highlight"><code>gxyd@stallman:~/foss/sympy$ bin/isympy
IPython console for SymPy 1.0.1.dev (Python 3.6.0-64-bit) (ground types: python)
These commands were executed:
>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)
>>> init_printing()
Documentation can be found at http://docs.sympy.org/dev
In [1]: import pdb
In [2]: from sympy.integrals.tests.test_integrals import test_halo
In [3]: pdb.run('test_halo()')
> <string>(1)<module>()
(Pdb) s
--Call--
> /home/gxyd/foss/sympy/sympy/integrals/tests/test_integrals.py(1182)test_halo()
-> def test_halo():
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/tests/test_integrals.py(1183)test_halo()
-> from sympy.abc import x
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/tests/test_integrals.py(1184)test_halo()
-> assert integrate(sin(x), x) == -cos(x)
(Pdb) s
--Call--
> /home/gxyd/foss/sympy/sympy/core/basic.py(105)__hash__()
-> def __hash__(self):
(Pdb) b sympy/integrals/integrals.py:1287
Breakpoint 1 at /home/gxyd/foss/sympy/sympy/integrals/integrals.py:1287
(Pdb) c
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(1287)integrate()
-> meijerg = kwargs.pop('meijerg', None)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(1288)integrate()
-> conds = kwargs.pop('conds', 'piecewise')
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(1289)integrate()
-> risch = kwargs.pop('risch', None)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(1290)integrate()
-> manual = kwargs.pop('manual', None)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(1291)integrate()
-> integral = Integral(*args, **kwargs)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(1293)integrate()
-> if isinstance(integral, Integral):
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(1294)integrate()
-> return integral.doit(deep=False, meijerg=meijerg, conds=conds,
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(1295)integrate()
-> risch=risch, manual=manual)
(Pdb) s
--Call--
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(354)doit()
-> def doit(self, **hints):
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(374)doit()
-> if not hints.get('integrals', True):
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(377)doit()
-> deep = hints.get('deep', True)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(378)doit()
-> meijerg = hints.get('meijerg', None)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(379)doit()
-> conds = hints.get('conds', 'piecewise')
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(380)doit()
-> risch = hints.get('risch', None)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(381)doit()
-> manual = hints.get('manual', None)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(383)doit()
-> if conds not in ['separate', 'piecewise', 'none']:
(Pdb) p conds
'piecewise'
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(387)doit()
-> if risch and any(len(xab) > 1 for xab in self.limits):
(Pdb) p risch
None
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(391)doit()
-> if self.is_zero:
(Pdb) p self
Integral(sin(x), x)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(395)doit()
-> function = self.function
(Pdb) p self.function
sin(x)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(396)doit()
-> if deep:
(Pdb) p deep
False
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(398)doit()
-> if function.is_zero:
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(401)doit()
-> if isinstance(function, MatrixBase):
(Pdb) p function
sin(x)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(406)doit()
-> undone_limits = []
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(408)doit()
-> ulj = set()
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(409)doit()
-> for xab in self.limits:
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(412)doit()
-> if len(xab) == 1:
(Pdb) p self.limits
((x,),)
(Pdb) p xab
(x,)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(413)doit()
-> uli = set(xab[:1])
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(422)doit()
-> if xab[0] in ulj or any(v[0] in uli for v in undone_limits):
(Pdb) p uli
{x}
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(438)doit()
-> def try_meijerg(function, xab):
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(462)doit()
-> meijerg1 = meijerg
(Pdb) p meijerg
None
(Pdb) p xab
(x,)
(Pdb) l
457 ret = f, cond
458 else:
459 ret = f
460 return ret
461
462 -> meijerg1 = meijerg
463 if len(xab) == 3 and xab[1].is_real and xab[2].is_real \
464 and not function.is_Poly and \
465 (xab[1].has(oo, -oo) or xab[2].has(oo, -oo)):
466 ret = try_meijerg(function, xab)
467 if ret is not None:
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(463)doit()
-> if len(xab) == 3 and xab[1].is_real and xab[2].is_real \
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(480)doit()
-> if meijerg1 is False and meijerg is True:
(Pdb) p meijerg1
None
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(483)doit()
-> antideriv = self._eval_integral(
(Pdb) p self.
*** SyntaxError: unexpected EOF while parsing
(Pdb) p self
Integral(sin(x), x)
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(484)doit()
-> function, xab[0],
(Pdb) s
--Call--
> /home/gxyd/foss/sympy/sympy/core/containers.py(40)__getitem__()
-> def __getitem__(self, i):
(Pdb) s
> /home/gxyd/foss/sympy/sympy/core/containers.py(41)__getitem__()
-> if isinstance(i, slice):
(Pdb) r
--Return--
> /home/gxyd/foss/sympy/sympy/core/containers.py(44)__getitem__()->x
-> return self.args[i]
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(485)doit()
-> meijerg=meijerg1, risch=risch, manual=manual,
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(486)doit()
-> conds=conds)
(Pdb) s
--Call--
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(651)_eval_integral()
-> def _eval_integral(self, f, x, meijerg=None, risch=None, manual=None,
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(735)_eval_integral()
-> from sympy.integrals.deltafunctions import deltaintegrate
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(736)_eval_integral()
-> from sympy.integrals.singularityfunctions import singularityintegrate
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(737)_eval_integral()
-> from sympy.integrals.heurisch import heurisch, heurisch_wrapper
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(738)_eval_integral()
-> from sympy.integrals.rationaltools import ratint
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(739)_eval_integral()
-> from sympy.integrals.risch import risch_integrate
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(741)_eval_integral()
-> if risch:
(Pdb) p risch
None
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(747)_eval_integral()
-> if manual:
(Pdb) p manual
None
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(762)_eval_integral()
-> if isinstance(f, Poly) and not meijerg:
(Pdb) p f
sin(x)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(766)_eval_integral()
-> if f.func is Piecewise:
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(770)_eval_integral()
-> if not f.has(x):
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(774)_eval_integral()
-> poly = f.as_poly(x)
(Pdb) p sin(x).as_poly(x)
*** NameError: name 'sin' is not defined
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(775)_eval_integral()
-> if poly is not None and not meijerg:
(Pdb) p poly
None
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(778)_eval_integral()
-> if risch is not False:
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(779)_eval_integral()
-> try:
(Pdb) p risch
None
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(780)_eval_integral()
-> result, i = risch_integrate(f, x, separate_integral=True, conds=conds)
(Pdb) s
--Call--
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(1569)risch_integrate()
-> def risch_integrate(f, x, extension=None, handle_first='log',
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(1674)risch_integrate()
-> f = S(f)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(1676)risch_integrate()
-> DE = extension or DifferentialExtension(f, x, handle_first=handle_first,
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(1677)risch_integrate()
-> dummy=True, rewrite_complex=rewrite_complex)
(Pdb) s
--Call--
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(165)__init__()
-> def __init__(self, f=None, x=None, handle_first='log', dummy=False, extension=None, rewrite_complex=False):
(Pdb) s
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(196)__init__()
-> if extension:
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(206)__init__()
-> elif f is None or x is None:
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(210)__init__()
-> from sympy.integrals.prde import is_deriv_k
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(212)__init__()
-> if handle_first not in ['log', 'exp']:
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(218)__init__()
-> self.f = f
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(219)__init__()
-> self.x = x
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(221)__init__()
-> self.dummy = dummy
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(222)__init__()
-> self.reset()
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(223)__init__()
-> exp_new_extension, log_new_extension = True, True
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(224)__init__()
-> if rewrite_complex:
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(233)__init__()
-> if any(i.has(x) for i in self.f.atoms(sin, cos, tan, atan, asin, acos)):
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(234)__init__()
-> raise NotImplementedError("Trigonometric extensions are not "
(Pdb) n
NotImplementedError: Trigonometric extensions are not supported (yet!)
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(234)__init__()
-> raise NotImplementedError("Trigonometric extensions are not "
(Pdb) n
--Return--
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(234)__init__()->None
-> raise NotImplementedError("Trigonometric extensions are not "
(Pdb) n
NotImplementedError: Trigonometric extensions are not supported (yet!)
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(1677)risch_integrate()
-> dummy=True, rewrite_complex=rewrite_complex)
(Pdb) n
--Return--
> /home/gxyd/foss/sympy/sympy/integrals/risch.py(1677)risch_integrate()->None
-> dummy=True, rewrite_complex=rewrite_complex)
(Pdb) n
NotImplementedError: Trigonometric extensions are not supported (yet!)
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(780)_eval_integral()
-> result, i = risch_integrate(f, x, separate_integral=True, conds=conds)
(Pdb) n
> /home/gxyd/foss/sympy/sympy/integrals/integrals.py(781)_eval_integral()
-> except NotImplementedError:
</code></pre>
</div>
<div class="highlighter-rouge"><pre class="highlight"><code> As you can see it raise *NotImplemenedError* for forming the *DifferentialExtension*
object for function f = *sin(x)*.
I will leave it here, I think it wouldn't be an issue to continue from here.
</code></pre>
</div>
<blockquote>
<h3 id="todo">TODO</h3>
</blockquote>
<p>I am still trying to make a call to <em>param_rischDE</em> in the function <em>limited_integration</em>. I will write more about this in my next blog, hopefully(a big hope here from me, I have been stuck here for quite sometime and frustrated about it) will have completed this task by then.</p>
GSoC 2016 Summary2016-11-30T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2016-summary<p>Below is the summary:</p>
<p><a href="https://github.com/gxyd">Gaurav Dhingra</a> - <a href="https://summerofcode.withgoogle.com/archive/2016/projects/6593494743252992/">Computational Group Theory in SymPy</a></p>
<p>This project aimed to implement free groups, finitely presented groups and various algorithms like <a href="https://en.wikipedia.org/wiki/Coset_enumeration">Coset Enumeration</a> using Todd Coxeter method, Low index subgroup and Reidemeister schreier.
Computation of order, index and other properties of the finitely presented
groups is now present. The functionality is added in the combinatorics module
of SymPy. He laid the groundwork for further addition of other algorithms
and integrate it with the permutation groups.</p>
GSoC 2016 wrap-up2016-08-19T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2016-project<p>GSoC 2016 Project with SymPy(<em>wrap up</em>): Computational Group Theory
Hi, I’m Gaurav Dhingra (<a href="https://github.com/gxyd">@gxyd</a>) and this post is a report of my work for SymPy under <a href="https://summerofcode.withgoogle.com">Google Summer of Code 2016</a>.</p>
<p>This is also intended to be a description of my work for submission to <b>GSoC’s Final Evaluation</b>.</p>
<blockquote>
<h2 id="work-product-submission">Work Product Submission</h2>
<p><a href="https://github.com/sympy/sympy/commits/master?author=gxyd">commits in GSoC 2016 product submission: Gaurav Dhingra</a>.
<a href="https://github.com/gxyd/sympy/wiki/GSoC-2016-Application-Gaurav-Dhingra:-Group-Theory">GSoC proposal</a></p>
</blockquote>
<blockquote>
<h2 id="pull-requests">Pull Requests</h2>
</blockquote>
<ol>
<li><a href="https://github.com/sympy/sympy/pull/10350">#10350 FreeGroup implementation in SymPy</a></li>
<li><a href="https://github.com/sympy/sympy/pull/11140">#11140 FpGroup implementation in SymPy</a></li>
<li><a href="https://github.com/sympy/sympy/pull/11231">#11231 Low Index Subgroups algorithm implementation in SymPy</a></li>
<li><a href="https://github.com/sympy/sympy/pull/11295">#11295 Reidemeister Schreier algorithm implementation in SymPy</a></li>
<li><a href="https://github.com/sympy/sympy/pull/11460">#11460 Add documentation for FpGroup file and fix separate bug</a></li>
</ol>
<ul>
<li><a href="https://github.com/sympy/sympy/pull/11361">#11361 <em>Modified Todd Coxeter</em> algorithm implementation in SymPy</a></li>
</ul>
<blockquote>
<h2 id="bugs-reported">Bugs reported</h2>
<p>[closed]</p>
<ul>
<li><a href="https://github.com/sympy/sympy/issues/11449">#11449 <em>TypeError</em> on compressing a Coset Table generated by coset table method</a>.</li>
</ul>
</blockquote>
<blockquote>
<h2 id="brief-information">Brief Information</h2>
</blockquote>
<p><strong>Project</strong>: <a href="https://summerofcode.withgoogle.com/projects/#5798586428162048">Group Theory</a></p>
<p><strong>Blog</strong>: <a href="https://gxyd.github.io/gsoc.html">https://gxyd.github.io/gsoc.html</a></p>
<p><strong>My Website</strong>: https://gxyd.github.io</p>
<p><strong>e-mail</strong>: gauravdhingra.gxyd[at]gmail.com, igauravdhingra[at]protonmail.com</p>
<p>I am a pre-final year undergraduate student of Applied Mathematics at IIT Roorkee.</p>
<blockquote>
<h2 id="before-gsoc">Before GSoC</h2>
</blockquote>
<p>I heard about the GSoC program and about SymPy org. since of one of my college mate, Prasoon Shukla (he also participated in GSoC with SymPy). I was quite amazed by how mathematics and computer science could intersect and help in solving math problems.</p>
<p>I have been contributing to SymPy from May last year. In the beginning I tended often to work on issues that were more often related to my then on-going courses in my college. In December I completed a basic course on Group Theory, so I thought of choosing to work on Group Theory and I saw quite a few things in CGT were missing from SymPy and those functionalities were already there in GAP and Magma. So I asked them from Kalevi, regarding things that could be taken up for a gsoc project. So finally with some discussions with him and Aaron, I was sure by December end that I was going to work on implementing Finitely Presented Group in SymPy. I looked upto the last GSoC project on CGT by Alexandar Makelov, for reference material that could be used for the implementation and it turned out that the book by Derek Holt, Handbook of Computational Group Theory (will mention as shortly <em>the Handbook</em>).</p>
<p>Though I already started working on <a href="https://github.com/sympy/sympy/pull/10350">PR #10350</a> for implementation of free groups in beginning January though I started working on the proposal from February beginning.</p>
<p>So what I should do? Since I was quite sure of the project. Well at that moment I thought, since I am a mathematics major, choosing this project would also help me. So I reached out to Kalevi, said to him what I was thinking to do, what could be good for the project. So we worked upon making a good gsoc proposal.</p>
<p>Here is my <a href="https://github.com/gxyd/sympy/wiki/GSoC-2016-Application-Gaurav-Dhingra:-Group-Theory">GSoC proposal</a>. Now that the summer is over and I’ve tackled a lot more with computational group theory, it seems that the main points in my GSoC proposal were:</p>
<ul>
<li>Implementation of different algebraic structures monoid, free monoid, free group, semi group, free semi group, magma, etc.</li>
<li>Rewriting System for reducing the elements of finitely presented groups.</li>
<li>The Todd-Coxeter algorithm for coset enumeration, used to find the index of a subgroup of a finitely presented group.</li>
<li>Reidemeister Schreier algorithm.</li>
<li>Implementation of main <code class="highlighter-rouge">Group</code> class.</li>
</ul>
<p>Well, I submitted my proposal and needed to wait until April 22 to the result, and then…</p>
<p><img src="../images/gsoc_selection.png" height="200" width="650" /></p>
<p><em>I was selected _/_</em></p>
<p>I got lucky to have Kalevi Suominen like mentor too. Aaron Meurer, the project leader of SymPy was to be co-mentor, and I felt honored to be alloted my preferred mentors.</p>
<blockquote>
<h2 id="during-gsoc">During GSoC</h2>
</blockquote>
<p>A more detailed account of my progress can be found on my blog <a href="https://gxyd.gitub.io/gsoc.html">here</a>.</p>
<ul>
<li>
<p>We started working on 7th May, we first started with working on completing the Free Group <a href="https://github.com/sympy/sympy/pull/10350">PR#10350</a> and we discussed things on our channel <a href="https://gitter.im/sympy/GroupTheory">sympy/GroupTheory</a>. We had some discussion on whether <code class="highlighter-rouge">Basic</code> should be a <em>super-class</em> of <code class="highlighter-rouge">FreeGroup</code> or not. In the end we decied not to derive <code class="highlighter-rouge">FreeGroup</code> from <code class="highlighter-rouge">Basic</code>. Its basic methods had already been written, most of them inspired from GAP software.</p>
</li>
<li>
<p>For the first point in my proposal (i.e implementation of algebraic structures), we didn’t started with them (infact we never worked on them). We then moved onto the Coset Enumeration which covered 5 weeks of work in my timeline, but we didn’t spend that much time, atleast on the first go at that moment, that did took alomost 3 weeks including the implementation of two strategies of enumeration <em>Felsch</em> and <em>HLT</em>. It was the very heart of our GSoC project. There were quite a few bugs that were there in algorithm, especially the bug #11449, to which the Kalevi found the solution.</p>
</li>
<li>
<p>For the second point we never reached it, there wasn’t sufficient time for that. Then we decided to rather implement the <em>Low Index Subgroups</em> algortithm. It was quite fun to implement the algorithm, since it gave some good insight into CGT. More on this on <a href="https://gxyd.github.io/gsoc_week_5.html">blog for week 5</a>.</p>
</li>
<li>
<p>From here I had passed my mid-term evaluations. Then we started with work on <em>Reidemeister Schreier</em> algorithm. The algorithm was mainly implemeted using the <a href="http://staff.itee.uq.edu.au/havas/1974h.pdf">Havas paper</a>, though the current implementation in SymPy doesn’t produce the best simplifed presentation. No good pseudocode is available for the algorithm, the major difficulty being the <em>sequence</em> of applying the operation. More on this on <a href="https://gxyd.github.io/gsoc_week_6.html">blog for week 6</a>.</p>
</li>
<li>
<p>After we thought that the result returned by Reidemeister Schreier algorithm we moved onto <em>modified todd coxeter</em> algorithm. The main difficulty in it was defining the $\tau$ which can be read on the our channel for comments by Kalevi, I belive it can help in solving that problem.</p>
</li>
<li>
<p>As to the fifth point (i.e making <code class="highlighter-rouge">Group</code> class), we never worked upon it. Also the topic of <em>Presenation of Finite Groups</em> , could not get much attention, since of my busy college schedule.</p>
</li>
</ul>
<blockquote>
<h3 id="commitscode-written-during-gsoc">Commits/Code written during GSoC</h3>
</blockquote>
<p>Since I have commited quite a few commits un-related to my project. So I decided to <em>cherry-pick</em> the commits made for my GSoC project. So the combined commits makes the things quite clear. <a href="https://github.com/gxyd/sympy/pull/6">PR for GSoC 2016 product submission: Gaurav Dhingra</a>.</p>
<blockquote>
<h3 id="most-annoying-issue">Most annoying issue</h3>
</blockquote>
<p><a href="https://github.com/sympy/sympy/issues/11449">issue #11449</a></p>
<blockquote>
<h2 id="after-gsoc">After GSoC</h2>
</blockquote>
<p>There is still much to be done regarding the finitely presented groups. As during the program my efforts were directed mainly towards getting the fundamental algorithms for finitely presented groups in, the overall structure of the module hasn’t received much attention.</p>
<p>The algorithms are in, but the methods in sympy/combinatorics/fp_groups.py are not that much user-friendly. The code organization is not terrible, I think. Some suggestions (both for me and anyone else interested) for future work are:</p>
<ul>
<li>
<p><strong>Cosets in permutation groups</strong>: [verbatim-copy of Kalevi’s mail - <em>“next thing to do”</em>] Finding cosets in permutation groups is more challenging to implement since there seems to be no ready-made pseudocode. However, there is a description of the procedure with an example in section 4.6.7. It can be based on the existing implementation of the <em>Screier-Sims algorithm</em>.</p>
</li>
<li>
<p><strong>Finitely generated abelian groups</strong>: [verbatim-copy of Kalevi’s mail - <em>“next thing to do”</em>] There is useful pseudocode in chapter 9 of the book by Holt that should make it fairly easy to implement the basic methods of abelian groups. We should probably try to base the implementation on the code in <code class="highlighter-rouge">polys.agca</code> as abelian groups are the same as Z-modules. It is all essentially about linear algebra over the integers.</p>
</li>
<li>
<p><strong>Complete modified Todd Coxeter algorithm</strong>: <a href="https://github.com/sympy/sympy/pull/11361">PR #11361</a> One bug is currently there in the algorithm, which can be fixed since we have to make assignments to $\tau$. Also currently no tests have been added, which can be added.</p>
</li>
<li>
<p><strong>Rewriting System</strong>: This can be a good candidate for a major work, I included this topic in my proposal though was left untouched. Perhaps <em>GAP</em> could be first seen in this regard. Like always.</p>
</li>
<li>
<p><strong>Groups folder</strong>: After a few of the above mentioned things have been done, I believe it could be a good time to make a folder named <code class="highlighter-rouge">groups</code>, since finitely presented groups should not be a part of combinatorics module which would contain the all algebraic structures including the permutation groups.</p>
</li>
<li>
<p><strong>Non-associative algebra</strong>: (Perhaps I got the spelling of <em>associative</em> this time right!) Albert CAS could be used to understand the workings related to non-associative algebra, it contains quite good functionalities.</p>
</li>
</ul>
<blockquote>
<h2 id="things-i-did-rightwrong">Things I did right/wrong</h2>
</blockquote>
<ul>
<li>I often lagged in writing blogs.</li>
<li>I worked more than expected hours before 15 July (before college started) but much less in the last one month of GSoC because of a little busy schedule.</li>
</ul>
<blockquote>
<h2 id="conclusion">Conclusion</h2>
</blockquote>
<p>I had say that I did about 70% of the work I promised to do in my proposal, considering that I also did two non-included task of Low Index subgroups algorithm and Modified Todd Coxeter algorithm, so I can say I swapped my work. It is good enough, and I hope to get back to extending the things that I have started. There’s still some revision to be made, some code to be clean up. And I’m doing that.</p>
<p>I don’t really know if I’ll pass final evaluations by Google, but, regardless, I’m really glad for all the coding and development experience I got during these weeks. I’ll probably use for personal projects, may be in Dissertation in last year, and try to contribute more to SymPy.</p>
<p>I appreciate the help of my mentor <a href="https://github.com/jksuom">Kalevi Suominen</a> who was always there for any query that I had regarding Group Theory in project, and I appreciate his ability to reply back within 1 hour for any message I left any time of day and every day of the week including weekend (I call it 1-hour rule). I think he was a wonderful mentor and I learnt a lot from him, and my co-mentor <a href="https://github.com/asmeurer">Aaron Meurer</a>, the current project leader of SymPy, and the entire SymPy community for helping me out and reviewing my work!</p>
<p>Also thank you <font color="#4885ed">G</font><font color="#db3236">o</font><font color="#f4c20d">o</font><font color="#4885ed">g</font><font color="#3cba54">l</font><font color="#db3236">e</font>.</p>
<p>अलविदा !</p>
GSoC Week 122016-08-09T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2016-week-12<p>Hi all, here’s a brief summary of the 12th week of my GSoC:</p>
<p>Last week I uploaded the <a href="https://gxyd.github.io/gsoc2016/covhtml/index.html">test-coverage files</a> on my website, that revealed some interesting places where a few versions of <code class="highlighter-rouge">scan</code> routine in coset enumeration have un-tested <code class="highlighter-rouge">if-elif-else</code> case.</p>
<p>As we are now approaching the end of GSoC time period, we decided to do some testing with some of the examples from 1973cdhw paper [2]. Coset Enumeration got my attention again since:</p>
<p>There seemed to be one bug raising <code class="highlighter-rouge">TypeError</code> so opened issue <a href="https://github.com/sympy/sympy/issues/11449">sympy/sympy/#11449</a>, resulting from coset enumeration by the coset-table based method. From beginning it was clear that the issue was not in <code class="highlighter-rouge">compress()</code> method. It was quite difficult for me get onto the main source of problem. But then Kalevi had a closer look on the pseudo-code in Derek Holt and also in Sims Finitely Presented Groups.</p>
<p>I wrote docstrings for a few of methods and fixed the issue <a href="https://github.com/sympy/sympy/issue/11449">#11449</a> in PR <a href="https://github.com/sympy/sympy/pull/11460">#11460</a>.</p>
<p>The problem there in code is explained briefly below</p>
<p><strong>Previous code-snippet</strong></p>
<div class="highlighter-rouge"><pre class="highlight"><code>1 i = 0
2 while i < len(C.omega):
3 alpha = C.omega[i]
4 i += 1
5 for x in C.A:
6 if C.table[alpha][C.A_dict[x]] is None:
7 C.define_f(alpha, x)
8 C.process_deductions(R_c_list[C.A_dict[x]], R_c_list[C.A_dict_inv[x]])
</code></pre>
</div>
<p><strong>After code-snippet</strong></p>
<div class="highlighter-rouge"><pre class="highlight"><code>1 while alpha < len(C.table):
2 if C.p[alpha] == alpha:
3 for x in C.A:
4 if C.p[alpha] != alpha:
5 break
6 if C.table[alpha][C.A_dict[x]] is None:
7 C.define_c(alpha, x)
8 C.process_deductions(R_c_list[C.A_dict[x]], R_c_list[C.A_dict_inv[x]])
</code></pre>
</div>
<p>Here $\alpha$ looks over in till $\lt$ <code class="highlighter-rouge">C.table</code>. This way all elements of $C.\Omega$ are tested even in case that the set becomes very small. The inner for $x$ loop should also tests $p[i]$ at each round and break if that becomes different from $i$.</p>
<p>The changes that have been addressed in <a href="https://github.com/sympy/sympy/pull/11460">PR #11460</a> also include chaging the file name <code class="highlighter-rouge">free_group.py</code> to <code class="highlighter-rouge">free_groups.py</code>, similar to what we have.</p>
<p>It seems that Presentation of Permutation Groups won’t happen during GSoC since there’s just one more week; instead, I plan to focus on improving and completing the current PR’s <a href="https://github.com/sympy/sympy/pull/11361">#11361</a> on Modified Todd-Coxeter algorithm and <a href="https://github.com/sympy/sympy/pull/11460">PR #11460</a> on addition of docstrings and better user methods.</p>
<p>One more thing, that I would start in this week though may not be completed this week will be the sphinx documentation of finitely presented groups. I found the documentation of Poly’s module by Kalevi very much readable and interesting, may be I can seek to follow that.</p>
<blockquote>
<h2 id="references">References</h2>
</blockquote>
<ol>
<li>
<p>Derek F. Holt, Bettina Eick, Bettina, Eamonn A. O’Brien, “Handbook of computational group theory”, Discrete Mathematics and its Applications (Boca Raton). Chapman & Hall/CRC, Boca Raton, FL, 2005. ISBN 1-5848-372-3 .</p>
</li>
<li>
<p><a href="http://staff.itee.uq.edu.au/havas/1973cdhw.pdf">John J. Cannon; Lucien A. Dimino; George Havas; Jane M. Watson, “Implementation and Analysis of the Todd-Coxeter Algorithm” , Mathematics of Computation, Vol. 27, No. 123. (Jul., 1973), pp. 463-490</a>.</p>
</li>
</ol>
GSoC Week 72016-07-11T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2016-week-7<p>Hi everyone.</p>
<p>Here’s what we have been doing for <em>7th</em> week of <em>GSoC</em>.</p>
<p>Kalevi mentioned about the $LaTex$ not getting rendered on Planet Sympy website, thought it works fine on my website. Following the conversation Aaron opened issue <a href="https://github.com/sympy/planet-sympy/issues/45">planet-sympy/issues/45</a>, though it hasn’t been fixed.</p>
<p>This week we completed PR <a href="https://github.com/sympy/sympy/pull/11295">#11295</a> on Reidemeister Schreier algorithm. Remember the <a href="https://gitter.im/sympy/GroupTheory?at=5776b220cdab7a1f4fbebd34">blog issue</a> I asked on our gitter channel. Kalevi suggested to be more on the ‘descriptive’ side.</p>
<blockquote>
<h2 id="what-do-we-do-this-week">What do we do this week?</h2>
</blockquote>
<p>Implemented the Reidemeister Schreier algorithm (shortly RS algorithm) and Titze Transformations (shortly TT) in PR #11295 . Most of the pseudo code for RS algorithm is there in the Handbook [1], perhaps majority of the time was spent working with TT. There isn’t any pseudo code available for making that work, but we gathered detailed information from [1] combined with Havas Paper [2].</p>
<p>What issues were there?
In the both [1] and [2], there a few assumptions made, like</p>
<blockquote>
<p>shall assume that all relators are always cyclically reduced; that is, that
whenever a relator is changed, it is immediately replaced by its cyclic reduction.</p>
</blockquote>
<p>I opened the issue <a href="https://github.com/sympy/sympy/issues/11352">#11352</a> regarding a typo I left in <code class="highlighter-rouge">coset_enumeration_c</code>. Though I didn’t expect a PR, @kritkaran94 fixed it. Perhaps a good test case which makes use of different value of <code class="highlighter-rouge">max_stack_size</code> was suggested by Kalevi. One thing came back to me, “everthing is an object in Python”, the fact that initially <code class="highlighter-rouge">CosetTableDefaultMaxLimit</code> was a module level variable initially and we changed it to <code class="highlighter-rouge">CosetTable.CosetTableDefaultMaxLimit</code>, module is an object so is a <code class="highlighter-rouge">class</code>.</p>
<blockquote>
<h2 id="what-hasnt-been-done">What hasn’t been done?</h2>
</blockquote>
<ul>
<li>
<p>No testing for a few of techniques, for example currently no tests exist for <code class="highlighter-rouge">elimination_technique_2</code>, which is a variant of the elimination procedures.</p>
</li>
<li>
<p>TT doesn’t produce the best possible result.</p>
</li>
</ul>
<p>Though doing this seemed easy at first. But I didn’t wanted to apply <code class="highlighter-rouge">identity_cyclic_reduction</code> every change as there can be a few instance where it not necessary to do this, perhaps because of the property of <em>words</em>.</p>
<p>The good thing about this week was that I could now understand the limitations that will remain after my GSoC project. The scope of Computational Group Theory is more than what I expected. Apart from that I will be leaving for my college this week stars from <em>15th</em> of <em>July</em>, perhaps I don’t know how things will shift regarding time for GSoC. Let’s be realistic :)</p>
<p>अलविदा</p>
<blockquote>
<h2 id="references">References</h2>
</blockquote>
<ol>
<li>
<p>Derek F. Holt, Bettina Eick, Bettina, Eamonn A. O’Brien, “Handbook of computational group theory”, Discrete Mathematics and its Applications (Boca Raton). Chapman & Hall/CRC, Boca Raton, FL, 2005. ISBN 1-5848-372-3 .</li></p>
</li>
<li>
<p><a href="http://staff.itee.uq.edu.au/havas/1974h.pdf">George Havas, “Reidemeister-Schreier program”</a>.</p>
</li>
</ol>
GSoC Week 62016-07-01T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2016-week-6<p>Hi everyone.</p>
<p>First of all the good news, I have <em>passed</em> the mid-term evaluations. I received the feedback from Kalevi, “I have had some problems with the blog posts.”. Though Kalevi, mentioned to not take the post seriously. Well, not to say, that is definitely true. I don’t claim that I will be able to remedy this, but lets see what happens.</p>
<p>Kalevi, had sent me a mail, mentioning “next things to do”, it included “Cosets in Permuations group” and “Finitely Presented Abelian groups”. (its been quite sometime since that mail). It was more of my decision to implement the topic of “presentation of subroups”. To be true, I particularly chose this topic, since that makes the output of out work done till now, to look beautiful :) . Earlier I had a constant doubts when I was making proposal about what it exactly means by “presentation of subgroups”. So while I read the examples from the Handbook, it became clear to me.</p>
<p>As to the progress in the topic, here’s what we have done, I opened the PR on sunday. This week we started with the implementation of subgroup presentations. There are two methods to compute “presentation of a subgroup”, first being called “computing presentations on schreier generators” also called the Reidemeister Schreier procedure. Since we have already implemented the “Todd Coxeter” procedure, which is used as the first step in Reidemeister Schreier for coset enumeration. It uses a routine which is called “define_schreier_generators” Second being “computing presentation on the generators of subgroup”. Well the pseudo code is there for both the two implementations. The code of</p>
<table>
<tbody>
<tr>
<td>The important part of finding the “presentation of subgroup” being simplifying the “presentations”, i.e reducing the three factors</td>
<td>X</td>
<td>(no. of subgroup generators),</td>
<td>R</td>
<td>(no. of subgroup relators) and l (total length of subgroup relators). Though there doesn’t seem to any pseudo code available anywhere for the implementation (this makes it quite interesting to implement). But the paper by Havas <a href="http://staff.itee.uq.edu.au/havas/1974h.pdf">Reidemeister Schreier program</a> neatly explains the things.</td>
</tr>
</tbody>
</table>
<p>Last 2 days were spent on trying to make <code class="highlighter-rouge">elimination_technique_1</code> work. Its still not
fully functional, since it still returns some dependent relators as a part of the presentation.</p>
<p>As for an example, currently Reidemeister Schreier procedure presentation works this way.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>>>> F, x, y = free_group("x, y")
>>> f = FpGroup(F, [x**2*y**2, y**-1*x*y*x**-3])
>>> H = [x]
>>> reidemeister_presentation(f, H)
([x_1], [x_1**-4, x_1**-8])
</code></pre>
</div>
<p>Two things need to be fixed here. First being, removal of -ve powers of single syllable
relators, $x_1^{-4}$ -> $x_1^4$, similarly for the other relator.
Second thing being, since $x_1^4 = 0$ implies that $x_1^8 = 0$ (dependent relator) so the relator
should be removed. Perhaps the issue with this is, where should the code for checking this dependence
be introduced? Kalevi seems a bit busy these days with other project. That is not the issue. I believe there may be
something more to the simplification in the “Handbook”, (have been referring to [2] for the
elimination of generators, relators and simplification of presentations).</p>
<p>Yesterday, I Thought of focussing on a new topic “simplification of presentations”, the method
is short descripted in [2], but that is sufficient enough. It starts by checking whether any relator
is of the form $gen^n$, where $n \in \mathbb{N}$. If any such relators are found then all other relators
are processed for strings in the $gen$ known order. All string length exceeding length $n/2$ are
replaced by their shortest equivalent. Further, for even <code class="highlighter-rouge">n</code> strings gen$^{-n/2}$ replaced by
gen$^{n/2}$. I have written its code, perhaps it only requires a few more tests to be added
to it.</p>
<p>I think I will be busy with “presentation of subgroups”, this week and next week as well.</p>
<blockquote>
<p>##References</p>
</blockquote>
<ol>
<li>
<p>Derek F. Holt, Bettina Eick, Bettina, Eamonn A. O’Brien, “Handbook of computational group theory”, Discrete Mathematics and its Applications (Boca Raton). Chapman & Hall/CRC, Boca Raton, FL, 2005. ISBN 1-5848-372-3 .</p>
</li>
<li>
<p><a href="http://staff.itee.uq.edu.au/havas/1974h.pdf">George Havas, “Reidemeister-Schreier program”</a>.</p>
</li>
</ol>
GSoC Week 52016-06-21T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2016-week-5<p>Hi everyone. Here’s a brief summary of 5th week of my GSoC.</p>
<table>
<tbody>
<tr>
<td>In the 5th week we worked upon the implementation of Low Index Subgroups algorithm. The basic problem dealt with by this algorithm is: *find all subgroups H such that the index</td>
<td>G:H</td>
<td>is at most a specified number N > 0.*</td>
</tr>
</tbody>
</table>
<p>The term “low” is used to indicate the impracticalness of solving the problem for large $N$ values. The Handbook [1] contains the necessary pseudo code for its implementation, in which it has been explained in a top-down approch instead of the usual bottom-up approach.</p>
<p>Complexity of the algorithm: exponential.</p>
<p>Status update: completion of Low Index Subgroup algorithm.
The main function for calling the algorithm is <code class="highlighter-rouge">low_index_subgroups</code> with signature <code class="highlighter-rouge">(G, N, Y=[])</code>, here $G$ is the group for which we want to find the subgroups for, $N$ being a positive integer specifying the upper bound on the index value of subgroup generated, and $Y$ is optional argument specifying.</p>
<p>This routine also (<code class="highlighter-rouge">coset_enumeration_c</code> to needed this) makes use of calling <em>cyclic conjugates</em> of cyclic reductions of a set of relators, so I made a method in <code class="highlighter-rouge">CosetTable</code> named <code class="highlighter-rouge">conjugates</code>, which does this task now. We have a list $S$, which stores the coset tables for the founds subgroups. The algorithm later calls a routine called <code class="highlighter-rouge">descendant_subgroups</code>. One of the things being that in <code class="highlighter-rouge">low_index_subgroups</code> the <code class="highlighter-rouge">descendant_subgroups</code> routine can be called on any of the generators of inverse of generator of group $G$, though this isn’t clear in the Handbook, but I some intuition to it.</p>
<p>descendant_subgroups($C$, ${R_{1x}^C }$, $R_2$, $N$)</p>
<p>try_descendant($C$, ${R_{1x}^C}$, $R_2$, $N$, $\alpha$, $x$, $\beta$)</p>
<p>Here is an example of Low Index Subgroup algorithm in work, Yay :) !!</p>
<div class="highlighter-rouge"><pre class="highlight"><code>>>> from sympy.combinatorics.free_group import free_group
>>> from sympy.combinatorics.fp_groups import FpGroup, low_index_subgroups
>>> F, x, y = free_group("x, y")
>>> f = FpGroup(F, [x**2, y**3, (x*y)**4])
>>> L = low_index_subgroups(f, 10)
>>> for i in L:
... print(i.table)
[[0, 0, 0, 0]]
[[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 3, 3]]
[[0, 0, 1, 2], [2, 2, 2, 0], [1, 1, 0, 1]]
[[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 4], [2, 2, 3, 5], [5, 5, 4, 3]]
[[1, 1, 0, 0], [0, 0, 1, 1]]
[[1, 1, 0, 0], [0, 0, 2, 3], [4, 4, 3, 1], [5, 5, 1, 2], [2, 2, 5, 6], [3, 3, 6, 4], [7, 7, 4, 5], [6, 6, 7, 7]]
[[1, 1, 1, 2], [0, 0, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], [5, 5, 5, 3], [4, 4, 3, 4]]
[[1, 1, 2, 3], [0, 0, 4, 5], [5, 5, 3, 0], [4, 4, 0, 2], [3, 3, 5, 1], [2, 2, 1, 4]]
</code></pre>
</div>
<p>Things I would love to have for this algorithm is to give, a presentation in the form Magma gives the subgroup returned in the form of generators of subgroup. That is coding the <strong>Reidemeister Schreier</strong> and its variant algorithms.</p>
GSoC 2016 Week 2, 32016-06-14T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2016-week-2_3<p>Here is a brief summary of what we did in the second and third week of GSoC.</p>
<p>First of all I got late in blogging about our progress for the weeks 2, 3. Since the internet connection was disrupted(<a href="https://en.wikipedia.org/wiki/Jat_reservation_agitation">reason</a>) for almost 3 weeks in my city, so in between I had to move out to some other place. But still project progress is good :)</p>
<p>Status update:</p>
<ul>
<li><a href="https://github.com/sympy/sympy/pull/11140">PR #11140</a> on implementation of strategies of coset enumeration has been <i>merged</i>.</li>
</ul>
<p></p></p>
<p>We implemented the <i>Coset Enumeration</i> strategies. Suppose $G$ is defined by a finite presentation, and $H$ is a subgroup of $G$ (for $H$ we currently only list of generators which generate $H$), which is specified by words in the generators of $G$ that generate $H$. The procedure is known as coset enumeration and is one of the most fundamental methods in CGT. No algorithm (its been proved mathematically [4]) can be guaranteed to terminate for <i>coset enumeration</i>, so it can’t be defined to have a fixed complexity.</p>
<p><i>Coset Table</i> is equivalent to the permutation representation of the input group $G$ in its action by right multiplication on the right cosets of $H$. Beginning with the <code class="highlighter-rouge">Coset Table</code>, we have initialised it with various attributes in <i>SymPy</i>, most of them are instances of <code>list</code>, they are appended on the way while strategies like <i>HLT</i>, <i>Felsch</i> run over it. Contrary to what I mentioned in my last post, <code>CosetTable</code> is not a subclass of <code>list</code>.</p>
<p>The algorithm we have implemented is known as <i><a href="https://en.wikipedia.org/wiki/Todd%E2%80%93Coxeter_algorithm">Todd-Coxeter algorithm">Todd Coxeter algorithm</a></i>. The algorithm can use too much memory and time, but still memory is more important resource than time in this algorithm. This algorithm has got two major implementations:</p>
<blockquote>
<h3 id="hlt-strategy">HLT strategy</h3>
<p>In this strategy whenever we use the <code class="highlighter-rouge">C.scan_and_fill($\alpha$, $w$)</code> for scanning the word $w$ over coset $\alpha$, routine for scanning which if the scan is incomplete makes a new definition of coset using <code class="highlighter-rouge">define</code> then we make new definitions to enable the scan to complete; that is, we fill in the gaps in the scan of the relator or subgroup generator. Kalevi suggested to make some modification from the original pseudo-code, which resulted in quite a few improvements, since the changes removes un-necessary scanning.</p>
</blockquote>
<p>For calculating the index of <script type="math/tex">x^{-1}</script>, for a generator <script type="math/tex">x</script>, we initialised the Coset Table with a dictionary <code class="highlighter-rouge">A_dict_inv</code>, which has <code class="highlighter-rouge">(gen,index)</code> as <code class="highlighter-rouge">(key,value)</code> pair.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>>>> for x, index in self.A_dict.items():
... if index % 2 == 0:
... self.A_dict_inv[x] = self.A_dict[x] + 1
... else:
... self.A_dict_inv[x] = self.A_dict[x] - 1
</code></pre>
</div>
<p>We changed the slicing of the Free Group elements, which now work this way.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>>>> w = x**2*y**6
>>> w[1]
x
>>> w[3]
y
</code></pre>
</div>
<p>Since earlier it was only possible using the <code class="highlighter-rouge">.subword(i, i+1)</code> to obtain the <script type="math/tex">i{th}</script> “word”.</p>
<p>We have now completed the <a href="https://github.com/sympy/sympy/pull/11140">PR #11140</a>. We used the utf-8 encoding in <code class="highlighter-rouge">sympy/combinatorics/fp_groups.py</code> in its comments, which was generating the error in <code class="highlighter-rouge">Python2.7</code> but not in <code class="highlighter-rouge">Python3.4</code>.</p>
<div class="highlighter-rouge"><pre class="highlight"><code>SyntaxError: Non-ASCII character '\xce' in file /home/gaurav/Public/sympy/sympy/combinatorics/fp_groups.py
on line 79, but no encoding declared; see http://www.python.org/peps/pep-0263.html for deta
</code></pre>
</div>
<p>and then using the line <code class="highlighter-rouge"># -*- coding: utf-8 -*-</code> at the top of file resolved the issue, so seems like <code class="highlighter-rouge">Python2.x</code> is more sensitive to such issues.</p>
<p>There was one error in the implemted code:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>>>> from sympy.combinatorics.free_group import free_group
>>> from sympy.combinatorics.fp_groups import FpGroup, coset_enumeration_r, CosetTable
>>> F, x, y = free_group("x, y")
>>> f = FpGroup(F, [x**2, y**3, (x*y)**3])
>>> Y = [x*y]
>>> C = coset_enumeration_r(f, Y)
>>> C.table # this will return the table
</code></pre>
</div>
<p>As for refinement, I will paste another one.</p>
<div class="highlighter-rouge"><pre class="highlight"><code># these are the steps that happen internally
>>> C = CosetTable(f, Y)
>>> C.scan_and_fill(0, x*y)
>>> C.scan_and_fill(0, x**2)
>>> C.scan_and_fill(0, y**3)
>>> C.scan_and_fill(0, (x*y)**3)
# till now coset table is fine.
# here the coset table returned is wrong.
</code></pre>
</div>
<p>In the implementation of <code class="highlighter-rouge">scan_and_fill</code> the implemened code differed from that in the book in one significant aspect. In the book, <code class="highlighter-rouge">scan_and_fill</code> looped until it filled the $\alpha$ row in the table. (“Made a new definition and continue with scan.”). While the implemented code returned after one definition, the error occured since I tried removing the while loop (some testing purpose). Then we also added some “examples” from [2].</p>
<blockquote>
<h3 id="felsch-strategy">Felsch strategy</h3>
</blockquote>
<p>In this we first find the first undefined coset $\alpha$, in this instead of seeing ahead by making use of <code class="highlighter-rouge">lookahead</code>, we make <b>deductions</b>, which are put in a <code class="highlighter-rouge">deduction_stack</code> (a <code class="highlighter-rouge">list</code> instance which behaves a <i>stack</i>), which contains the pair $(\alpha, x)$, whenever a new <b>definition</b> or a <b>deduction</b> is made, this reduces the number of un-necessary cosets made (loweing the memory use at the cost of time).
</p></p>
<p>Though we have made use of <code class="highlighter-rouge">CosetTableDefaultMaxLimit = 409600</code> (similar to that in <i>GAP</i>), till now I haven’t found a single example which would exhaust this much memory in our implementation, every one just seems to take too much of time.</p>
<p>Python utilities learned on the way:</p>
<ul>
<li>At one point we had to make a list of generator and inverse of generators of a finitely presented groups i.e `A` for a `CosetTable`, I did a bit of searching a arrived at using the [chain.from_iterable](https://docs.python.org/2/library/itertools.html#itertools.chain.from_iterable)</a> from the `itertools` which works as follows:
```
>>> from itertools import chain
>>> list(chain.from_iterable((x**2, x**3) for x in range(4)))
[0, 0, 1, 1, 4, 8, 9, 27]
```
</li>
<li>
Use of `product` routine, since in `coset enumeration`, we often iterate over $w \in Y$ and $x \in A$.
</li>
<li>
In `Python2.x` a `list` instance doesn't have a `copy` attribute, so `list()` function or <i>slicing</i> is used to make a shallow copy. [3]
</li>
</ul>
<p>At the end of the post, here’s one awesome small example of <code class="highlighter-rouge">coset enumeration</code> using the <i>HLT</i> strategy. Here is how the code works!! :)</p>
<div class="highlighter-rouge"><pre class="highlight"><code>In[1]: from sympy import *
In[2]: from sympy.combinatorics.free_group import free_group
In[3]: from sympy.combinatorics.fp_groups import FpGroup, CosetTable, coset_enumeration_r
In[4]: F, x, y = free_group("x, y")
In[5]: f = FpGroup(F, [x**2, y**3, (x*y)**4])
In[6]: C = coset_enumeration_r(f, [x])
In[7]: C.table
Out[7]:[[0, 0, 1, 2],
[3, 3, 2, 0],
[6, 6, 0, 1],
[1, 1, 4, 10],
[5, 5, 10, 3],
[4, 4, 6, 7],
[2, 2, 7, 5],
[8, 8, 5, 6],
[7, 7, 9, 12],
[10, 10, 12, 8],
[9, 9, 3, 4],
[None, 10, 12, None],
[12, 12, 8, 9],
[None, 12, 8, 9],
[7, None, None, 13]]
In[8]: C.compress()
In[9]: C.standardize()
In[10]: C.table
Out[10]: [[0, 0, 1, 2],
[3, 3, 2, 0],
[4, 4, 0, 1],
[1, 1, 5, 6],
[2, 2, 7, 8],
[8, 8, 6, 3],
[9, 9, 3, 5],
[10, 10, 8, 4],
[5, 5, 4, 7],
[6, 6, 11, 10],
[7, 7, 9, 11],
[11, 11, 10, 9]]
</code></pre>
</div>
<p>My mentor, Kalevi, has been very much supportive, when I informed him about my possible abscence (due to internet unavailability), he even sent me a mail about the <i>things we could do next</i>, even if I am offline.
So here they are: Cosets in Permutation Groups, Finitely presented abelian groups.</p>
<blockquote>
<h3 id="references">References</h3>
</blockquote>
<ul>
<li>1. Derek F. Holt, Bettina Eick, Bettina, Eamonn A. O'Brien, "Handbook of computational group theory", Discrete Mathematics and its Applications (Boca Raton). Chapman & Hall/CRC, Boca Raton, FL, 2005. ISBN 1-5848-372-3 .</li>
<li>2. John J. Cannon, Lucien A. Dimino, George Havas and Jane M. Watson, Implementation and Analysis of the Todd-Coxeter Algorithm</li>
<li>3. https://mail.python.org/pipermail/tutor/2006-November/051189.html</li>
<li>4. http://www.gap-system.org/Manuals/doc/ref/chap47.html</li>
</ul>
<p></body>
</html></p>
GSoC 2016 Week 12016-05-29T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2016-week-1<p>Hi everyone.
Here is a brief summary of what we have been doing for the first week of GSoC.</p>
<p>In last week we opened the <a href="https://github.com/sympy/sympy/pull/11140">PR #11140</a> for working on implementing the Finitely Presented Groups and Coset Enumeration. Implementing the Coset Enumeration first understanding how the routine mentioned in [1] interact with each other. Since The different routines being: <code class="highlighter-rouge">define</code>, <code class="highlighter-rouge">scan</code>, <code class="highlighter-rouge">coincidence</code>, <code class="highlighter-rouge">merge</code>, <code class="highlighter-rouge">rep</code>. Most of these methods have different versions as well, which can be made to be suitable for a particular class of groups.</p>
<p><code class="highlighter-rouge">Coset Table</code>: We represented it using list of lists data structure, inner lists are of fixed length, twice the number of generators, the outer list can grow as much as needed. We started with writing code for the <code class="highlighter-rouge">define</code>, <code class="highlighter-rouge">scan</code> routines. There was one typo in [1] for <code class="highlighter-rouge">scan</code> routine, which I somehow intuitively passed initially while writing code from pseudo-code, but came across it when reading the pseudo-code again. (I didn’t expected the book to contain such a type in pseudo-code). Intially we started with <code class="highlighter-rouge">-1</code> as an entry for undefined slots but since <code class="highlighter-rouge">-1</code> may lead to problems as Python will accept it as an index with no error indications, allowing the bugs to pass silently. So we chose <code class="highlighter-rouge">None</code> as a better option to opt for.</p>
<p>We wanted to make sure, these implemeted methods work as expected, so I wrote extensive tests (currently in doctests), 4 of which have been taken from [1] while one from the original Todd Coxeter paper [2].</p>
<p>Just yesterday we decided to make <code class="highlighter-rouge">Coset Table</code> a <code class="highlighter-rouge">class</code>, since every <code class="highlighter-rouge">Coset Table</code> in itself has certain attributes which are changed along the execution of the Enumeration, which can be better represented by a <code class="highlighter-rouge">class</code>. It’s struture is be something like</p>
<pre>
class CosetTable(list):
def __init__(self, fp_grp, subgroup):
self.fp_group = fp_grp
self.subgroup = subgroup
self._A = list(chain.from_iterable((gen, gen**-1)
for gen in self.fp_group.generators))
self.append([None]*len(self.A))
@property
def is_complete(self):
for coset in self:
for res in coset:
if res is None:
return False
return True
# other methods
</pre>
<p>On the other side we are working on <a href="https://github.com/sympy/sympy/pull/11150">PR#11150</a>, which deals with implementation of <code class="highlighter-rouge">FreeAbelianGroup</code>, it wouldn’t be tough to get along with this PR, since it is just similar to the previously implemented <code class="highlighter-rouge">FreeGroup</code>, with <code class="highlighter-rouge">dict</code> as its data structure.</p>
<blockquote>
<h2 id="for-next-week">For next week</h2>
</blockquote>
<ul>
<li>
<p>Complete the <code class="highlighter-rouge">Coset Table</code> PR, i.e implement the different strategies of Felsch, HLT. I am pretty sure, this task would take more than 1 week, since there are whole lot of other strategies which if we decide to implement would take up a lot of time, even the <code class="highlighter-rouge">Lookahead</code> version of Todd Coxeter is there, which specifies a whole new data-structure for different compoents involved in Enumeration.</p>
</li>
<li>
<p>Later, implement different methods for <code class="highlighter-rouge">FpGroup</code>.</p>
</li>
</ul>
<p>Anyway, I’m really enthusiastic about my project and hope that we’ll have some nice and reasonably fast algorithms in CGT by the end of the summer!</p>
<p>References</p>
<ol>
<li>
<p>Derek F. Holt, Bettina Eick, Bettina, Eamonn A. O’Brien, “Handbook of computational group theory”, Discrete Mathematics and its Applications (Boca Raton). Chapman & Hall/CRC, Boca Raton, FL, 2005. ISBN 1-5848-372-3 .</p>
</li>
<li>
<p>A practical method for enumerating cosets of a finite abstract group by J. A. TODD (University of Manchester), and H.S.M. Coxeter (University of Cambridge)</p>
</li>
</ol>
Community Bonding period ends, Coding period starts2016-05-20T00:00:00+00:00https://gxyd.github.io/blogs/Coding-period-starts<p>Community Bonding period ends, Coding period starts
The Community bonding period comes to an end now. First of all considering the issues described in the last post:</p>
<ul>
<li>Aaron created a new channel for our GSoC project discussion, <a href="https://gitter.im/sympy/GroupTheory">sympy/GroupTheory</a>.</li>
<li>I have also added rss-feed in my blog. As for time of meeting, me and Kalevi often have discussion on the gitter channel, but since of quite a bit differene in timings between me and Aaron (I tend to sleep early at 11 PM IST). We three haven’t been able to together have a meeting. Though Aaron suggested “Kalevi is the primary mentor, so if you have to meet without me that is fine”. I also think that’s not too big of an issue now, but his opinion has always helped, since he has best knowledge of sympy core.</li>
</ul>
<p>In the past few weeks I wasn’t too much productive, since I had a touch of fever, anyways I am okay now. We have now completed the implementation of the <code class="highlighter-rouge">FreeGroup</code> class in <a href="https://github.com/sympy/sympy/pull/10350">PR #10350</a>. I started working on the PR back in January but I halted, since of my semester classes. <code class="highlighter-rouge">FreeGroup</code> is quite similar to the <code class="highlighter-rouge">PolyRing</code> implemented in <code class="highlighter-rouge">sympy.polys.rings.py</code>. We first started with the list of tuples as the data structure for the <code class="highlighter-rouge">FreeGroupElm</code>, where each tuple being <code class="highlighter-rouge">(index, exp)</code>, but since of the mutable nature of lists, Kalevi suggested to go with tuple of tuples. Also as tuples are probably more efficient as there is no ‘housekeeping’ overhead. Also changed the element from <code class="highlighter-rouge">(index, exp)</code> –> <code class="highlighter-rouge">(symbol, exp)</code>.</p>
<p>Implementing <code class="highlighter-rouge">FreeGroupElm</code> deals elegantly in such a way that it can’t be independently created in a public interface. The reason being: every <code class="highlighter-rouge">FreeGroupElm</code> is in itself created only by the <code class="highlighter-rouge">dtype</code> method of <code class="highlighter-rouge">FreeGroup</code> class. The assignment is as follows:</p>
<div class="highlighter-rouge"><pre class="highlight"><code> `obj.dtype = type("FreeGroupElm", (FreeGroupElm,), {"group": obj})`
</code></pre>
</div>
<p>Its sort of an advanced usage of <code class="highlighter-rouge">type</code> function as a <a href="http://www.stackoverflow.com/questions/100003/what-is-a-metaclass-in-python">metaclass</a>.</p>
<p>Currently the printing code of <code class="highlighter-rouge">latex</code> and <code class="highlighter-rouge">pprint</code> for <code class="highlighter-rouge">FreeGroupElm</code> is a little hacky. I need to work on that as well.</p>
<blockquote>
<h2 id="plan-for-next-few-weeks">Plan for Next few weeks</h2>
</blockquote>
<p>Though according to my <a href="https://github.com/sympy/sympy/wiki/GSoC-2016-Application-Gaurav-Dhingra:-Group-Theory#Proposed_Timeline">proposal timeline</a>, we described to go with implementation of other algebraic structures i.e <code class="highlighter-rouge">Magma</code>, <code class="highlighter-rouge">SemiGroup</code>, <code class="highlighter-rouge">Monoid</code>. But we will next move onto <strong>Coset Enumeration</strong>. It is going to be a big task. That is harder and more important than other algebraic structures. Timline states it to be 5 week task, thats almost half the GSoC coding period. Well how do we go about that? I think of studying the mathematics in parallel with the implementation.</p>
<p>We have created a PR for implementation of Finitely Presented Group <a href="https://github.com/sympy/sympy/pull/11140">#11140</a>. Not much code has been added here. Paper on Coset Enumeration using <a href="http://staff.itee.uq.edu.au/havas/1973cdhw.pdf">Implementation and Analysis of Todd Coxeter Algorithm</a> (by John J. Cannon, George Havas), and other paper being the original paper by Todd and Coxeter, “A practical method for enumerating cosets of a finite abstract group” are the ones I am reading. As for the implementation of Todd Coxeter, we will be following the methods described in the book “Handbook of Computational Group Theory” by Derek F. Holt.</p>
GSoC 2016 Phase I : Proposal, Acceptance2016-05-02T00:00:00+00:00https://gxyd.github.io/blogs/Gsoc2016-with-sympy<p>Hello, I’m Gaurav Dhingra a 3rd year undergraduate student at IIT Roorkee, my proposal on Group Theory with <i>SymPy</i> has been accepted as a part of Google Summer of Code.</p>
<p>First, a little bit about <a href="http://www.sympy.org/">SymPy</a>, a <em>Computer Algebra System</em> (CAS) written entirely in Python. SymPy 1.0 was released about 2 months ago, <em>Sympy</em> has been created by hundreds of contributors starting from 2006.</p>
<p>I will be working on Group Theory over the summer, for the next 3 months, to implement Computational Group Theory (CGT) and Group Theory, which are parts of mathematics I particularly enjoy. You can view my project proposal <a href="https://github.com/sympy/sympy/wiki/GSoC-2016-Application-Gaurav-Dhingra:-Group-Theory">GSoC 2016 Application Gaurav Dhingra: Group Theory</a>. Until a few days ago I was pretty busy with my exams, but in the next few weeks I will go over working on the project. I will particularly focus on <code class="highlighter-rouge">Finite and Finitely Presented Groups</code>.</p>
<p>I hope that I’ll be able to implement everything that I promised in it. Moving onto the ongoing community bonding. Since I am very well acquitted with the workflow of SymPy, I can get straight to few important things, which i will do in the next few days.</p>
<p>This includes things like:</p>
<ul>
<li>
<p>Setting up a blog with RSS feed i.e this blog in which I am supposed to add an RSS feed functionality.</p>
</li>
<li>
<p>Talking to my mentors regarding the time, and place of chat on internet, we differ by almost 5hrs. Time wouldn’t be an issue, since seeing from past, I haven’t faced such difficulty as both me and my mentor work for almost the same time intervals. From the GSoC 2015 discussions, I remember that Ondrej tries to make sure everyone knows what time student-mentor meet, since of different time zones.</p>
</li>
<li>
<p>In the past we have had discussion on my private gitter channel <a href="https://gitter.im/gxyd/group_theory_implementation">Group Theory Implementation</a>. <em>Would it be wise to continue code discussions there?</em>. Since no one can be added in the channel without my permission.</p>
</li>
</ul>
<p>One thing that has been a hell of a lot annoying has been the GSoC mailing list, it’s a lot distracting. I changed list settings to abridged daily updates because I was getting like 50 mails every day and that too about some really stupid and irrelevant things. But yeah like whatever.</p>
<p><em>“LESS TALK, MORE CODE”</em> is the policy that I always tend to follow (not for blog!!). I will try my best to implement it in a strict way this summer. I have seen this policy working fine for me, mostly first I start writing question in a message box to my mentor, and then i think more about it myself and in the end I come up with a solution on my own, instead of asking.</p>
<p>I’m quite sure that I will write more than enough blog posts about my project during the summers. Since I enjoy writing and that too regarding things that occupy larger part of my day.</p>
<p>I’d like to thank all the people involved with contributions to <i>SymPy</i>. My special thanks to my mentor - <a href="https://github.com/jksuom">Kalevi Suominen</a> and my co-mentor - <a href="https://github.com/asmeurer">Aaron Meurer</a> for all the suggestions while making my proposal, and showing faith and enthusiasm in my ability and my proposal.</p>