This chapter is taken from the book A Primer on Scientific Programming with Python by H. P. Langtangen, 5th edition, Springer, 2016.
Python has a package SymPy for doing symbolic computing, such as symbolic (exact) integration, differentiation, equation solving, and expansion of Taylor series, to mention some common operations in mathematics. We shall here only give a glimpse of SymPy in action with the purpose of drawing attention to this powerful part of Python.
For interactive work with SymPy it is recommended to either use
IPython or the special, interactive shell isympy
, which is installed
along with SymPy itself.
Below we shall explicitly import each symbol we need from SymPy to
emphasize that the symbol comes from that package. For example, it
will be important to know whether sin
means the sine function from
the math
module, aimed at real numbers, or the special sine function
from sympy
, aimed at symbolic expressions.
The following session shows how easy it is to differentiate a formula \( v_0t - \frac{1}{2}gt^2 \) with respect to \( t \) and integrate the answer to get the formula back:
>>> from sympy import (
... symbols, # define symbols for symbolic math
... diff, # differentiate expressions
... integrate, # integrate expressions
... Rational, # define rational numbers
... lambdify, # turn symbolic expr. into Python functions
... )
>>> t, v0, g = symbols('t v0 g')
>>> y = v0*t - Rational(1,2)*g*t**2
>>> dydt = diff(y, t)
>>> dydt
-g*t + v0
>>> print 'acceleration:', diff(y, t, t) # 2nd derivative
acceleration: -g
>>> y2 = integrate(dydt, t)
>>> y2
-g*t**2/2 + t*v0
Note here that t
is a symbolic variable (not a float
as it is
in numerical computing), and y
(like y2
) is a symbolic expression (not
a float
as it would be in numerical computing).
A very convenient feature of SymPy is that symbolic expressions can be
turned into ordinary Python functions via lambdify
.
Let us take the
dydt
expression above and turn it into a Python function
v(t, v0, g)
for numerical computing:
>>> v = lambdify([t, v0, g], # arguments in v
dydt) # symbolic expression
>>> v(t=0, v0=5, g=9.81)
5
>>> v(2, 5, 9.81)
-14.62
>>> 5 - 9.81*2 # control the previous calculation
-14.62
A linear equation defined through an expression e
that is zero, can
be solved by solve(e, t)
, if t
is the unknown (symbol) in the
equation. Here we may find the roots of \( y=0 \):
>>> from sympy import solve
>>> roots = solve(y, t)
>>> roots
[0, 2*v0/g]
We can easily check the answer by inserting the roots in \( y \).
Inserting an expression e2
for e1
in some expression e
is done by e.subs(e1, e2)
. In our case we check that
>>> y.subs(t, roots[0])
0
>>> y.subs(t, roots[1])
0
A Taylor polynomial of order n
for an expression e
in a variable
t
around the point t0
is computed by e.series(t, t0, n)
.
Testing this on \( e^t \) and \( e^{\sin(t)} \) gives
>>> from sympy import exp, sin, cos
>>> f = exp(t)
>>> f.series(t, 0, 3)
1 + t + t**2/2 + O(t**3)
>>> f = exp(sin(t))
>>> f.series(t, 0, 8)
1 + t + t**2/2 - t**4/8 - t**5/15 - t**6/240 + t**7/90 + O(t**8)
Output of mathematical expressions in the LaTeX typesetting system is possible:
>>> from sympy import latex
>>> print latex(f.series(t, 0, 7))
'1 + t + \frac{t^{2}}{2} - \frac{t^{4}}{8} - \frac{t^{5}}{15} -
\frac{t^{6}}{240} + \mathcal{O}\left(t^{7}\right)'
Finally, we mention that there are tools for expanding and simplifying expressions:
>>> from sympy import simplify, expand
>>> x, y = symbols('x y')
>>> f = -sin(x)*sin(y) + cos(x)*cos(y)
>>> simplify(f)
cos(x + y)
>>> expand(sin(x+y), trig=True) # requires a trigonometric hint
sin(x)*cos(y) + sin(y)*cos(x)