Symbolic and Automatic Di Erentiation in Python: Some Convenient Tools
Symbolic and Automatic Di Erentiation in Python: Some Convenient Tools
Symbolic and Automatic Di Erentiation in Python: Some Convenient Tools
Lab Objective: Python is good for more than just analysis of numerical data.
There are several packages available which allow symbolic and automatic computa-
tion in Python, two of which are SympPy and autograd. This lab should teach you to
do some basic manipulations in SymPy and autograd as well as their applications in
di↵erentiation. Keep in mind, however, that this introduction is not comprehensive.
SymPy
SymPy is designed to be a fully featured computer algebra system in Python. It is
actually used for much of the symbolic computation in Sage. An example of what
we mean by symbolic computation is the following:
>>> import sympy as sy
>>> x = sy.symbols('x') # Define a symbolic variable.
>>> sy.expand((x+1)**10) # Expand an expression with that variable.
x**10 + 10*x**9 + 45*x**8 + 120*x**7 + 210*x**6 + 252*x**5 + 210*x**4 + 120*x**3 -
+ 45*x**2 + 10*x + 1
When used properly, this package can simplify large amounts of algebra for
you. This can be incredibly useful in a wide variety of situations. As you may
have guessed, such packages generally have a wide variety of features. The official
documentation for SymPy is found at http://sympy.org/en/index.html.
177
178 Lab 15. SymPyAutograd
SymPy also has several nice options for printing equations. If you want to get a
rough idea of what the equation looks like, you can use sy.pprint(). It can interface
with the IPython Notebook to display the formula more clearly as well. If you
are using the IPython Notebook, you can enable pretty printing by loading the
extension that comes with SymPy. In SymPy 7.2 this is done as follows:
%load_ext sympy.interactive.ipythonprinting
SymPy has many more useful features. Figure 15.1 shows a screenshot of
SymPy’s special printing in the IPython notebook. If at some point you need
to write a formula in LATEX, the function sy.latex() can convert a SymPy symbolic
expression to LATEX for you.
Figure 15.1: A screenshot showing how SymPy can interface with the IPython
Notebook to display equations nicely.
This function works by evaluating the Taylor Series for 6 arcsin 12 . We used a
rather crude error estimate to ensure that we were close enough to break the loop.
Symbolic Manipulation
In SymPy, you need to declare symbolic objects before you use them. To define
a symbol x, we write x = sy.symbols('x'). This can also be used to define multiple
variables at once, as in x, y, z = sy.symbols('x,y,z'). The string form of each vari-
able on the right is used for showing expressions that involve the variable. You will
need to be careful about capitalization and that last ‘s’ in the name of the function.
Calling sy.Symbol() will allow you to create a single symbolic variable, but sy.symbol
is a submodule and cannot be called at all.
SymPy can be used to solve difficult expressions for given variables. Not every-
thing can be solved, but SymPy’s algorithms are pretty good and can often save a
great deal of time. We consider the following equation:
w x y z
+ + + =0
w x x y y z z w
Say we need an explicit solution for a given variable. Since the expression is sym-
metrical, it doesn’t really matter which one, but we can solve this in the following
way:
import sympy as sy
w, x, y, z = sy.symbols('w, x, y, z')
expr = w/(w-x) + x/(x-y) + y/(y-z) + z/(z-w)
sy.solve(expr, w)
In any variable, this expression is quadratic, but each coefficient will depend on the
other 3 variables. This would be a terrible pain to do by hand, but SymPy can take
care of that for us. It is worth noting that SymPy cannot do everything, but if we
keep in mind what we are doing and are familiar with the tools it has, it can make
180 Lab 15. SymPyAutograd
complex algebraic operations a great deal faster. We should also note that solve()
returns a list of expressions. If we want an expression to work with, we must take
an item from the list.
In this particular example, you will notice that we only used a symbolic expres-
sion and not a full equation. What SymPy did was set the expression equal to
zero, solve for the variable we wanted, then return the result. SymPy also supports
equation objects (and inequalities), but this approach is often easier. If you need to
declare equations, they can be declared using something like equation = sy.Eq(x, y)
which represents the equation x = y
SymPy can also be used to expand and simplify di↵erent symbolic expressions.
As an example we will simplify the expression
wx2 y 2 wx2 wy 2 + w x2 y 2 z + 2x2 y 2 + x2 z 2x2 + y 2 z 2y 2 z + 2
wxy wx wy + w xyz + 2xy + xz 2x + yz 2y z+2
Another useful feature is substitution. Substitution can be done using the subs()
method of an expression. You can substitute numbers and variables in for variables
and even expressions. For example, if you want to see what an expression looks like
if x is set to zero, you can use:
>>> x, y = sy.symbols('x,y')
>>> expr = sy.sin(x)*sy.cos(x)*sy.exp(y)*(x**3+y)**4
>>> expr.subs(x, 0)
0
where expr is the expression you have already defined. Note that none of these
operations modify the expression in place. They return a modified version of the
expression, but do not actually change the original.
Substitution also can be used (to some extent) to substitute one expression for
another. For example, if you want to apply the double angle identity to replace
products of sines and cosines, you could use the following:
>>> expr.subs(sy.sin(x) * sy.cos(x), sy.sin(2*x)/2)
(x**3 + y)**4*exp(y)*sin(2*x)/2
If you want to eliminate higher powers of a variable in an expression you can use
something like:
>>> expr.subs(x**3, 0)
y**4*exp(y)*sin(x)*cos(x)
which will eliminate all terms of the expression involving x3 . At present time this
will not eliminate terms involving x4 or higher powers of x that are not divisible by
3.
If you want to substitute values in for multiple variables, you can either use a
dictionary or a list of tuples for each variable and value.
>>> expr.subs({x:1.,y:2.})
272.113412745844
>>> expr.subs([(x,1.),(y,2.)])
272.113412745844
Calculus in SymPy
SymPy can also be used to take limits, integrals, and derivatives. Again, this can be
very helpful when doing things that would be difficult to do by hand. For example,
the following equation takes the 20th partial derivative with respect to x of
23
Y
(x + iy)
i=1
x, y, i = sy.symbols('x, y, i')
expr = sy.product((x+i*y), (i, 1, 23))
expr = expr.expand()
expr.diff(x, 20)
182 Lab 15. SymPyAutograd
Notice the .doit() method. This tells SymPy to evaluate all derivatives, integrals,
limits, etc. inside the expression.
Derivatives can be taken using the sy.Derivative() function, or the .diff() method
of a SymPy expression. This can be done like this:
>>> x, y = sy.symbols('x,y')
>>> expr = sy.sin(x)*sy.cos(x)*sy.exp(y)*(x**3+y)**4
>>> sy.Derivative(expr,x).doit()
12*x**2*(x**3 + y)**3*exp(y)*sin(x)*cos(x) - (x**3 + y)**4*exp(y)*sin(x)**2 + (x -
**3 + y)**4*exp(y)*cos(x)**2
These tricks also work with integrals, with the exception of taking multiple integrals
in the same variable. You can integrate two di↵erent variables along two di↵erent
bounds, as in:
sy.integrate(y**2*x**2, (x, -1, 1), (y, -1, 1))
You can also use SymPy to solve some sorts of basic ordinary di↵erential equa-
tions. This will solve the equation yxx 2 ⇤ yx + y = sin (x)
x = sy.symbols('x')
f = sy.Function('f')
eq = sy.Eq(f(x).diff(x, 2) - 2*f(x).diff(x) + f(x), sy.sin(x))
sy.dsolve(eq)
or, equivalently,
x = sy.symbols('x')
f = sy.Function('f')
expr = f(x).diff(x, 2) - 2*f(x).diff(x) + f(x) - sy.sin(x)
sy.dsolve(expr)
You may recall from your last class on di↵erential equations that this sort of
problem is solved by the method of undetermined coefficients. Imagine how
terrible this would be to do by hand!
SymPy can also be used to compute the Jacobian of a matrix using the .jacobian
() method, which
takes in either a list or a matrix of the variables. The Jacobian
2
x
of f (x, y) = is found by doing the following:
x+y
x,y = sy.symbols('x,y')
F = sy.Matrix([x**2,x+y])
F.jacobian([x,y])
Autograd
Autograd is a package that allows you to automatically di↵erentiate Python and
NumPy code. Unlike SymPy which has many diverse applications, autograd is used
solely in di↵erentiation. Autograd is very useful in machine learning.
184 Lab 15. SymPyAutograd
There are a couple of things to note from this example. autograd.numpy is a thinly-
wrapped NumPy. Also, grad() returns a function that computes the gradient of
your original function. This new function which returns the gradient accepts the
same parameters as the original function.
When there are multiple variables, the parameter argnum allows you to specify
with respect to which variable you are computing the gradient.
>>> f = lambda x,y: 3*x*y + 2*y - x
>>> grad_f = grad(f, argnum=0) #gradient with respect to the first variable
>>> grad_f(.25,.5)
0.5
>>> grad_f = grad(f, argnum=1) #gradient with respect to the second variable
>>> grad_fun(.25,.5)
2.75
Finding the gradient with respect to multiple variables can by done using multigrad()
by specifying which variables in the argnums parameter.
>>> grad_fun = autograd.multigrad(function, argnums=[0,1])
>>> grad_fun(.25,.5)
(0.5, 2.75)
p p
Problem 6. Use autograd to compute the derivative of f (x) = ln sin( x)
at x = ⇡4 . Time how long it takes to compute this derivative using autograd,
SymPy, and the centered di↵erence quotient. Calculate the error for each
approximation.
It is important to remember that if you use grad() the output must be a scalar,
whereas using jacobian() allows you to compute the gradient of a vector.
185
Problem 7.
Let f : R2 ! R2 be defined by
ex sin(y) + y 3
f (x, y) =
3y cos(x)
Find the Jacobian function using SymPy and autograd. Time how long it
takes to compute each Jacobian at (x, y) = (1, 1).