Sympy II-极限和微积分

蔡俊杰

2022-05-22

English

建议从这里下载这篇文章对应的.ipynb文件和相关资源。这样你就能在Jupyter中边阅读,边测试文中的代码。

初始化环境

In [3]:
from IPython.display import display, Math
from sympy import *
init_printing()

from helper import comparator_factory, comparator_eval_factory, comparator_method_factory

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

comparator = comparator_factory('使用{}前:','使用后:')
method_comparator = comparator_method_factory('调用{}前:','调用后:')
eval_comparator = comparator_eval_factory('计算前:','计算后:')

微积分

这部分设计如何进行基本的微积分操作,比如微分,积分,求极限,级数展开。

微分

diff()求微分

基本的微分

传入表达式和应用微分的符号变量。

In [4]:
expr = sin(x)

expr_diff = diff(expr,x)

comparator(expr, diff, x)
使用diff()前:
$$\sin{\left (x \right )}$$
使用后:
$$\cos{\left (x \right )}$$

也可以用方法调用的方式计算微分

In [5]:
expr = sin(x)

method_comparator(expr, 'diff', x)
调用diff()前:
$$\sin{\left (x \right )}$$
调用后:
$$\cos{\left (x \right )}$$

如果要创建一个未执行计算的微分, 可以使用Derivative类。 初始化的语法和diff()是一样的。

In [6]:
expr = sin(x)

diff_expr = Derivative(expr,x)

print('Before evaluation:')
display(diff_expr)
Before evaluation:
$$\frac{d}{d x} \sin{\left (x \right )}$$

然后调用doit()方法执行计算。

In [7]:
print('After evaluation:')
display(diff_expr.doit())
After evaluation:
$$\cos{\left (x \right )}$$

为了避免冗余代码, 后面的笔记我们使用eval_comparator来进行比较。

高阶微分

如果要计算n次高阶微分, 传入符号n次或者在符号后面传入n。

In [8]:
expr = Derivative(x**4,x,x,x)

eval_comparator(expr)
计算前:
$$\frac{d^{3}}{d x^{3}} x^{4}$$
计算后:
$$24 x$$

用第二种方式达到同样的效果。

In [9]:
expr = Derivative(x**4,x,3)

eval_comparator(expr)
计算前:
$$\frac{d^{3}}{d x^{3}} x^{4}$$
计算后:
$$24 x$$

高阶偏微分

只要按照顺序传入符号就可以, 语法和一阶微分一样。

In [10]:
expr = Derivative(exp(x*y*z),x, y, y, z, z, z, z)

eval_comparator(expr)
计算前:
$$\frac{\partial^{7}}{\partial x\partial y^{2}\partial z^{4}} e^{x y z}$$
计算后:
$$x^{3} y^{2} \left(x^{3} y^{3} z^{3} + 14 x^{2} y^{2} z^{2} + 52 x y z + 48\right) e^{x y z}$$

或者通过数字控制每个符号的微分阶数

In [11]:
expr = Derivative(exp(x*y*z),x, y, 2, z, 4)

eval_comparator(expr)
计算前:
$$\frac{\partial^{7}}{\partial x\partial y^{2}\partial z^{4}} e^{x y z}$$
计算后:
$$x^{3} y^{2} \left(x^{3} y^{3} z^{3} + 14 x^{2} y^{2} z^{2} + 52 x y z + 48\right) e^{x y z}$$

积分

不定积分

和微分类似,积分可以通过integral()函数或者方法来实现。 如果要创建未计算的积分表达式,初始化一个Integral类然后调用doit()进行计算。

In [12]:
expr = Integral(cos(x),x)

eval_comparator(expr)
计算前:
$$\int \cos{\left (x \right )}\, dx$$
计算后:
$$\sin{\left (x \right )}$$

定积分

传入一个包含符号,积分下限, 积分上线的tuple去进行定积分。

In [13]:
expr = Integral(exp(-x),(x,0,oo))

eval_comparator(expr)
计算前:
$$\int_{0}^{\infty} e^{- x}\, dx$$
计算后:
$$1$$

注意,在Sympy中$\infty$用oo表示(两个小写的'O')

多重积分

传入多个包含符号和积分限的tuple进行多重积分。

In [14]:
expr = Integral(exp(-x**2 - y**2), (x, -oo, oo), (y, -oo, oo))

eval_comparator(expr)
计算前:
$$\int_{-\infty}^{\infty}\int_{-\infty}^{\infty} e^{- x^{2} - y^{2}}\, dx\, dy$$
计算后:
$$\pi$$

如果Sympy无法计算一个表达式的积分,机会返回未计算的积分式。

In [15]:
expr = Integral(x**x)

eval_comparator(expr)
计算前:
$$\int x^{x}\, dx$$
计算后:
$$\int x^{x}\, dx$$

极限

和微分一样, 极限可以用过limit()函数或者方法进行微分计算。 如果要创建未计算的表达式,初始化一个Limit类, 然后通过调用doit()方法完成计算。

默认情况下, dir = '+', 极限从右侧计算。

In [16]:
expr = Limit(sin(x)/x, x, 0)

eval_comparator(expr)
计算前:
$$\lim_{x \to 0^+}\left(\frac{1}{x} \sin{\left (x \right )}\right)$$
计算后:
$$1$$

如果要计算左侧极限, 可以传入dir='-'

In [17]:
expr = Limit(sin(x)/x, x, 0, dir = '-')

eval_comparator(expr)
计算前:
$$\lim_{x \to 0^-}\left(\frac{1}{x} \sin{\left (x \right )}\right)$$
计算后:
$$1$$

级数展开

通过调用series()方法, Sympy可以计算误差关于$O(x-x_0)^n$, 在点$x_0$处的渐进级数展开。

In [18]:
expr = sin(x)

method_comparator(expr, 'series', x,0,6)
调用series()前:
$$\sin{\left (x \right )}$$
调用后:
$$x - \frac{x^{3}}{6} + \frac{x^{5}}{120} + \mathcal{O}\left(x^{6}\right)$$

如果要去掉误差项,可以调用removeO()方法。

In [19]:
print('Expanded expression without order term:')
expr.series(x,0,6).removeO()
Expanded expression without order term:
Out[19]:
$$\frac{x^{5}}{120} - \frac{x^{3}}{6} + x$$

参考资料

Sympy Documentation