SymPy

  • Computer algebra system,
  • Open source,
  • Python library,
  • Can do symbolic integration and differentiation, operations from linear algebra and much more!

Alt text that describes the graphic

How to install SymPy

Create a Python virtual environment.

andrei@css-tech-x:~/math-fun$ python3 -m venv venv

Enter the virtual environment.

andrei@css-tech-x:~/math-fun$ . venv/bin/activate

And simply install the package with pip.

(venv) andrei@css-tech-x:~/math-fun$ pip install sympy
Collecting sympy
Collecting mpmath>=0.19 (from sympy)
Installing collected packages: mpmath, sympy
Successfully installed mpmath-1.0.0 sympy-1.1.1

You can use SymPy in your console

Run Python inside the virtual environment.

(venv) andrei@css-tech-x:~/math-fun$ python3
Python 3.6.3 (default, Oct  3 2017, 21:45:48) 
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

With SymPy, you can manipulate abstract symbols.

>>> from sympy.abc import x
>>> x ** 2
x**2

And you can already start doing Math! Here's a derivative.

>>> (x ** 2).diff()
2*x

SymPy in a Jupyter notebook

You can also use SymPy in a Jupyter notebook with beautifully rendered equations.

In [1]:
from sympy import init_printing
init_printing()
In [2]:
from sympy import Derivative
from sympy.abc import x
Derivative(x ** 2)
Out[2]:
$$\frac{d}{d x} x^{2}$$

What can it do?

Fully embedded inside a real programing language.

  • You can store equations in a variable.
In [3]:
from sympy.abc import a, b
sq = (a + b) ** 2

To reference later.

In [4]:
sq
Out[4]:
$$\left(a + b\right)^{2}$$

And manipulate.

In [5]:
sq.expand()
Out[5]:
$$a^{2} + 2 a b + b^{2}$$

SymPy can integrate

In [6]:
from sympy import Integral, cot
from sympy.abc import x
int = Integral(cot(x))
int
Out[6]:
$$\int \cot{\left (x \right )}\, dx$$
In [7]:
int.doit()
Out[7]:
$$\frac{1}{2} \log{\left (\cos^{2}{\left (x \right )} - 1 \right )}$$

SymPy can take derivatives

In [8]:
from sympy import exp, cos, Derivative
from sympy.abc import x
complicated = Derivative(exp(-x * cos(x)) * (2 * x - 1) / (cos(x * 2)))
complicated
Out[8]:
$$\frac{d}{d x}\left(\frac{\left(2 x - 1\right) e^{- x \cos{\left (x \right )}}}{\cos{\left (2 x \right )}}\right)$$
In [9]:
complicated.doit()
Out[9]:
$$\frac{e^{- x \cos{\left (x \right )}}}{\cos{\left (2 x \right )}} \left(2 x - 1\right) \left(x \sin{\left (x \right )} - \cos{\left (x \right )}\right) + \frac{2 e^{- x \cos{\left (x \right )}}}{\cos^{2}{\left (2 x \right )}} \left(2 x - 1\right) \sin{\left (2 x \right )} + \frac{2 e^{- x \cos{\left (x \right )}}}{\cos{\left (2 x \right )}}$$

SymPy handle complex numbers.

In [10]:
from sympy import exp, pi, I
from sympy.abc import theta
circular = exp(I * theta)
circular
Out[10]:
$$e^{i \theta}$$
In [11]:
circular.subs(theta, pi / 2)
Out[11]:
$$i$$
In [12]:
circular.subs(theta, pi)
Out[12]:
$$-1$$

SymPy can do linear algebra

In [13]:
from sympy import Matrix
In [14]:
a_matrix = Matrix([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])
a_matrix
Out[14]:
$$\left[\begin{matrix}1 & 2 & 3\\4 & 5 & 6\\7 & 8 & 9\end{matrix}\right]$$
In [15]:
a_matrix.det()
Out[15]:
$$0$$

Applications of SymPy

How I use it.

Simulate a Markov process

Given:

  • a stochastic matrix and
  • an initial distribution.
In [16]:
tick_tock = Matrix([
    [0, 1],
    [1, 0]
])
tick_tock
Out[16]:
$$\left[\begin{matrix}0 & 1\\1 & 0\end{matrix}\right]$$
In [17]:
t0 = Matrix([1, 0])
t0
Out[17]:
$$\left[\begin{matrix}1\\0\end{matrix}\right]$$
In [18]:
t1 = tick_tock * t0
t1
Out[18]:
$$\left[\begin{matrix}0\\1\end{matrix}\right]$$

Not just with numbers!

In [19]:
from sympy.abc import a, b
tick_tock * Matrix([a, b])
Out[19]:
$$\left[\begin{matrix}b\\a\end{matrix}\right]$$

SymPy can compute whatever you want

Mutual Information

$$ I(X;Y) = \sum_{x,y} p(x,y) \log \frac{p(x,y)}{p(x)p(y)}\\ $$

def mi(pxy):
    ''' Takes a joint probability P(X, Y) and returns I(X; Y). '''
    px, py = marginalize(pxy)
    return sum(pxy[x, y] * log2(pxy[x, y] / (px[x] * py[y]))
               if pxy[x, y] else 0
               for x in range(len(px)) for y in range(len(py)))
In [20]:
import process
cycle_matrix = process.mixed_cycles()
cycle_matrix
Out[20]:
$$\left[\begin{matrix}0 & \sigma & 0 & - \sigma + 1\\1 & 0 & 0 & 0\\0 & - \sigma + 1 & 0 & \sigma\\0 & 0 & 1 & 0\end{matrix}\right]$$
In [21]:
particular_matrix = cycle_matrix.subs(process.mixed_cycles.SIGMA, 0.7)
particular_matrix
Out[21]:
$$\left[\begin{matrix}0 & 0.7 & 0 & 0.3\\1 & 0 & 0 & 0\\0 & 0.3 & 0 & 0.7\\0 & 0 & 1 & 0\end{matrix}\right]$$
In [22]:
import util
util.draw_graph(particular_matrix)
Out[22]:

Information flow in a stochastic proces

In [23]:
import it
i = it.mi(it.to_joint(process.mixed_cycles(), process.uniform(4)))
i
Out[23]:
$$\frac{\sigma \log{\left (4 \sigma \right )}}{2 \log{\left (2 \right )}} + \frac{2}{\log{\left (2 \right )}} \left(- \frac{\sigma}{4} + \frac{1}{4}\right) \log{\left (- 4 \sigma + 4 \right )} + \frac{\log{\left (4 \right )}}{2 \log{\left (2 \right )}}$$
In [25]:
# ...
plot_over_sigma(i)

We can take the derivative of that function

In [26]:
from sympy import diff, simplify
sigma = process.mixed_cycles.SIGMA
di = simplify(diff(i, sigma))
di
Out[26]:
$$\frac{1}{2 \log{\left (2 \right )}} \left(\log{\left (\sigma \right )} - \log{\left (- \sigma + 1 \right )}\right)$$
In [27]:
plot_over_sigma(di)

Is this derivative exploding?

In [38]:
from sympy import Limit
l0 = Limit(di, sigma, 0)
l0
Out[38]:
$$\lim_{\sigma \to 0^+}\left(\frac{1}{2 \log{\left (2 \right )}} \left(\log{\left (\sigma \right )} - \log{\left (- \sigma + 1 \right )}\right)\right)$$
In [39]:
l0.doit()
Out[39]:
$$-\infty$$
In [40]:
l1 = Limit(di, sigma, 1)
l1
Out[40]:
$$\lim_{\sigma \to 1^+}\left(\frac{1}{2 \log{\left (2 \right )}} \left(\log{\left (\sigma \right )} - \log{\left (- \sigma + 1 \right )}\right)\right)$$
In [41]:
l1.doit()
Out[41]:
$$\infty$$

What did I find out with SymPy here?

  • Infinite slopes at 0 and 1,
  • Therefore no simple way to perturb clocks.