Symbolic Mathematics (Need)

What to Expect in This Chapter

There are many situations where we would like to manipulate mathematics symbolically rather than numerically. Packages such as Mathematica and Maple can perform this symbolic magic, but they are expensive. Fortunately, Python has an open-source package called SymPy that brings powerful symbolic manipulation to your fingertips.

These notes introduce symbolic mathematics using SymPy. The examples are deliberately short and practical.

Point to Ponder

Now that we have Large Language Models (LLMs) at our beck and call, it is tempting to use them for symbolic manipulation too. While this may sometimes work, you have no guarantee that what the LLM outputs is correct—unless it has been specifically designed for mathematical reasoning. My advice is to tread carefully.

Setting Up

Install and Import

You can install SymPy in the usual way (e.g. with pip or conda) and then import it as follows:

#| echo: false
def show(exp):
    print('$$', sp.latex(exp), '$$', sep='')
import sympy as sp

Pretty Printing

The following is optional but I strongly recommend you do, so that things look nice.

sp.init_printing()

I got the following from this Stackoverflow discuss

def _colab_latex_printer(exp, **options):
    # Lightweight helper for Colab's MathJax
    from google.colab.output._publish import javascript  # type: ignore
    url = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=default"
    javascript(url=url)
    return sp.printing.latex(exp, **options)

sp.init_printing(use_latex="mathjax", latex_printer=_colab_latex_printer)

Basics

Declaring Symbols

Before you can use variables in SymPy, you need to declare them as symbols. This step only needs to be done once per session.

x, y, z = sp.symbols('x y z')

Declaring symbols gives you full control over how they behave mathematically and how they are displayed. For example, you can specify whether a symbol should be real, positive, or an integer.

x = sp.symbols('x', real=True, positive=True)
a, b, c = sp.symbols('a b c', real=True, positive=True)

Expansion

sp.expand((x + y + z)**3)

\[x^{3} + 3 x^{2} y + 3 x^{2} z + 3 x y^{2} + 6 x y z + 3 x z^{2} + y^{3} + 3 y^{2} z + 3 y z^{2} + z^{3}\]

Square roots and radicals

show(sp.sqrt(8*x + 4*y + 2*z))

\[\sqrt{8 x + 4 y + 2 z}\]

Substitution

hahaha = sp.symbols('hahaha')
(sp.cos(x)).subs(x, hahaha)

\[\cos{\left(hahaha \right)}\]

Simplification

sp.simplify(sp.sin(x)**2 + sp.cos(x)**2)
1

Solving Equations

a, b, c = sp.symbols('a b c')
show(sp.solve(a*x**2 + b*x + c, x))  

\[\left[ \frac{- b - \sqrt{- 4 a c + b^{2}}}{2 a}, \ \frac{- b + \sqrt{- 4 a c + b^{2}}}{2 a}\right]\]

Calculus

Differentiation

sp.diff(x**4, x)

\[4x^{3}\]

Differentiate multiple times:

sp.diff(x**4, x, 3)

\[24x\]

Partial derivatives

sp.diff(x*y*sp.sin(x), x)  # ∂/∂x

\[xy\cos(x) + y\sin(x)\]

sp.diff(x*y*sp.sin(x), y)  # ∂/∂y

\[x\sin(x)\]

Integration

Indefinite integrals

sp.integrate(a*sp.exp(-(x-b)**2/c**2), x)

\[\frac{ac}{2}\sqrt{\pi}\,\operatorname{erf}\!\left(\frac{x-b}{c}\right).\]

Definite integrals

show(sp.integrate(a*sp.exp(-(x-b)**2/c**2), (x, -1, 1)))

\[\frac{\sqrt{\pi} a c \operatorname{erf}{\left(\frac{1 - b}{c} \right)}}{2} - \frac{\sqrt{\pi} a c \operatorname{erf}{\left(\frac{- b - 1}{c} \right)}}{2}\]

show(sp.integrate(sp.exp(-x**2 - y**2), (x, -sp.oo, sp.oo), (y, -sp.oo, sp.oo)))

\[\pi,\]

The latter equals \(\pi\) as expected for the Gaussian integral in two dimensions.

Leave integrals unevaluated

sp.Integral(sp.exp(-x**2 - y**2), (x, -sp.oo, sp.oo), (y, -sp.oo, sp.oo))

\[\int_{-\infty}^{\infty}\int_{-\infty}^{\infty} e^{-x^{2}-y^{2}}\,dx\,dy.\]