<h1>Simplification</h1>

<p><a href="https://docs.sympy.org/latest/_sources/tutorial/simplification.rst.txt">From</a></p>

<hr />

<p>To make this document easier to read, we are going to enable pretty printing.</p>


```julia
    >>> from sympy import *
    >>> x, y, z = symbols('x y z')
    >>> init_printing(use_unicode=True)
```

<h5>In <code>Julia</code>:</h5>

<ul>
<li><p>" not ' are used for strings:</p>
</li>
<li><p>pretty printing in enable by default</p>
</li>
<li><p>we input extra functions from <code>sympy</code> such as <code>powsimp</code>, ...</p>
</li>
</ul>


```julia
using SymPy
import_from(sympy)
x, y, z = symbols("x y z")
```




    (x, y, z)



<hr />

<h2><code>simplify</code></h2>

<p>Now let's jump in and do some interesting mathematics.  One of the most useful features of a symbolic manipulation system is the ability to simplify mathematical expressions.  SymPy has dozens of functions to perform various kinds of simplification.  There is also one general function called <code>simplify&#40;&#41;</code> that attempts to apply all of these functions in an intelligent way to arrive at the simplest form of an expression.  Here are some examples</p>


```julia
    >>> simplify(sin(x)**2 + cos(x)**2)
    1
    >>> simplify((x**3 + x**2 - x - 1)/(x**2 + 2*x + 1))
    x - 1
    >>> simplify(gamma(x)/gamma(x - 2))
    (x - 2)⋅(x - 1)
```

<h5>In <code>Julia</code>:</h5>

<ul>
<li><p>we need to load in <code>SpecialFunctions</code> to have access to <code>gamma</code>:</p>
</li>
</ul>


```julia
simplify(sin(x)^2 + cos(x)^2)
```




\begin{equation*}1\end{equation*}




```julia
simplify((x^3 + x^2 - x - 1)/(x^2 + 2*x + 1))
```




\begin{equation*}x - 1\end{equation*}




```julia
using SpecialFunctions
simplify(gamma(x)/gamma(x - 2))
```




\begin{equation*}\left(x - 2\right) \left(x - 1\right)\end{equation*}



<hr />

<p>Here, <code>gamma&#40;x&#41;</code> is $\Gamma(x)$, the <code>gamma function &lt;http://en.wikipedia.org/wiki/Gamma_function&gt;</code>_.  We see that <code>simplify&#40;&#41;</code> is capable of handling a large class of expressions.</p>

<p>But <code>simplify&#40;&#41;</code> has a pitfall.  It just applies all the major simplification operations in SymPy, and uses heuristics to determine the simplest result. But "simplest" is not a well-defined term.  For example, say we wanted to "simplify" <code>x^2 &#43; 2x &#43; 1</code> into <code>&#40;x &#43; 1&#41;^2</code>:</p>


```julia
    >>> simplify(x**2 + 2*x + 1)
     2
    x  + 2⋅x + 1
```

<h5>In <code>Julia</code>:</h5>


```julia
simplify(x^2 + 2*x + 1)
```




\begin{equation*}x^{2} + 2 x + 1\end{equation*}



<hr />

<p>We did not get what we want.  There is a function to perform this simplification, called <code>factor&#40;&#41;</code>, which will be discussed below.</p>

<p>Another pitfall to <code>simplify&#40;&#41;</code> is that it can be unnecessarily slow, since it tries many kinds of simplifications before picking the best one.  If you already know exactly what kind of simplification you are after, it is better to apply the specific simplification function(s) that apply those simplifications.</p>

<p>Applying specific simplification functions instead of <code>simplify&#40;&#41;</code> also has the advantage that specific functions have certain guarantees about the form of their output.  These will be discussed with each function below.  For example, <code>factor&#40;&#41;</code>, when called on a polynomial with rational coefficients, is guaranteed to factor the polynomial into irreducible factors. <code>simplify&#40;&#41;</code> has no guarantees.  It is entirely heuristical, and, as we saw above, it may even miss a possible type of simplification that SymPy is capable of doing.</p>

<p><code>simplify&#40;&#41;</code> is best when used interactively, when you just want to whittle down an expression to a simpler form.  You may then choose to apply specific functions once you see what <code>simplify&#40;&#41;</code> returns, to get a more precise result.  It is also useful when you have no idea what form an expression will take, and you need a catchall function to simplify it.</p>

<h2>Polynomial/Rational Function Simplification</h2>

<h3>expand</h3>

<p><code>expand&#40;&#41;</code> is one of the most common simplification functions in SymPy. Although it has a lot of scopes, for now, we will consider its function in expanding polynomial expressions. For example:</p>


```julia
    >>> expand((x + 1)**2)
     2
    x  + 2⋅x + 1
    >>> expand((x + 2)*(x - 3))
     2
    x  - x - 6
```

<h5>In <code>Julia</code>:</h5>


```julia
expand((x + 1)^2)
```




\begin{equation*}x^{2} + 2 x + 1\end{equation*}




```julia
expand((x + 2)*(x - 3))
```




\begin{equation*}x^{2} - x - 6\end{equation*}



<hr />

<p>Given a polynomial, <code>expand&#40;&#41;</code> will put it into a canonical form of a sum of monomials.</p>

<p><code>expand&#40;&#41;</code> may not sound like a simplification function.  After all, by its very name, it makes expressions bigger, not smaller.  Usually this is the case, but often an expression will become smaller upon calling <code>expand&#40;&#41;</code> on it due to cancellation.</p>


```julia
    >>> expand((x + 1)*(x - 2) - (x - 1)*x)
    -2
```

<h5>In <code>Julia</code>:</h5>


```julia
expand((x + 1)*(x - 2) - (x - 1)*x)
```




\begin{equation*}-2\end{equation*}



<hr />

<h3>factor</h3>

<p><code>factor&#40;&#41;</code> takes a polynomial and factors it into irreducible factors over the rational numbers.  For example:</p>


```julia
    >>> factor(x**3 - x**2 + x - 1)
            ⎛ 2    ⎞
    (x - 1)⋅⎝x  + 1⎠
    >>> factor(x**2*z + 4*x*y*z + 4*y**2*z)
               2
    z⋅(x + 2⋅y)
```

<h5>In <code>Julia</code>:</h5>


```julia
factor(x^3 - x^2 + x - 1)
```




\begin{equation*}\left(x - 1\right) \left(x^{2} + 1\right)\end{equation*}




```julia
factor(x^2*z + 4*x*y*z + 4*y^2*z)
```




\begin{equation*}z \left(x + 2 y\right)^{2}\end{equation*}



<hr />

<p>For polynomials, <code>factor&#40;&#41;</code> is the opposite of <code>expand&#40;&#41;</code>.  <code>factor&#40;&#41;</code> uses a complete multivariate factorization algorithm over the rational numbers, which means that each of the factors returned by <code>factor&#40;&#41;</code> is guaranteed to be irreducible.</p>

<p>If you are interested in the factors themselves, <code>factor_list</code> returns a more structured output.</p>


```julia
    >>> factor_list(x**2*z + 4*x*y*z + 4*y**2*z)
    (1, [(z, 1), (x + 2⋅y, 2)])
```

<h5>In <code>Julia</code>:</h5>


```julia
factor_list(x^2*z + 4*x*y*z + 4*y^2*z)
```




    (1, Tuple{SymPy.Sym,Int64}[(z, 1), (x + 2*y, 2)])



<hr />

<p>Note that the input to <code>factor</code> and <code>expand</code> need not be polynomials in the strict sense.  They will intelligently factor or expand any kind of expression (though note that the factors may not be irreducible if the input is no longer a polynomial over the rationals).</p>


```julia
    >>> expand((cos(x) + sin(x))**2)
       2                           2
    sin (x) + 2⋅sin(x)⋅cos(x) + cos (x)
    >>> factor(cos(x)**2 + 2*cos(x)*sin(x) + sin(x)**2)
                     2
    (sin(x) + cos(x))
```

<h5>In <code>Julia</code>:</h5>


```julia
expand((cos(x) + sin(x))^2)
factor(cos(x)^2 + 2*cos(x)*sin(x) + sin(x)^2)
```




\begin{equation*}\left(\sin{\left (x \right )} + \cos{\left (x \right )}\right)^{2}\end{equation*}



<hr />

<h3>collect</h3>

<p><code>collect&#40;&#41;</code> collects common powers of a term in an expression.  For example</p>


```julia
    >>> expr = x*y + x - 3 + 2*x**2 - z*x**2 + x**3
    >>> expr
     3    2        2
    x  - x ⋅z + 2⋅x  + x⋅y + x - 3
    >>> collected_expr = collect(expr, x)
    >>> collected_expr
     3    2
    x  + x ⋅(-z + 2) + x⋅(y + 1) - 3
```

<h5>In <code>Julia</code>:</h5>


```julia
expr = x*y + x - 3 + 2*x^2 - z*x^2 + x^3
expr
```




\begin{equation*}x^{3} - x^{2} z + 2 x^{2} + x y + x - 3\end{equation*}




```julia
collected_expr = collect(expr, x)
collected_expr
```




\begin{equation*}x^{3} + x^{2} \left(- z + 2\right) + x \left(y + 1\right) - 3\end{equation*}



<hr />

<p><code>collect&#40;&#41;</code> is particularly useful in conjunction with the <code>.coeff&#40;&#41;</code> method.  <code>expr.coeff&#40;x, n&#41;</code> gives the coefficient of <code>x**n</code> in <code>expr</code>:</p>


```julia
    >>> collected_expr.coeff(x, 2)
    -z + 2
```

<h5>In <code>Julia</code>:</h5>


```julia
collected_expr.coeff(x, 2)
```




\begin{equation*}- z + 2\end{equation*}



<hr />

<div class="admonition note"><p class="admonition-title">TODO</p><p>Discuss coeff method in more detail in some other section (maybe basic expression manipulation tools)</p>
</div>

<h3>cancel</h3>

<p><code>cancel&#40;&#41;</code> will take any rational function and put it into the standard canonical form, $\frac{p}{q}$, where $p$ and $q$ are expanded polynomials with no common factors, and the leading coefficients of $p$ and $q$ do not have denominators (i.e., are integers).</p>


```julia
    >>> cancel((x**2 + 2*x + 1)/(x**2 + x))
    x + 1
    ─────
      x

    >>> expr = 1/x + (3*x/2 - 2)/(x - 4)
    >>> expr
    3⋅x
    ─── - 2
     2        1
    ─────── + ─
     x - 4    x
    >>> cancel(expr)
       2
    3⋅x  - 2⋅x - 8
    ──────────────
         2
      2⋅x  - 8⋅x

    >>> expr = (x*y**2 - 2*x*y*z + x*z**2 + y**2 - 2*y*z + z**2)/(x**2 - 1)
    >>> expr
       2                2    2            2
    x⋅y  - 2⋅x⋅y⋅z + x⋅z  + y  - 2⋅y⋅z + z
    ───────────────────────────────────────
                      2
                     x  - 1
    >>> cancel(expr)
     2            2
    y  - 2⋅y⋅z + z
    ───────────────
         x - 1
```

<h5>In <code>Julia</code>:</h5>


```julia
cancel((x^2 + 2*x + 1)/(x^2 + x))
```




\begin{equation*}\frac{x + 1}{x}\end{equation*}




```julia
expr = 1/x + (3*x/2 - 2)/(x - 4)
expr
```




\begin{equation*}\frac{\frac{3 x}{2} - 2}{x - 4} + \frac{1}{x}\end{equation*}




```julia
cancel(expr)
```




\begin{equation*}\frac{3 x^{2} - 2 x - 8}{2 x^{2} - 8 x}\end{equation*}




```julia
expr = (x*y^2 - 2*x*y*z + x*z^2 + y^2 - 2*y*z + z^2)/(x^2 - 1)
expr
cancel(expr)
```




\begin{equation*}\frac{y^{2} - 2 y z + z^{2}}{x - 1}\end{equation*}



<hr />

<p>Note that since <code>factor&#40;&#41;</code> will completely factorize both the numerator and the denominator of an expression, it can also be used to do the same thing:</p>


```julia
    >>> factor(expr)
           2
    (y - z)
    ────────
     x - 1
```

<h5>In <code>Julia</code>:</h5>


```julia
factor(expr)
```




\begin{equation*}\frac{\left(y - z\right)^{2}}{x - 1}\end{equation*}



<hr />

<p>However, if you are only interested in making sure that the expression is in canceled form, <code>cancel&#40;&#41;</code> is more efficient than <code>factor&#40;&#41;</code>.</p>

<h3>apart</h3>

<p><code>apart&#40;&#41;</code> performs a <code>partial fraction decomposition &lt;http://en.wikipedia.org/wiki/Partial_fraction_decomposition&gt;</code>_ on a rational function.</p>


```julia
    >>> expr = (4*x**3 + 21*x**2 + 10*x + 12)/(x**4 + 5*x**3 + 5*x**2 + 4*x)
    >>> expr
       3       2
    4⋅x  + 21⋅x  + 10⋅x + 12
    ────────────────────────
      4      3      2
     x  + 5⋅x  + 5⋅x  + 4⋅x
    >>> apart(expr)
     2⋅x - 1       1     3
    ────────── - ───── + ─
     2           x + 4   x
    x  + x + 1
```

<h5>In <code>Julia</code>:</h5>


```julia
expr = (4*x^3 + 21*x^2 + 10*x + 12)/(x^4 + 5*x^3 + 5*x^2 + 4*x)
expr
```




\begin{equation*}\frac{4 x^{3} + 21 x^{2} + 10 x + 12}{x^{4} + 5 x^{3} + 5 x^{2} + 4 x}\end{equation*}




```julia
apart(expr)
```




\begin{equation*}\frac{2 x - 1}{x^{2} + x + 1} - \frac{1}{x + 4} + \frac{3}{x}\end{equation*}



<hr />

<h2>Trigonometric Simplification</h2>

<div class="admonition note"><p class="admonition-title">Note</p><p>SymPy follows Python's naming conventions for inverse trigonometric functions, which is to append an <code>a</code> to the front of the function's name.  For example, the inverse cosine, or arc cosine, is called <code>acos&#40;&#41;</code>.</p>
</div>


```julia
   >>> acos(x)
   acos(x)
   >>> cos(acos(x))
   x
   >>> asin(1)
   π
   ─
   2
```

<h5>In <code>Julia</code>:</h5>


```julia
acos(x)
```




\begin{equation*}\operatorname{acos}{\left (x \right )}\end{equation*}




```julia
cos(acos(x))
```




\begin{equation*}x\end{equation*}




```julia
asin(1)
```




    1.5707963267948966



<hr />

<div class="admonition note"><p class="admonition-title">TODO</p><p>Can we actually do anything with inverse trig functions, simplification wise?</p>
</div>

<h3>trigsimp</h3>

<p>To simplify expressions using trigonometric identities, use <code>trigsimp&#40;&#41;</code>.</p>


```julia
    >>> trigsimp(sin(x)^2 + cos(x)**2)
    1
    >>> trigsimp(sin(x)**4 - 2*cos(x)**2*sin(x)**2 + cos(x)**4)
    cos(4⋅x)   1
    ──────── + ─
       2       2
    >>> trigsimp(sin(x)*tan(x)/sec(x))
       2
    sin (x)
```

<h5>In <code>Julia</code>:</h5>


```julia
trigsimp(sin(x)^2 + cos(x)^2)
```




\begin{equation*}1\end{equation*}




```julia
trigsimp(sin(x)^4 - 2*cos(x)^2*sin(x)^2 + cos(x)^4)
```




\begin{equation*}\frac{\cos{\left (4 x \right )}}{2} + \frac{1}{2}\end{equation*}




```julia
trigsimp(sin(x)*tan(x)/sec(x))
```




\begin{equation*}\sin^{2}{\left (x \right )}\end{equation*}



<hr />

<p><code>trigsimp&#40;&#41;</code> also works with hyperbolic trig functions.</p>


```julia
    >>> trigsimp(cosh(x)**2 + sinh(x)**2)
    cosh(2⋅x)
    >>> trigsimp(sinh(x)/tanh(x))
    cosh(x)
```

<h5>In <code>Julia</code>:</h5>


```julia
trigsimp(cosh(x)^2 + sinh(x)^2)
```




\begin{equation*}\cosh{\left (2 x \right )}\end{equation*}




```julia
trigsimp(sinh(x)/tanh(x))
```




\begin{equation*}\cosh{\left (x \right )}\end{equation*}



<hr />

<p>Much like <code>simplify&#40;&#41;</code>, <code>trigsimp&#40;&#41;</code> applies various trigonometric identities to the input expression, and then uses a heuristic to return the "best" one.</p>

<h3>expand_trig</h3>

<p>To expand trigonometric functions, that is, apply the sum or double angle identities, use <code>expand_trig&#40;&#41;</code>.</p>


```julia
    >>> expand_trig(sin(x + y))
    sin(x)⋅cos(y) + sin(y)⋅cos(x)
    >>> expand_trig(tan(2*x))
       2⋅tan(x)
    ─────────────
         2
    - tan (x) + 1
```

<h5>In <code>Julia</code>:</h5>


```julia
expand_trig(sin(x + y))
```




\begin{equation*}\sin{\left (x \right )} \cos{\left (y \right )} + \sin{\left (y \right )} \cos{\left (x \right )}\end{equation*}




```julia
expand_trig(tan(2*x))
```




\begin{equation*}\frac{2 \tan{\left (x \right )}}{- \tan^{2}{\left (x \right )} + 1}\end{equation*}



<hr />

<p>Because <code>expand_trig&#40;&#41;</code> tends to make trigonometric expressions larger, and <code>trigsimp&#40;&#41;</code> tends to make them smaller, these identities can be applied in reverse using <code>trigsimp&#40;&#41;</code></p>


```julia
    >>> trigsimp(sin(x)*cos(y) + sin(y)*cos(x))
    sin(x + y)
```

<h5>In <code>Julia</code>:</h5>


```julia
trigsimp(sin(x)*cos(y) + sin(y)*cos(x))
```




\begin{equation*}\sin{\left (x + y \right )}\end{equation*}



<hr />

<div class="admonition note"><p class="admonition-title">TODO</p><p>It would be much better to teach individual trig rewriting functions here, but they don't exist yet.  See https://github.com/sympy/sympy/issues/3456.</p>
</div>

<h2>Powers</h2>

<p>Before we introduce the power simplification functions, a mathematical discussion on the identities held by powers is in order.  There are three kinds of identities satisfied by exponents</p>

<ol>
<li><p><code>x^ax^b &#61; x^&#123;a &#43; b&#125;</code></p>
</li>
<li><p><code>x^ay^a &#61; &#40;xy&#41;^a</code></p>
</li>
<li><p><code>&#40;x^a&#41;^b &#61; x^&#123;ab&#125;</code></p>
</li>
</ol>

<p>Identity 1 is always true.</p>

<p>Identity 2 is not always true.  For example, if $x = y = -1$ and $a = \frac{1}{2}$, then $x^ay^a = \sqrt{-1}\sqrt{-1} = i\cdot i = -1$, whereas $(xy)^a = \sqrt{-1\cdot-1} = \sqrt{1} = 1$.  However, identity 2 is true at least if $x$ and $y$ are nonnegative and $a$ is real (it may also be true under other conditions as well).  A common consequence of the failure of identity 2 is that $\sqrt{x}\sqrt{y} \neq \sqrt{xy}$.</p>

<p>Identity 3 is not always true.  For example, if $x = -1$, $a = 2$, and $b = \frac{1}{2}$, then $(x^a)^b = {\left ((-1)^2\right )}^{1/2} = \sqrt{1} = 1$ and $x^{ab} = (-1)^{2\cdot1/2} = (-1)^1 = -1$.  However, identity 3 is true when $b$ is an integer (again, it may also hold in other cases as well).  Two common consequences of the failure of identity 3 are that $\sqrt{x^2}\neq x$ and that $\sqrt{\frac{1}{x}} \neq \frac{1}{\sqrt{x}}$.</p>

<p>To summarize</p>

<ol>
<li><p>This: $x^ax^b = x^{a + b}$ is always true</p>
</li>
<li><p>This: $x^ay^a = (xy)^a$ is true when  $x, y \geq 0$ and $a \in \mathbb{R}$; but note $(-1)^{1/2}(-1)^{1/2} \neq (-1\cdot-1)^{1/2}$       and $\sqrt{x}\sqrt{y} \neq \sqrt{xy}$ in general</p>
</li>
<li><p>This: $(x^a)^b = x^{ab}$  when $b \in \mathbb{Z}$;                  but note ${\left((-1)^2\right )}^{1/2} \neq (-1)^{2\cdot1/2}$ and $\sqrt{x^2}\neq x$ and $\sqrt{\frac{1}{x}}\neq\frac{1}{\sqrt{x}}$ in general</p>
</li>
</ol>

<p>This is important to remember, because by default, SymPy will not perform simplifications if they are not true in general.</p>

<p>In order to make SymPy perform simplifications involving identities that are only true under certain assumptions, we need to put assumptions on our Symbols.  We will undertake a full discussion of the assumptions system later, but for now, all we need to know are the following.</p>

<ul>
<li><p>By default, SymPy Symbols are assumed to be complex (elements of $\mathbb{C}$).  That is, a simplification will not be applied to an expression with a given Symbol unless it holds for all complex numbers.</p>
</li>
<li><p>Symbols can be given different assumptions by passing the assumption to <code>symbols&#40;&#41;</code>.  For the rest of this section, we will be assuming that <code>x</code> and <code>y</code> are positive, and that <code>a</code> and <code>b</code> are real.  We will leave <code>z</code>, <code>t</code>, and <code>c</code> as arbitrary complex Symbols to demonstrate what happens in that case.</p>
</li>
</ul>


```julia
    >>> x, y = symbols('x y', positive=True)
    >>> a, b = symbols('a b', real=True)
    >>> z, t, c = symbols('z t c')
```

<h5>In <code>Julia</code>:</h5>


```julia
x, y = symbols("x y", positive=true)
a, b = symbols("a b", real=true)
z, t, c = symbols("z t c")
```




    (z, t, c)



<hr />

<div class="admonition note"><p class="admonition-title">TODO:</p><p>Rewrite this using the new assumptions</p>
</div>

<div class="admonition note"><p class="admonition-title">Note</p><p>In SymPy, <code>sqrt&#40;x&#41;</code> is just a shortcut to <code>x**Rational&#40;1, 2&#41;</code>.  They are exactly the same object.</p>
</div>


```julia
     >>> sqrt(x) == x**Rational(1, 2)
     True
```

<h5>In <code>Julia</code>:</h5>

<ul>
<li><p>we can construction rational numbers with <code>//</code></p>
</li>
</ul>


```julia
sqrt(x) == x^(1//2)
```




    true



<hr />

<h2>powsimp</h2>

<p><code>powsimp&#40;&#41;</code> applies identities 1 and 2 from above, from left to right.</p>


```julia
   >>> powsimp(x**a*x**b)
     a + b
    x
   >>> powsimp(x**a*y**a)
        a
   (x⋅y)
```

<h5>In <code>Julia</code>:</h5>


```julia
powsimp(x^a*x^b)
powsimp(x^a*y^a)
```




\begin{equation*}\left(x y\right)^{a}\end{equation*}



<hr />

<p>Notice that <code>powsimp&#40;&#41;</code> refuses to do the simplification if it is not valid.</p>


```julia
    >>> powsimp(t**c*z**c)
     c  c
    t ⋅z
```

<h5>In <code>Julia</code>:</h5>


```julia
powsimp(t^c*z^c)
```




\begin{equation*}t^{c} z^{c}\end{equation*}



<hr />

<p>If you know that you want to apply this simplification, but you don't want to mess with assumptions, you can pass the <code>force&#61;True</code> flag.  This will force the simplification to take place, regardless of assumptions.</p>


```julia
    >>> powsimp(t**c*z**c, force=True)
         c
    (t⋅z)
```

<h5>In <code>Julia</code>:</h5>


```julia
powsimp(t^c*z^c, force=true)
```




\begin{equation*}\left(t z\right)^{c}\end{equation*}



<hr />

<p>Note that in some instances, in particular, when the exponents are integers or rational numbers, and identity 2 holds, it will be applied automatically.</p>


```julia
   >>> (z*t)**2
     2  2
    t ⋅z
   >>> sqrt(x*y)
    √x⋅√y
```

<h5>In <code>Julia</code>:</h5>


```julia
(z*t)^2
```




\begin{equation*}t^{2} z^{2}\end{equation*}




```julia
sqrt(x*y)
```




\begin{equation*}\sqrt{x} \sqrt{y}\end{equation*}



<hr />

<p>This means that it will be impossible to undo this identity with <code>powsimp&#40;&#41;</code>, because even if <code>powsimp&#40;&#41;</code> were to put the bases together, they would be automatically split apart again.</p>


```julia
   >>> powsimp(z**2*t**2)
     2  2
    t ⋅z
   >>> powsimp(sqrt(x)*sqrt(y))
    √x⋅√y
```

<h5>In <code>Julia</code>:</h5>


```julia
powsimp(z^2*t^2)
```




\begin{equation*}t^{2} z^{2}\end{equation*}




```julia
powsimp(sqrt(x)*sqrt(y))
```




\begin{equation*}\sqrt{x} \sqrt{y}\end{equation*}



<hr />

<h3><code>expand_power_exp</code> / <code>expand_power_base</code></h3>

<p><code>expand_power_exp&#40;&#41;</code> and <code>expand_power_base&#40;&#41;</code> apply identities 1 and 2 from right to left, respectively.</p>


```julia
    >>> expand_power_exp(x**(a + b))
     a  b
    x ⋅x

    >>> expand_power_base((x*y)**a)
     a  a
    x ⋅y
```

<h5>In <code>Julia</code>:</h5>


```julia
expand_power_exp(x^(a + b))
expand_power_base((x*y)^a)
```




\begin{equation*}x^{a} y^{a}\end{equation*}



<hr />

<p>As with <code>powsimp&#40;&#41;</code>, identity 2 is not applied if it is not valid.</p>


```julia
    >>> expand_power_base((z*t)**c)
         c
    (t⋅z)
```

<h5>In <code>Julia</code>:</h5>


```julia
expand_power_base((z*t)^c)
```




\begin{equation*}\left(t z\right)^{c}\end{equation*}



<hr />

<p>And as with <code>powsimp&#40;&#41;</code>, you can force the expansion to happen without fiddling with assumptions by using <code>force&#61;True</code>.</p>


```julia
   >>> expand_power_base((z*t)**c, force=True)
     c  c
    t ⋅z
```

<h5>In <code>Julia</code>:</h5>


```julia
expand_power_base((z*t)^c, force=true)
```




\begin{equation*}t^{c} z^{c}\end{equation*}



<hr />

<p>As with identity 2, identity 1 is applied automatically if the power is a number, and hence cannot be undone with <code>expand_power_exp&#40;&#41;</code>.</p>


```julia
   >>> x**2*x**3
     5
    x
   >>> expand_power_exp(x**5)
     5
    x
```

<h5>In <code>Julia</code>:</h5>


```julia
x^2*x^3
expand_power_exp(x^5)
```




\begin{equation*}x^{5}\end{equation*}



<hr />

<h3>powdenest</h3>

<p><code>powdenest&#40;&#41;</code> applies identity 3, from left to right.</p>


```julia
    >>> powdenest((x**a)**b)
     a⋅b
    x
```

<h5>In <code>Julia</code>:</h5>


```julia
powdenest((x^a)^b)
```




\begin{equation*}x^{a b}\end{equation*}



<hr />

<p>As before, the identity is not applied if it is not true under the given assumptions.</p>


```julia
    >>> powdenest((z**a)**b)
        b
    ⎛ a⎞
    ⎝z ⎠
```

<h5>In <code>Julia</code>:</h5>


```julia
powdenest((z^a)^b)
```




\begin{equation*}\left(z^{a}\right)^{b}\end{equation*}



<hr />

<p>And as before, this can be manually overridden with <code>force&#61;True</code>.</p>


```julia
    >>> powdenest((z**a)**b, force=True)
     a⋅b
    z
```

<h5>In <code>Julia</code>:</h5>


```julia
powdenest((z^a)^b, force=true)
```




\begin{equation*}z^{a b}\end{equation*}



<hr />

<h2>Exponentials and logarithms</h2>

<div class="admonition note"><p class="admonition-title">Note</p><p>In SymPy, as in Python and most programming languages, <code>log</code> is the natural logarithm, also known as <code>ln</code>.  SymPy automatically provides an alias <code>ln &#61; log</code> in case you forget this.</p>
</div>


```julia
    >>> ln(x)
    log(x)
```

<h5>In <code>Julia</code>:</h5>

<ul>
<li><p><code>ln</code> is exported</p>
</li>
</ul>


```julia
ln(x)
```




\begin{equation*}\log{\left (x \right )}\end{equation*}



<hr />

<p>Logarithms have similar issues as powers.  There are two main identities</p>

<ol>
<li>$\log{(xy)} = \log{(x)} + \log{(y)}$
</li>
<li>$\log{(x^n)} = n\log{(x)}$
</li>
</ol>

<p>Neither identity is true for arbitrary complex $x$ and $y$, due to the branch cut in the complex plane for the complex logarithm.  However, sufficient conditions for the identities to hold are if $x$ and $y$ are positive and $n$ is real.</p>


```julia
    >>> x, y = symbols('x y', positive=True)
    >>> n = symbols('n', real=True)
```

<h5>In <code>Julia</code>:</h5>


```julia
x, y = symbols("x y", positive=true)
n = symbols("n", real=true)
```




\begin{equation*}n\end{equation*}



<hr />

<p>As before, <code>z</code> and <code>t</code> will be Symbols with no additional assumptions.</p>

<p>Note that the identity $\log{\left (\frac{x}{y}\right )} = \log(x) - \log(y)$ is a special case of identities 1 and 2 by $\log{\left (\frac{x}{y}\right )} =$ $\log{\left (x\cdot\frac{1}{y}\right )} =$ $\log(x) + \log{\left( y^{-1}\right )} =$ $\log(x) - \log(y)$, and thus it also holds if <code>x</code> and <code>y</code> are positive, but may not hold in general.</p>

<p>We also see that $\log{\left( e^x \right)} = x$ comes from $\log{\left ( e^x \right)} = x\log(e) = x$, and thus holds when $x$ is real (and it can be verified that it does not hold in general for arbitrary complex $x$, for example, $\log{\left (e^{x + 2\pi i}\right)} = \log{\left (e^x\right )} = x \neq x + 2\pi i$).</p>

<h2>expand_log</h2>

<p>To apply identities 1 and 2 from left to right, use <code>expand_log&#40;&#41;</code>.  As always, the identities will not be applied unless they are valid.</p>


```julia
    >>> expand_log(log(x*y))
    log(x) + log(y)
    >>> expand_log(log(x/y))
    log(x) - log(y)
    >>> expand_log(log(x**2))
    2⋅log(x)
    >>> expand_log(log(x**n))
    n⋅log(x)
    >>> expand_log(log(z*t))
    log(t⋅z)
```

<h5>In <code>Julia</code>:</h5>


```julia
expand_log(log(x*y))
```




\begin{equation*}\log{\left (x \right )} + \log{\left (y \right )}\end{equation*}




```julia
expand_log(log(x/y))
```




\begin{equation*}\log{\left (x \right )} - \log{\left (y \right )}\end{equation*}




```julia
expand_log(log(x^2))
```




\begin{equation*}2 \log{\left (x \right )}\end{equation*}




```julia
expand_log(log(x^n))
```




\begin{equation*}n \log{\left (x \right )}\end{equation*}




```julia
expand_log(log(z*t))
```




\begin{equation*}\log{\left (t z \right )}\end{equation*}



<hr />

<p>As with <code>powsimp&#40;&#41;</code> and <code>powdenest&#40;&#41;</code>, <code>expand_log&#40;&#41;</code> has a <code>force</code> option that can be used to ignore assumptions.</p>


```julia
    >>> expand_log(log(z**2))
       ⎛ 2⎞
    log⎝z ⎠
    >>> expand_log(log(z**2), force=True)
    2⋅log(z)
```

<h5>In <code>Julia</code>:</h5>


```julia
expand_log(log(z^2))
```




\begin{equation*}\log{\left (z^{2} \right )}\end{equation*}




```julia
expand_log(log(z^2), force=true)
```




\begin{equation*}2 \log{\left (z \right )}\end{equation*}



<hr />

<h2>logcombine</h2>

<p>To apply identities 1 and 2 from right to left, use <code>logcombine&#40;&#41;</code>.</p>


```julia
    >>> logcombine(log(x) + log(y))
    log(x⋅y)
    >>> logcombine(n*log(x))
       ⎛ n⎞
    log⎝x ⎠
    >>> logcombine(n*log(z))
    n⋅log(z)
```

<h5>In <code>Julia</code>:</h5>


```julia
logcombine(log(x) + log(y))
logcombine(n*log(x))
logcombine(n*log(z))
```




\begin{equation*}n \log{\left (z \right )}\end{equation*}



<hr />

<p><code>logcombine&#40;&#41;</code> also has a <code>force</code> option that can be used to ignore assumptions.</p>


```julia
    >>> logcombine(n*log(z), force=True)
       ⎛ n⎞
    log⎝z ⎠
```

<h5>In <code>Julia</code>:</h5>


```julia
logcombine(n*log(z), force=true)
```




\begin{equation*}\log{\left (z^{n} \right )}\end{equation*}



<hr />

<h2>Special Functions</h2>

<p>SymPy implements dozens of special functions, ranging from functions in combinatorics to mathematical physics.</p>

<p>An extensive list of the special functions included with SymPy and their documentation is at the :ref:<code>Functions Module &lt;functions-contents&gt;</code> page.</p>

<p>For the purposes of this tutorial, let's introduce a few special functions in SymPy.</p>

<p>Let's define <code>x</code>, <code>y</code>, and <code>z</code> as regular, complex Symbols, removing any assumptions we put on them in the previous section.  We will also define <code>k</code>, <code>m</code>, and <code>n</code>.</p>


```julia
    >>> x, y, z = symbols('x y z')
    >>> k, m, n = symbols('k m n')
```

<h5>In <code>Julia</code>:</h5>


```julia
x, y, z = symbols("x y z")
k, m, n = symbols("k m n")
```




    (k, m, n)



<hr />

<p>The <code>factorial &lt;http://en.wikipedia.org/wiki/Factorial&gt;</code>_ function is <code>factorial</code>.  <code>factorial&#40;n&#41;</code> represents $n!= 1\cdot2\cdots(n - 1)\cdot n$. <code>n&#33;</code> represents the number of permutations of <code>n</code> distinct items.</p>


```julia
    >>> factorial(n)
    n!
```

<h5>In <code>Julia</code>:</h5>


```julia
factorial(n)
```




\begin{equation*}n!\end{equation*}



<hr />

<p>The <code>binomial coefficient &lt;http://en.wikipedia.org/wiki/Binomial_coefficient&gt;</code>_ function is <code>binomial</code>.  <code>binomial&#40;n, k&#41;</code> represents $\binom{n}{k}$, the number of ways to choose <code>k</code> items from a set of <code>n</code> distinct items.  It is also often written as <code>nCk</code>, and is pronounced "<code>n</code> choose <code>k</code>".</p>


```julia
    >>> binomial(n, k)
    ⎛n⎞
    ⎜ ⎟
    ⎝k⎠
```

<h5>In <code>Julia</code>:</h5>


```julia
binomial(n, k)
```




\begin{equation*}{\binom{n}{k}}\end{equation*}



<hr />

<p>The factorial function is closely related to the <code>gamma function &lt;http://en.wikipedia.org/wiki/Gamma_function&gt;</code><em>, <code>gamma</code>.  <code>gamma&#40;z&#41;</code> represents \Gamma(z) = \int</em>0^\infty t^{z - 1}e^{-t}\,dt$, which for positive integer <code>z</code> is the same as <code>&#40;z - 1&#41;&#33;</code>.</p>


```julia
    >>> gamma(z)
    Γ(z)
```

<h5>In <code>Julia</code>:</h5>

<ul>
<li><p>recall, we need to load <code>SpecialFunctions</code> for <code>gamma</code> to be available</p>
</li>
</ul>


```julia
gamma(z)
```




\begin{equation*}\Gamma\left(z\right)\end{equation*}



<hr />

<p>The <code>generalized hypergeometric function &lt;http://en.wikipedia.org/wiki/Generalized_hypergeometric_function&gt;</code> is <code>hyper</code>.  <code>hyper&#40;&#91;a_1, ..., a_p&#93;, &#91;b_1, ..., b_q&#93;, z&#41;</code> represents ${}_pF_q\left(\begin{matrix} a_1, \cdots, a_p \\ b_1, \cdots, b_q \end{matrix} \middle| z \right)$.  The most common case is ${}_2F_1$, which is often referred to as the <code>ordinary hypergeometric function &lt;http://en.wikipedia.org/wiki/Hypergeometric_function&gt;</code>.</p>


```julia
    >>> hyper([1, 2], [3], z)
     ┌─  ⎛1, 2 │  ⎞
     ├─  ⎜     │ z⎟
    2╵ 1 ⎝ 3   │  ⎠
```

<h5>In <code>Julia</code>:</h5>

<ul>
<li><p>as <code>&#91;1,2&#93;</code> is not symbolic, we qualify <code>hyper</code></p>
</li>
</ul>


```julia
sympy.hyper([1, 2], [3], z)
```




\begin{equation*}{{}_{2}F_{1}\left(\begin{matrix} 1, 2 \\ 3 \end{matrix}\middle| {z} \right)}\end{equation*}



<hr />

<h2>rewrite</h2>

<p>A common way to deal with special functions is to rewrite them in terms of one another.  This works for any function in SymPy, not just special functions. To rewrite an expression in terms of a function, use <code>expr.rewrite&#40;function&#41;</code>.  For example,</p>


```julia
    >>> tan(x).rewrite(sin)
         2
    2⋅sin (x)
    ─────────
     sin(2⋅x)
    >>> factorial(x).rewrite(gamma)
    Γ(x + 1)
```

<h5>In <code>Julia</code>:</h5>


```julia
tan(x).rewrite(sin)
```




\begin{equation*}\frac{2 \sin^{2}{\left (x \right )}}{\sin{\left (2 x \right )}}\end{equation*}




```julia
factorial(x).rewrite(gamma)
```




\begin{equation*}x!\end{equation*}



<hr />

<p>For some tips on applying more targeted rewriting, see the :ref:<code>tutorial-manipulation</code> section.</p>

<h3>expand_func</h3>

<p>To expand special functions in terms of some identities, use <code>expand_func&#40;&#41;</code>.  For example</p>


```julia
    >>> expand_func(gamma(x + 3))
    x⋅(x + 1)⋅(x + 2)⋅Γ(x)
```

<h5>In <code>Julia</code>:</h5>


```julia
expand_func(gamma(x + 3))
```




\begin{equation*}x \left(x + 1\right) \left(x + 2\right) \Gamma\left(x\right)\end{equation*}



<hr />

<h2>hyperexpand</h2>

<p>To rewrite <code>hyper</code> in terms of more standard functions, use <code>hyperexpand&#40;&#41;</code>.</p>


```julia
    >>> hyperexpand(hyper([1, 1], [2], z))
    -log(-z + 1)
    ─────────────
         z
```

<h5>In <code>Julia</code>:</h5>

<ul>
<li><p>As <code>&#91;1,1&#93;</code> is not symbolic, we qualify <code>hyperexpand</code>:</p>
</li>
</ul>


```julia
sympy.hyperexpand(hyper([1, 1], [2], z))
```




    MethodError(SymPy.hyper, ([1, 1], [2], z), 0x000000000000827e)




<hr />

<p><code>hyperexpand&#40;&#41;</code> also works on the more general Meijer G-function (see :py:meth:<code>its documentation &lt;sympy.functions.special.hyper.meijerg&gt;</code> for more information).</p>


```julia
    >>> expr = meijerg([[1],[1]], [[1],[]], -z)
    >>> expr
    ╭─╮1, 1 ⎛1  1 │   ⎞
    │╶┐     ⎜     │ -z⎟
    ╰─╯2, 1 ⎝1    │   ⎠
    >>> hyperexpand(expr)
     1
     ─
     z
    ℯ
```

<h5>In <code>Julia</code>:</h5>

<ul>
<li><p>again, we qualify <code>meijerg</code></p>
</li>
</ul>


```julia
expr = sympy.meijerg([[1],[1]], [[1],[]], -z)
expr
```




\begin{equation*}{G_{2, 1}^{1, 1}\left(\begin{matrix} 1 & 1 \\1 &  \end{matrix} \middle| {- z} \right)}\end{equation*}




```julia
hyperexpand(expr)
```




\begin{equation*}e^{\frac{1}{z}}\end{equation*}



<hr />

<h3>combsimp</h3>

<p>To simplify combinatorial expressions, use <code>combsimp&#40;&#41;</code>.</p>


```julia
    >>> n, k = symbols('n k', integer = True)
    >>> combsimp(factorial(n)/factorial(n - 3))
    n⋅(n - 2)⋅(n - 1)
    >>> combsimp(binomial(n+1, k+1)/binomial(n, k))
    n + 1
    ─────
    k + 1
```

<h5>In <code>Julia</code>:</h5>


```julia
n, k = symbols("n k", integer = true)
```




    (n, k)




```julia
combsimp(factorial(n)/factorial(n - 3))
```




\begin{equation*}n \left(n - 2\right) \left(n - 1\right)\end{equation*}




```julia
combsimp(binomial(n+1, k+1)/binomial(n, k))
```




\begin{equation*}\frac{n + 1}{k + 1}\end{equation*}



<hr />

<h3>gammasimp</h3>

<p>To simplify expressions with gamma functions or combinatorial functions with non-integer argument, use <code>gammasimp&#40;&#41;</code>.</p>


```julia
    >>> gammasimp(gamma(x)*gamma(1 - x))
       π
    ────────
    sin(π⋅x)
```

<h5>In <code>Julia</code>:</h5>


```julia
gammasimp(gamma(x)*gamma(1 - x))
```




\begin{equation*}\frac{\pi}{\sin{\left (\pi x \right )}}\end{equation*}



<hr />

<h3>Example: Continued Fractions</h3>

<p>Let's use SymPy to explore continued fractions.  A <code>continued fraction &lt;http://en.wikipedia.org/wiki/Continued_fraction&gt;</code>_ is an expression of the form</p>


$$
   a_0 + \cfrac{1}{a_1 + \cfrac{1}{a_2 + \cfrac{1}{ \ddots + \cfrac{1}{a_n}
   }}}
   $$


<p>where $a_0, \ldots, a_n$ are integers, and $a_1, \ldots, a_n$ are positive. Acontinued fraction can also be infinite, but infinite objects are more difficult to represent in computers, so we will only examine the finite case here.</p>

<p>A continued fraction of the above form is often represented as a list $[a_0; a_1, \ldots, a_n]$.  Let's write a simple function that converts such a list to its continued fraction form.  The easiest way to construct a continued fraction from a list is to work backwards.  Note that despite the apparent symmetry of the definition, the first element, <code>a_0</code>, must usually be handled differently from the rest.</p>


```julia
    >>> def list_to_frac(l):
    ...     expr = Integer(0)
    ...     for i in reversed(l[1:]):
    ...         expr += i
    ...         expr = 1/expr
    ...     return l[0] + expr
    >>> list_to_frac([x, y, z])
          1
    x + ─────
            1
        y + ─
            z
```

<h5>In <code>Julia</code>:</h5>


```julia
function list_to_frac(l)
   expr = sympy.Integer(0)
   for i in reverse(l[1:end])
      expr += i
      expr = 1/expr
   end
   return l[1] + expr
end
list_to_frac([x, y, z])
```




\begin{equation*}x + \frac{1}{x + \frac{1}{y + \frac{1}{z}}}\end{equation*}



<hr />

<p>We use <code>Integer&#40;0&#41;</code> in <code>list_to_frac</code> so that the result will always be a SymPy object, even if we only pass in Python ints.</p>


```julia
    >>> list_to_frac([1, 2, 3, 4])
    43
    ──
    30
```

<h5>In <code>Julia</code>:</h5>


```julia
list_to_frac([1, 2, 3, 4])
```




\begin{equation*}\frac{73}{43}\end{equation*}



<hr />

<p>Every finite continued fraction is a rational number, but we are interested in symbolics here, so let's create a symbolic continued fraction.  The <code>symbols&#40;&#41;</code> function that we have been using has a shortcut to create numbered symbols.  <code>symbols&#40;&#39;a0:5&#39;&#41;</code> will create the symbols <code>a0</code>, <code>a1</code>, ..., <code>a4</code>.</p>


```julia
    >>> syms = symbols('a0:5')
    >>> syms
    (a₀, a₁, a₂, a₃, a₄)
    >>> a0, a1, a2, a3, a4 = syms
    >>> frac = list_to_frac(syms)
    >>> frac
                 1
    a₀ + ─────────────────
                   1
         a₁ + ────────────
                      1
              a₂ + ───────
                        1
                   a₃ + ──
                        a₄
```

<h5>In <code>Julia</code>:</h5>


```julia
syms = symbols("a0:5")
syms
```




    (a0, a1, a2, a3, a4)




```julia
a0, a1, a2, a3, a4 = syms
```




    (a0, a1, a2, a3, a4)




```julia
frac = list_to_frac(syms)
frac
```




\begin{equation*}a_{0} + \frac{1}{a_{0} + \frac{1}{a_{1} + \frac{1}{a_{2} + \frac{1}{a_{3} + \frac{1}{a_{4}}}}}}\end{equation*}



<hr />

<p>This form is useful for understanding continued fractions, but lets put it into standard rational function form using <code>cancel&#40;&#41;</code>.</p>


```julia
    >>> frac = cancel(frac)
    >>> frac
    a₀⋅a₁⋅a₂⋅a₃⋅a₄ + a₀⋅a₁⋅a₂ + a₀⋅a₁⋅a₄ + a₀⋅a₃⋅a₄ + a₀ + a₂⋅a₃⋅a₄ + a₂ + a₄
    ─────────────────────────────────────────────────────────────────────────
                     a₁⋅a₂⋅a₃⋅a₄ + a₁⋅a₂ + a₁⋅a₄ + a₃⋅a₄ + 1

```

<h5>In <code>Julia</code>:</h5>


```julia
frac = cancel(frac)
frac
```




\begin{equation*}\frac{a_{0}^{2} a_{1} a_{2} a_{3} a_{4} + a_{0}^{2} a_{1} a_{2} + a_{0}^{2} a_{1} a_{4} + a_{0}^{2} a_{3} a_{4} + a_{0}^{2} + a_{0} a_{2} a_{3} a_{4} + a_{0} a_{2} + a_{0} a_{4} + a_{1} a_{2} a_{3} a_{4} + a_{1} a_{2} + a_{1} a_{4} + a_{3} a_{4} + 1}{a_{0} a_{1} a_{2} a_{3} a_{4} + a_{0} a_{1} a_{2} + a_{0} a_{1} a_{4} + a_{0} a_{3} a_{4} + a_{0} + a_{2} a_{3} a_{4} + a_{2} + a_{4}}\end{equation*}



<hr />

<p>Now suppose we were given <code>frac</code> in the above canceled form. In fact, we might be given the fraction in any form, but we can always put it into the above canonical form with <code>cancel&#40;&#41;</code>.  Suppose that we knew that it could be rewritten as a continued fraction.  How could we do this with SymPy?  A continued fraction is recursively $c + \frac{1}{f}$, where $c$ is an integer and $f$ is a (smaller) continued fraction.  If we could write the expression in this form, we could pull out each $c$ recursively and add it to a list.  We could then get a continued fraction with our <code>list_to_frac&#40;&#41;</code> function.</p>

<p>The key observation here is that we can convert an expression to the form <code>c &#43; \frac&#123;1&#125;&#123;f&#125;</code> by doing a partial fraction decomposition with respect to <code>c</code>. This is because <code>f</code> does not contain <code>c</code>.  This means we need to use the <code>apart&#40;&#41;</code> function.  We use <code>apart&#40;&#41;</code> to pull the term out, then subtract it from the expression, and take the reciprocal to get the <code>f</code> part.</p>


```julia
    >>> l = []
    >>> frac = apart(frac, a0)
    >>> frac
                    a₂⋅a₃⋅a₄ + a₂ + a₄
    a₀ + ───────────────────────────────────────
         a₁⋅a₂⋅a₃⋅a₄ + a₁⋅a₂ + a₁⋅a₄ + a₃⋅a₄ + 1
    >>> l.append(a0)
    >>> frac = 1/(frac - a0)
    >>> frac
    a₁⋅a₂⋅a₃⋅a₄ + a₁⋅a₂ + a₁⋅a₄ + a₃⋅a₄ + 1
    ───────────────────────────────────────
               a₂⋅a₃⋅a₄ + a₂ + a₄
```

<h5>In <code>Julia</code>:</h5>


```julia
l = []
frac = apart(frac, a0)
frac
push!(l, append(a0))
frac = 1/(frac - a0)
frac
```




\begin{equation*}\frac{a_{0} a_{1} a_{2} a_{3} a_{4} + a_{0} a_{1} a_{2} + a_{0} a_{1} a_{4} + a_{0} a_{3} a_{4} + a_{0} + a_{2} a_{3} a_{4} + a_{2} + a_{4}}{a_{1} a_{2} a_{3} a_{4} + a_{1} a_{2} + a_{1} a_{4} + a_{3} a_{4} + 1}\end{equation*}



<hr />

<p>Now we repeat this process</p>


```julia
    >>> frac = apart(frac, a1)
    >>> frac
             a₃⋅a₄ + 1
    a₁ + ──────────────────
         a₂⋅a₃⋅a₄ + a₂ + a₄
    >>> l.append(a1)
    >>> frac = 1/(frac - a1)
    >>> frac = apart(frac, a2)
    >>> frac
             a₄
    a₂ + ─────────
         a₃⋅a₄ + 1
    >>> l.append(a2)
    >>> frac = 1/(frac - a2)
    >>> frac = apart(frac, a3)
    >>> frac
         1
    a₃ + ──
         a₄
    >>> l.append(a3)
    >>> frac = 1/(frac - a3)
    >>> frac = apart(frac, a4)
    >>> frac
    a₄
    >>> l.append(a4)
    >>> list_to_frac(l)
                 1
    a₀ + ─────────────────
                   1
         a₁ + ────────────
                      1
              a₂ + ───────
                        1
                   a₃ + ──
                        a₄
```

<h5>In <code>Julia</code>:</h5>


```julia
frac = apart(frac, a1)
frac
```




\begin{equation*}a_{0} + \frac{a_{2} a_{3} a_{4} + a_{2} + a_{4}}{a_{1} a_{2} a_{3} a_{4} + a_{1} a_{2} + a_{1} a_{4} + a_{3} a_{4} + 1}\end{equation*}




```julia
push!(l, a1)
frac = 1/(frac - a1)
```




\begin{equation*}\frac{1}{a_{0} - a_{1} + \frac{a_{2} a_{3} a_{4} + a_{2} + a_{4}}{a_{1} a_{2} a_{3} a_{4} + a_{1} a_{2} + a_{1} a_{4} + a_{3} a_{4} + 1}}\end{equation*}




```julia
frac = apart(frac, a2)
frac
```




\begin{equation*}\frac{a_{1}}{a_{0} a_{1} - a_{1}^{2} + 1} + \frac{a_{3} a_{4} + 1}{\left(a_{0} a_{1} - a_{1}^{2} + 1\right) \left(a_{0} a_{1} a_{2} a_{3} a_{4} + a_{0} a_{1} a_{2} + a_{0} a_{1} a_{4} + a_{0} a_{3} a_{4} + a_{0} - a_{1}^{2} a_{2} a_{3} a_{4} - a_{1}^{2} a_{2} - a_{1}^{2} a_{4} - a_{1} a_{3} a_{4} - a_{1} + a_{2} a_{3} a_{4} + a_{2} + a_{4}\right)}\end{equation*}




```julia
push!(l, a2)
frac = 1/(frac - a2)
```




\begin{equation*}\frac{1}{\frac{a_{1}}{a_{0} a_{1} - a_{1}^{2} + 1} - a_{2} + \frac{a_{3} a_{4} + 1}{\left(a_{0} a_{1} - a_{1}^{2} + 1\right) \left(a_{0} a_{1} a_{2} a_{3} a_{4} + a_{0} a_{1} a_{2} + a_{0} a_{1} a_{4} + a_{0} a_{3} a_{4} + a_{0} - a_{1}^{2} a_{2} a_{3} a_{4} - a_{1}^{2} a_{2} - a_{1}^{2} a_{4} - a_{1} a_{3} a_{4} - a_{1} + a_{2} a_{3} a_{4} + a_{2} + a_{4}\right)}}\end{equation*}




```julia
frac = apart(frac, a3)
frac
```




\begin{equation*}\frac{a_{4}}{\left(a_{0} a_{1} a_{2}^{2} + a_{0} a_{2} - a_{1}^{2} a_{2}^{2} - 2 a_{1} a_{2} + a_{2}^{2} - 1\right) \left(a_{0} a_{1} a_{2}^{2} a_{3} a_{4} + a_{0} a_{1} a_{2}^{2} + a_{0} a_{1} a_{2} a_{4} + a_{0} a_{2} a_{3} a_{4} + a_{0} a_{2} - a_{1}^{2} a_{2}^{2} a_{3} a_{4} - a_{1}^{2} a_{2}^{2} - a_{1}^{2} a_{2} a_{4} - 2 a_{1} a_{2} a_{3} a_{4} - 2 a_{1} a_{2} - a_{1} a_{4} + a_{2}^{2} a_{3} a_{4} + a_{2}^{2} + a_{2} a_{4} - a_{3} a_{4} - 1\right)} - \frac{a_{0} a_{1} a_{2} + a_{0} - a_{1}^{2} a_{2} - a_{1} + a_{2}}{a_{0} a_{1} a_{2}^{2} + a_{0} a_{2} - a_{1}^{2} a_{2}^{2} - 2 a_{1} a_{2} + a_{2}^{2} - 1}\end{equation*}




```julia
push!(l, a3)
frac = 1/(frac - a3)
```




\begin{equation*}\frac{1}{- a_{3} + \frac{a_{4}}{\left(a_{0} a_{1} a_{2}^{2} + a_{0} a_{2} - a_{1}^{2} a_{2}^{2} - 2 a_{1} a_{2} + a_{2}^{2} - 1\right) \left(a_{0} a_{1} a_{2}^{2} a_{3} a_{4} + a_{0} a_{1} a_{2}^{2} + a_{0} a_{1} a_{2} a_{4} + a_{0} a_{2} a_{3} a_{4} + a_{0} a_{2} - a_{1}^{2} a_{2}^{2} a_{3} a_{4} - a_{1}^{2} a_{2}^{2} - a_{1}^{2} a_{2} a_{4} - 2 a_{1} a_{2} a_{3} a_{4} - 2 a_{1} a_{2} - a_{1} a_{4} + a_{2}^{2} a_{3} a_{4} + a_{2}^{2} + a_{2} a_{4} - a_{3} a_{4} - 1\right)} - \frac{a_{0} a_{1} a_{2} + a_{0} - a_{1}^{2} a_{2} - a_{1} + a_{2}}{a_{0} a_{1} a_{2}^{2} + a_{0} a_{2} - a_{1}^{2} a_{2}^{2} - 2 a_{1} a_{2} + a_{2}^{2} - 1}}\end{equation*}




```julia
frac = apart(frac, a4)
frac
```




\begin{equation*}- \frac{a_{0} a_{1} a_{2}^{2} a_{3} + a_{0} a_{1} a_{2} + a_{0} a_{2} a_{3} - a_{1}^{2} a_{2}^{2} a_{3} - a_{1}^{2} a_{2} - 2 a_{1} a_{2} a_{3} - a_{1} + a_{2}^{2} a_{3} + a_{2} - a_{3}}{a_{0} a_{1} a_{2}^{2} a_{3}^{2} + 2 a_{0} a_{1} a_{2} a_{3} + a_{0} a_{1} + a_{0} a_{2} a_{3}^{2} + a_{0} a_{3} - a_{1}^{2} a_{2}^{2} a_{3}^{2} - 2 a_{1}^{2} a_{2} a_{3} - a_{1}^{2} - 2 a_{1} a_{2} a_{3}^{2} - 2 a_{1} a_{3} + a_{2}^{2} a_{3}^{2} + 2 a_{2} a_{3} - a_{3}^{2} + 1} + \frac{1}{\left(a_{0} a_{1} a_{2}^{2} a_{3}^{2} + 2 a_{0} a_{1} a_{2} a_{3} + a_{0} a_{1} + a_{0} a_{2} a_{3}^{2} + a_{0} a_{3} - a_{1}^{2} a_{2}^{2} a_{3}^{2} - 2 a_{1}^{2} a_{2} a_{3} - a_{1}^{2} - 2 a_{1} a_{2} a_{3}^{2} - 2 a_{1} a_{3} + a_{2}^{2} a_{3}^{2} + 2 a_{2} a_{3} - a_{3}^{2} + 1\right) \left(a_{0} a_{1} a_{2}^{2} a_{3}^{2} a_{4} + a_{0} a_{1} a_{2}^{2} a_{3} + 2 a_{0} a_{1} a_{2} a_{3} a_{4} + a_{0} a_{1} a_{2} + a_{0} a_{1} a_{4} + a_{0} a_{2} a_{3}^{2} a_{4} + a_{0} a_{2} a_{3} + a_{0} a_{3} a_{4} + a_{0} - a_{1}^{2} a_{2}^{2} a_{3}^{2} a_{4} - a_{1}^{2} a_{2}^{2} a_{3} - 2 a_{1}^{2} a_{2} a_{3} a_{4} - a_{1}^{2} a_{2} - a_{1}^{2} a_{4} - 2 a_{1} a_{2} a_{3}^{2} a_{4} - 2 a_{1} a_{2} a_{3} - 2 a_{1} a_{3} a_{4} - a_{1} + a_{2}^{2} a_{3}^{2} a_{4} + a_{2}^{2} a_{3} + 2 a_{2} a_{3} a_{4} + a_{2} - a_{3}^{2} a_{4} - a_{3} + a_{4}\right)}\end{equation*}




```julia
push!(l, a4)
list_to_frac(l)
```




\begin{equation*}a_{1} + \frac{1}{a_{1} + \frac{1}{a_{2} + \frac{1}{a_{3} + \frac{1}{a_{4}}}}}\end{equation*}



<hr />

<div class="admonition note"><p class="admonition-title">Quick tip</p><p>You can execute multiple lines at once in SymPy Live.  Typing <code>Shift-Enter</code> instead of <code>Enter</code> will enter a newline instead of executing.</p>
</div>

<p>Of course, this exercise seems pointless, because we already know that our <code>frac</code> is <code>list_to_frac&#40;&#91;a0, a1, a2, a3, a4&#93;&#41;</code>.  So try the following exercise.  Take a list of symbols and randomize them, and create the canceled continued fraction, and see if you can reproduce the original list.  For example</p>


```julia
    >>> import random
    >>> l = list(symbols('a0:5'))
    >>> random.shuffle(l)
    >>> orig_frac = frac = cancel(list_to_frac(l))
    >>> del l
```

<h5>In <code>Julia</code>:</h5>

<ul>
<li><p><code>shuffle</code> from Python is <code>randperm</code> in the <code>Random</code> module</p>
</li>
</ul>


```julia
using Random
l = symbols("a0:5")
l = l[randperm(length(l))]
orig_frac = frac = cancel(list_to_frac(l))
```




\begin{equation*}\frac{a_{0} a_{1}^{2} a_{2} a_{3} a_{4} + a_{0} a_{1}^{2} a_{2} + a_{0} a_{1}^{2} a_{3} + a_{0} a_{2} a_{3} a_{4} + a_{0} a_{2} + a_{0} a_{3} + a_{1}^{2} a_{3} a_{4} + a_{1}^{2} + a_{1} a_{2} a_{3} a_{4} + a_{1} a_{2} + a_{1} a_{3} + a_{3} a_{4} + 1}{a_{0} a_{1} a_{2} a_{3} a_{4} + a_{0} a_{1} a_{2} + a_{0} a_{1} a_{3} + a_{1} a_{3} a_{4} + a_{1} + a_{2} a_{3} a_{4} + a_{2} + a_{3}}\end{equation*}



<hr />

<p>Click on "Run code block in SymPy Live" on the definition of <code>list_to_frac&#40;&#41;</code> above, and then on the above example, and try to reproduce <code>l</code> from <code>frac</code>.  I have deleted <code>l</code> at the end to remove the temptation for peeking (you can check your answer at the end by calling <code>cancel&#40;list_to_frac&#40;l&#41;&#41;</code> on the list that you generate at the end, and comparing it to <code>orig_frac</code>.</p>

<p>See if you can think of a way to figure out what symbol to pass to <code>apart&#40;&#41;</code> at each stage (hint: think of what happens to $a_0$ in the formula $a_0 + \frac{1}{a_1 + \cdots}$ when it is canceled).</p>

<div class="admonition note"><p class="admonition-title">Note</p><p>Answer: a0 is the only symbol that does not appear in the denominator</p>
</div>

<hr />

<p><a href="./index.html">return to index</a></p>

22c2ddeee85debced14bb86258013fea697216d8
ipynb
Jupyter Notebook
examples/simplification.ipynb
UnofficialJuliaMirrorSnapshots/SymPy.jl-24249f21-da20-56a4-8eb1-6a02cf4ae2e6
a6e5a24b3d1ad069a413d0c28f01052c5fa4c6cc
MIT
examples/simplification.ipynb
UnofficialJuliaMirrorSnapshots/SymPy.jl-24249f21-da20-56a4-8eb1-6a02cf4ae2e6
a6e5a24b3d1ad069a413d0c28f01052c5fa4c6cc
MIT
examples/simplification.ipynb
UnofficialJuliaMirrorSnapshots/SymPy.jl-24249f21-da20-56a4-8eb1-6a02cf4ae2e6
a6e5a24b3d1ad069a413d0c28f01052c5fa4c6cc
MIT
Qwen/Qwen-72B
1. YES
2. YES