1.1.1. 简介

符号计算

符号计算(Symbolic Computation)是以符号的方式处理数学对象的计算。这意味着数学对象被精确的表示,而不是近似的表示,带有未求值的数学表达式保留符号形式。

下面举几个例子来说明符号计算的好处。

精确求值

对于 \(\sqrt{9}=3\) 这个数学常识,我们一定不会陌生。可以直接使用 Python 内建库求取:

import math
math.sqrt(9)
3.0

此时,符合数学直观。但是,对于 \(\sqrt{8}\) 可能并不一定会那么的准确:

math.sqrt(8)
2.8284271247461903

这里得到的是 \(\sqrt{8}\) 的近似值(因为 \(\sqrt{8}\) 是无理数,不能使用有限小数表示)。如果仅仅是想要获得 \(\sqrt{8}\) 的近似值,这样就结束是没有问题的,但是,想要通过下面的近似值立即判断 \(\sqrt{8} = 2\sqrt{2}\)

math.sqrt(8), math.sqrt(2)
(2.8284271247461903, 1.4142135623730951)

是很难的。对于符号计算,则是很容易的:

import sympy
sympy.sqrt(8)
\[\displaystyle 2 \sqrt{2}\]

数学表达式

上面的例子可以看出 SymPy 可以精确的表达数学概念。符号计算系统(Symbolic computation systems,也称为 CAS(computer algebra systems)) 可以使用变量计算数学表达式:

数学变量是使用 symbols 定义的。比如,可以定义数学表达式 \(x + 2y\)

from sympy import symbols

x, y = symbols('x y')
expr = x + 2*y
expr
\[\displaystyle x + 2 y\]

可以继续对数学表达式 expr 进行计算:

expr + 1
\[\displaystyle x + 2 y + 1\]
expr - x
\[\displaystyle 2 y\]
x*expr
\[\displaystyle x \left(x + 2 y\right)\]

也可以对数学表达式进行因式分解或者展示:

from sympy import expand, factor

expanded_expr = expand(x*expr)
expanded_expr # 展示表达式
\[\displaystyle x^{2} + 2 x y\]
factor(expanded_expr) # 转换为因子分解表达式
\[\displaystyle x \left(x + 2 y\right)\]

求导和求积分

from sympy import *

计算:\(\sin(x) \exp(x)\) 的导数:

diff(sin(x)*exp(x), x)
\[\displaystyle e^{x} \sin{\left(x \right)} + e^{x} \cos{\left(x \right)}\]

计算:\(\int(e^x\sin{(x)} + e^x\cos{(x)})\mathsf{d}x\)

integrate(exp(x)*sin(x) + exp(x)*cos(x), x)
\[\displaystyle e^{x} \sin{\left(x \right)}\]

计算:\(\int_{-\infty}^\infty \sin{(x^2)}\mathsf{d}x\)

integrate(sin(x**2), (x, -oo, oo))
\[\displaystyle \frac{\sqrt{2} \sqrt{\pi}}{2}\]

计算:\(\lim_{x\to 0} \frac{\sin{(x)}}{x}\)

limit(sin(x)/x, x, 0)
\[\displaystyle 1\]

其他

解方程:\(x^2−2=0\)

init_printing(use_latex='mathjax')
solve(x**2 - 2, x)
\[\displaystyle \left[ - \sqrt{2}, \ \sqrt{2}\right]\]

解微分方程:\(y'' - y = e^t\)

y = Function('y')
t = symbols('t')
dsolve(Eq(y(t).diff(t, t) - y(t), exp(t)), y(t))
\[\displaystyle y{\left(t \right)} = C_{2} e^{- t} + \left(C_{1} + \frac{t}{2}\right) e^{t}\]

计算 \(\left[\begin{smallmatrix}1 & 2\\2 & 2\end{smallmatrix}\right]\) 的奇异值:

Matrix([[1, 2], [2, 2]]).eigenvals()
\[\displaystyle \left\{ \frac{3}{2} - \frac{\sqrt{17}}{2} : 1, \ \frac{3}{2} + \frac{\sqrt{17}}{2} : 1\right\}\]

使用球面 Bessel 函数 \(j_\nu(z)\) 重写 Bessel 函数 \(J_{\nu}\left(z\right)\)

nu, z = symbols('nu z')
besselj(nu, z).rewrite(jn)
\[\displaystyle \frac{\sqrt{2} \sqrt{z} j_{\nu - \frac{1}{2}}\left(z\right)}{\sqrt{\pi}}\]