ZetCode

SymPy

最后修改于 2024 年 1 月 29 日

SymPy 教程介绍了如何使用 sympy 模块在 Python 中进行符号计算。这是对 SymPy 的简要介绍。

计算机代数系统 (CAS) 是一种数学软件,能够以类似于数学家和科学家传统手动计算的方式来处理数学表达式。

符号计算 处理数学对象的符号计算。数学对象被精确地表示,而不是近似表示,带有未求值的变量的数学表达式以符号形式保留。

SymPy

SymPy 是一个用于符号数学的 Python 库。它旨在成为一个功能齐全的计算机代数系统。SymPy 包含从基本符号算术到微积分、代数、离散数学和量子物理的功能。它能够以 LaTeX 格式显示结果。

$ pip install sympy

SymPy 使用 pip install sympy 命令安装。

有理数值

SymPy 提供 Rational 来处理有理数。有理数是任何可以表示为两个整数之比或分数 p/q 的数,其中 p 是分子,q 是非零分母。

rational_values.py
#!/usr/bin/python

from sympy import Rational

r1 = Rational(1/10)
r2 = Rational(1/10)
r3 = Rational(1/10)

val = (r1 + r2 + r3) * 3
print(val.evalf())

val2 = (1/10 + 1/10 + 1/10) * 3
print(val2)

该示例处理有理数。

val = (r1 + r2 + r3) * 3
print(val.evalf())

表达式是符号形式;我们使用 evalf 方法对其进行求值。

$ rational_values.py
0.900000000000000
0.9000000000000001

请注意,当不使用有理数时,输出中存在一个小错误。

SymPy pprint

pprint 用于在控制台上进行漂亮打印输出。在 Jupyter notebook 中使用 LaTeX 可以获得最佳效果。

prettify.py
#!/usr/bin/python

from sympy import pprint, Symbol, exp, sqrt
from sympy import init_printing

init_printing(use_unicode=True)

x = Symbol('x')

a = sqrt(2)
pprint(a)
print(a)

print("------------------------")

c = (exp(x) ** 2)/2
pprint(c)
print(c)

该程序美化了输出。

init_printing(use_unicode=True)

对于某些字符,我们需要启用 unicode 支持。

$ prettify.py
√2
sqrt(2)
------------------------
    2⋅x
ℯ
────
    2
exp(2*x)/2

这是输出。请注意,使用 Jupyter notebook 可以获得更漂亮的输出。

平方根

平方根是某个数乘以自身会得到一个指定数量的数。

square_root.py
#!/usr/bin/python

from sympy import sqrt, pprint, Mul

x = sqrt(2)
y = sqrt(2)

pprint(Mul(x,  y, evaluate=False)) 
print('equals to ')
print(x * y)

该程序输出一个包含平方根的表达式。

pprint(Mul(x,  y, evaluate=False))

我们使用 evaluate 属性推迟乘法表达式的求值。

$ square_root.py
√2⋅√2
equals to
2

SymPy 符号

符号计算处理符号,这些符号以后可以进行求值。在使用符号之前,必须在 SymPy 中定义它们。

def_sym.py
#!/usr/bin/python

# ways to define symbols

from sympy import Symbol, symbols
from sympy.abc import x, y

expr = 2*x + 5*y
print(expr)

a = Symbol('a')
b = Symbol('b')

expr2 = a*b + a - b
print(expr2)

i, j = symbols('i j')
expr3 = 2*i*j + i*j
print(expr3) 

程序展示了在 SymPy 中定义符号的三种方法。

from sympy.abc import x, y

符号可以从 sympy.abc 模块导入。它导出所有拉丁字母和希腊字母作为符号,因此我们可以方便地使用它们。

a = Symbol('a')
b = Symbol('b')

它们可以使用 Symbol 定义

i, j = symbols('i j')

可以使用 symbols 方法定义多个符号。

SymPy 表达式的规范形式

SymPy 会自动将表达式转换为规范形式。SymPy 只执行低成本操作;因此,表达式可能不会简化到最简形式。

canonical_form.py
#!/usr/bin/python

from sympy.abc import a, b

expr = b*a + -4*a + b + a*b + 4*a + (a + b)*3

print(expr)

我们有一个包含符号 ab 的表达式。该表达式可以轻松简化。

$ canonical_form.py
2*a*b + 3*a + 4*b

SymPy 展开代数表达式

使用 expand,我们可以展开代数表达式;即,该方法尝试嵌套展开幂和乘法。

expand.py
#!/usr/bin/python

from sympy import expand, pprint
from sympy.abc import x

expr = (x + 1) ** 2

pprint(expr)

print('-----------------------')
print('-----------------------')

expr = expand(expr)
pprint(expr)

该程序展开了一个简单的表达式。

$ expand.py
       2
(x + 1)
-----------------------
-----------------------
 2
x  + 2⋅x + 1

SymPy 简化表达式

可以使用 simplify 将表达式更改为更简单的形式。

simplify.py
#!/usr/bin/python

from sympy import sin, cos, simplify, pprint
from sympy.abc import x

expr = sin(x) / cos(x)

pprint(expr)

print('-----------------------')

expr = simplify(expr)
pprint(expr)

示例将 sin(x)/sin(y) 表达式简化为 tan(x)

$ simplify.py
sin(x)
──────
cos(x)
-----------------------
tan(x)

SymPy 比较表达式

SymPy 表达式使用 equals 而不是 == 运算符进行比较。

expr_equality.py
#!/usr/bin/python

from sympy import pprint, Symbol, sin, cos

x = Symbol('x')

a = cos(x)**2 - sin(x)**2
b = cos(2*x)

print(a.equals(b))

# we cannot use == operator
print(a == b)

该程序比较了两个表达式。

print(a.equals(b))

我们使用 equals 比较两个表达式。在应用该方法之前,SymPy 会尝试简化这些表达式。

$ expr_equality.py
True
False

SymPy 求值表达式

可以通过代换符号来求值表达式。

evaluating.py
#!/usr/bin/python

from sympy import pi

print(pi.evalf(30))

该示例将 pi 值求值到小数点后三十位。

$ evaluating.py
3.14159265358979323846264338328
evaluating2.py
#!/usr/bin/python

from sympy.abc import a, b
from sympy import pprint

expr = b*a + -4*a + b + a*b + 4*a + (a + b)*3

print(expr.subs([(a, 3), (b, 2)]))

该示例通过代换 ab 符号为数字来求值表达式。

$ evaluating.py
3.14159265358979323846264338328

SymPy 求解方程

方程使用 solvesolveset 进行求解。

solving.py
#!/usr/bin/python

from sympy import Symbol, solve

x = Symbol('x')

sol = solve(x**2 - x, x)

print(sol)

该示例使用 solve 求解了一个简单的方程。

sol = solve(x**2 - x, x)

solve 的第一个参数是方程。方程以适合 SymPy 的特定形式编写;即 x**2 - x 而不是 x**2 = x。第二个参数是要求解的符号。

$ solving.py
[0, 1]

该方程有两个解:0 和 1。

或者,我们可以使用 Eq 来表示方程。

solving2.py
#!/usr/bin/python

from sympy import pprint, Symbol, Eq, solve

x = Symbol('x')

eq1 = Eq(x + 1, 4)
pprint(eq1)

sol = solve(eq1, x)
print(sol)

该示例求解了一个简单的 x + 1 = 4 方程。

$ solving2.py
x + 1 = 4
[3]
solving3.py
#!/usr/bin/python

from sympy.solvers import solveset
from sympy import Symbol, Interval, pprint

x = Symbol('x')

sol = solveset(x**2 - 1, x, Interval(0, 100))
print(sol)

使用 solveset,我们可以找到给定区间内的解。

$ solving3.py
{1}

SymPy 序列

序列 是对象的枚举集合,其中允许重复。序列可以是有限的或无限的。元素的数量称为序列的长度。与集合不同,相同的元素可以在序列的不同位置出现多次。元素的顺序很重要。

sequence.py
#!/usr/bin/python

from sympy import summation, sequence, pprint
from sympy.abc import x

s = sequence(x, (x, 1, 10))
print(s)
pprint(s)
print(list(s))

print(s.length)

print(summation(s.formula, (x, s.start, s.stop)))
# print(sum(list(s)))

该示例创建了一个数字序列 1, 2, ..., 10。我们计算这些数字的总和。

$ sequence.py
SeqFormula(x, (x, 1, 10))
[1, 2, 3, 4, …]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
10
55

SymPy 极限

一个 极限 是当输入(或索引)“接近”某个值时,函数(或序列)“趋近”的值。

limit.py
#!/usr/bin/python

from sympy import sin, limit, oo
from sympy.abc import x

l1 = limit(1/x, x, oo)
print(l1)

l2 = limit(1/x, x, 0)
print(l2)

在示例中,我们有一个 1/x 函数。它有一个左极限和一个右极限。

from sympy import sin, limit, sqrt, oo

oo 表示无穷大。

l1 = limit(1/x, x, oo)
print(l1)

我们计算 1/x 在 x 趋近于正无穷大时的极限。

$ limit.py
0
oo

SymPy 矩阵

在 SymPy 中,我们可以处理矩阵。矩阵是由数字或其他数学对象组成的矩形数组,可以对其进行加法和乘法等运算。

矩阵用于计算、工程或图像处理。

matrix.py
#!/usr/bin/python

from sympy import Matrix, pprint

M = Matrix([[1, 2], [3, 4], [0, 3]])
print(M)
pprint(M)

N = Matrix([2, 2])

print("---------------------------")
print("M * N")
print("---------------------------")

pprint(M*N)

该示例定义了两个矩阵并相乘。

$ matrix.py
Matrix([[1, 2], [3, 4], [0, 3]])
⎡1  2⎤
⎢    ⎥
⎢3  4⎥
⎢    ⎥
⎣0  3⎦
---------------------------
M * N
---------------------------
⎡6 ⎤
⎢  ⎥
⎢14⎥
⎢  ⎥
⎣6 ⎦

SymPy 绘图

SymPy 包含一个绘图模块。它基于 Matplotlib。

simple_plot.py
#!/usr/bin/python

# uses matplotlib

import sympy
from sympy.abc import x
from sympy.plotting import plot

plot(1/x)

该示例绘制了一个 1/x 函数的二维图形。

来源

Python SymPy 文档

以上是 SymPy 教程。

作者

我叫 Jan Bodnar,我是一名热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面有十多年的经验。

列出所有 Python 教程