3.2. Sympy : Symbolic Mathematics in Python

作者Fabian Pedregosa

目标

  1. 以任意精度评估表达式。
  2. 对符号表达式执行代数操作。
  3. 执行基本的微积分任务(限制,微分和
    集成)与符号表达式。
  4. 求解多项式和超越方程。
  5. 求解一些微分方程。

什么是SymPy?SymPy是一个用于符号数学的Python库。它的目的是替代系统,如Mathematica或Maple,同时保持代码尽可能简单和易于扩展。SymPy完全用Python编写,不需要任何外部库。

可在http://www.sympy.org/上找到有关安装的Sympy文档和软件包

3.2.1. 使用SymPy 的第一步

3.2.1.1. 使用SymPy作为计算器

SymPy定义三种数值类型:Real,Rational和Integer。

Rational类将有理数表示为一对两个整数:分子和分母,因此Rational(1,2)表示1/2,Rational(5,2)5/2等等:

>>> from sympy import *
>>> a = Rational(1,2)
>>> a
1/2
>>> a*2
1

SymPy在后台使用mpmath,这使得可以使用任意精度算术执行计算。这样,一些特殊的常数,如e,pi,oo(Infinity),被视为符号,可以任意精度计算:

>>> pi**2
2
pi
>>> pi.evalf()
3.14159265358979
>>> (pi + exp(1)).evalf()
5.85987448204884

如您所见,evalf将表达式计算为浮点数。

还有一个表示数学无穷大的类,称为oo

>>> oo > 99999
True
>>> oo + 1
oo

3.2.1.2. 练习

  1. 用100小数计算​​\sqrt{2}
  2. 在有理算术中计算1/2 + 1/3

3.2.1.3. 符号

与其他计算机代数系统相反,在SymPy中,您必须显式声明符号变量:

>>> from sympy import *
>>> x = Symbol('x')
>>> y = Symbol('y')

然后你可以操纵他们:

>>> x + y + x - y
2*x
>>> (x + y)**2
2
(x + y)

现在可以使用一些python运算符来处理符号:+, - ,*,**(arithmetic),&,|,〜

打印

这里我们使用以下设置进行打印

>>> sympy.init_printing(use_unicode=False, wrap_line=True)

3.2.2. 代数操作

SymPy能够执行强大的代数操作。我们将介绍一些最常用的:扩展和简化。

3.2.2.1. 展开

使用此来展开代数表达式。它将试图否认权力和乘法:

>>> expand((x + y)**3)
3 2 2 3
x + 3*x *y + 3*x*y + y
>>> 3*x*y**2 + 3*y*x**2 + x**3 + y**3
3 2 2 3
x + 3*x *y + 3*x*y + y

更多选项可以在形式上给出关键字:

>>> expand(x + y, complex=True)
re(x) + re(y) + I*im(x) + I*im(y)
>>> I*im(x) + I*im(y) + re(x) + re(y)
re(x) + re(y) + I*im(x) + I*im(y)
>>> expand(cos(x + y), trig=True)
-sin(x)*sin(y) + cos(x)*cos(y)
>>> cos(x)*cos(y) - sin(x)*sin(y)
-sin(x)*sin(y) + cos(x)*cos(y)

3.2.2.2. 简化

如果要将表达式转换为更简单的形式,请使用简化:

>>> simplify((x + x*y) / x)
y + 1

简化是一个有点模糊的术语,更简洁的替代存在:powsimp(简化指数),trigsimp(用于三角表达式),logcombine,radsimp。

练习

  1. 计算(x+y)^6的展开形式。
  2. 简化三角表达式

3.2.3. 微积分

3.2.3.1. 限制

限制在SymPy中很容易使用,它们遵循语法限制(函数,变量,点),因此要计算f(x)作为x \rightarrow 0的限制,您将发出limit(f,x,0):

>>> limit(sin(x)/x, x, 0)
1

您还可以计算无限极限:

>>> limit(x, x, oo)
oo
>>> limit(1/x, x, oo)
0
>>> limit(x**x, x, 0)
1

3.2.3.2. 区分

您可以使用diff(func, var)来区分任何SymPy表达式。例子:

>>> diff(sin(x), x)
cos(x)
>>> diff(sin(2*x), x)
2*cos(2*x)
>>> diff(tan(x), x)
2
tan (x) + 1

你可以检查,它是正确的:

>>> limit((tan(x+y) - tan(x))/y, y, 0)
2
tan (x) + 1

可以使用diff(func, var, n)方法计算更高的导数:

>>> diff(sin(2*x), x, 1)
2*cos(2*x)
>>> diff(sin(2*x), x, 2)
-4*sin(2*x)
>>> diff(sin(2*x), x, 3)
-8*cos(2*x)

3.2.3.3. 系列扩展

SymPy也知道如何计算某点的表达式的泰勒级数。使用系列(expr, var)

>>> series(cos(x), x)
2 4
x x / 6\
1 - -- + -- + O\x /
2 24
>>> series(1/cos(x), x)
2 4
x 5*x / 6\
1 + -- + ---- + O\x /
2 24

练习

  1. 计算
  2. Calculate the derivative of log(x) for x.

3.2.3.4. 集成

SymPy通过integrate()工具支持超越基本和特殊函数的不确定和定义集成,它使用强大的扩展Risch-Norman算法和一些启发式和模式匹配。您可以集成基本功能:

>>> integrate(6*x**5, x)
6
x
>>> integrate(sin(x), x)
-cos(x)
>>> integrate(log(x), x)
x*log(x) - x
>>> integrate(2*x + sinh(x), x)
2
x + cosh(x)

特殊功能也很容易处理:

>>> integrate(exp(-x**2)*erf(x), x)
____ 2
\/ pi *erf (x)
--------------
4

可以计算定积分:

>>> integrate(x**3, (x, -1, 1))
0
>>> integrate(sin(x), (x, 0, pi/2))
1
>>> integrate(cos(x), (x, -pi/2, pi/2))
2

也支持不正确的积分:

>>> integrate(exp(-x), (x, 0, oo))
1
>>> integrate(exp(-x**2), (x, -oo, oo))
____
\/ pi

3.2.4. 方程求解

SymPy能够在一个和多个变量中求解代数方程:

In [7]: solve(x**4 - 1, x)
Out[7]: [I, 1, -1, -I]

你可以看到它接受一个表达式作为第一个参数,该表达式应该等于0。它能够求解大部分多项式方程,并且还能够针对多个变量求解多个方程,给出一个元组作为第二个参数:

In [8]: solve([x + 5*y - 2, -3*x + 6*y - 15], [x, y])
Out[8]: {y: 1, x: -3}

它还具有(有限)对trascendental方程的支持:

In [9]: solve(exp(x) + 1, x)
Out[9]: [pi*I]

在多项式方程的情况下的另一个替代方案是因子因子返回分解为不可约项的多项式,并且能够计算各种域上的因式分解:

In [10]: f = x**4 - 3*x**2 + 1
In [11]: factor(f)
Out[11]: (1 + x - x**2)*(1 - x - x**2)
In [12]: factor(f, modulus=5)
Out[12]: (2 + x)**2*(2 - x)**2

SymPy也能够解决布尔方程,也就是说,决定某个布尔表达式是否是可满足的。为此,我们使用函数satisfiable:

In [13]: satisfiable(x & y)
Out[13]: {x: True, y: True}

这告诉我们,当x和y都为True时,(x和y)为True。如果表达式不能为true,即其参数的值不能使表达式为True,则它将返回False:

In [14]: satisfiable(x & ~x)
Out[14]: False

3.2.4.1. 练习

  1. 求解方程组x + y = 2
  2. Are there boolean values x, y that make (~x | y) & (~y | x) true?

3.2.5. 线性代数

3.2.5.1. 矩阵

矩阵从Matrix类创建为实例:

>>> from sympy import Matrix
>>> Matrix([[1,0], [0,1]])
[1 0]
[ ]
[0 1]

不像NumPy数组,你也可以把符号放入其中:

>>> x = Symbol('x')
>>> y = Symbol('y')
>>> A = Matrix([[1,x], [y,1]])
>>> A
[1 x]
[ ]
[y 1]
>>> A**2
[x*y + 1 2*x ]
[ ]
[ 2*y x*y + 1]

3.2.5.2. 微分方程

SymPy能够解决(一些)普通微分。为了求解微分方程,使用dsolve。首先,通过将cls = Function传递给符号函数来创建未定义的函数:

>>> f, g = symbols('f g', cls=Function)

f和g现在是未定义的函数。我们可以调用f(x),它将表示一个未知的函数:

>>> f(x)
f(x)
>>> f(x).diff(x, x) + f(x)
2
d
f(x) + ---(f(x))
2
dx
>>> dsolve(f(x).diff(x, x) + f(x), f(x))
f(x) = C1*sin(x) + C2*cos(x)

关键字参数可以赋予这个函数,以帮助如果找到最好的解决方案系统。例如,如果您知道它是一个可分离的方程,可以使用关键字hint ='separable'来强制dsolve将其解析为可分离方程:

>>> dsolve(sin(x)*cos(f(x)) + cos(x)*sin(f(x))*f(x).diff(x), f(x), hint='separable') 
/ _____________\ / _____________\
| / C1 | | / C1 |
[f(x) = - asin| / ------- + 1 | + pi, f(x) = asin| / ------- + 1 | + pi,
| / 2 | | / 2 |
\\/ cos (x) / \\/ cos (x) /
/ _____________\ / _____________\
| / C1 | | / C1 |
f(x) = -asin| / ------- + 1 |, f(x) = asin| / ------- + 1 |]
| / 2 | | / 2 |
\\/ cos (x) / \\/ cos (x) /

练习

  1. 求解伯努利微分方程

  1. 使用hint ='Bernoulli'求解同样的方程。你观察什么?