简介
SymPy是一个符号计算的Python库。它的目标是成为一个全功能的计算机代数系统,同时保持代码简洁、易于理解和扩展。它完全由Python写成,不依赖于外部库。
SymPy支持符号计算、高精度计算、模式匹配、绘图、解方程、微积分、组合数学、离散 数学、几何学、概率与统计、物理学等方面的功能。(来自维基百科的描述)
基本数值类型
实数,有理数和整数
SymPy有三个内建的数值类型:实数,有理数和整数。有理数类用两个整数来表示一个有理数。分子与分母,所以Rational(1,2)代表1/2,Rational(5,2)代表5/2,等等。
分数:
from sympy import *
a = Rational(1,2)
b = Rational(2)
print(a)
print(b)
结果:
1/2
2
整数计算:
from sympy import *
a = Rational(2)**2/Rational(10)**2
b = 2**2/10**2
print(a)
print(b)
结果:
1/25
0.04
Sympy模块的特殊函数的写法
三角函数:
sin
cos
tan
反三角函数:
asin
acos
atan
指数函数:
exp()
对数函数:
Inx:log(x)
logn(x):log(x,n)
特殊的常数
E——自然常数
π——pi
e——exp(1)
limit——求极限
oo——无穷
from sympy import *
a = pi
b = pi**2
c = pi.evalf() #evalf()函数可以用来求出表达式的浮点数
d = pi.evalf(n=3) #evalf(n=m)是浮点数保留m个有效数字
print(a)
print(b)
print(c)
运行结果:
pi
pi**2
3.14159265358979
3.14
打印公式
from sympy import pprint, Symbol, exp, sqrt
#pprint()用于在控制台上漂亮地打印输出。 LaTeX 可以达到最佳效果。
from sympy import init_printing
init_printing(use_unicode=True) # 对于某些字符,我们需要启用 unicode 支持
x = Symbol('x')
a = sqrt(2)
pprint(a)
print(a)
c = (exp(x) ** 2)/2
print('//----------------------//')
pprint(c)
print('//----------------------//')
print(c)
结果:
√2
sqrt(2)
//----------------------//
2⋅x
ℯ
────
2
//----------------------//
exp(2*x)/2
Sympy基本使用
定义变量——Symbols函数
对比与其他的计算机代数系统,在SymPy中要明确声明符号变量:
from sympy import *
x = symbols('x')
a = x+1
print(a)
结果:
x + 1
from sympy import *
x,y,z=symbols('x y z')
crazy = symbols('unrelated')
a = crazy + 1
b = z + 1
print(a)
print(b)
结果:
unrelated + 1
z + 1
变量替换subs函数
例子:
from sympy import *
x = symbols('x')
t = symbols('t') #定义变量
a = x + 1
b = a.subs(x, 2)
c = a.subs(x, t)
print(a)
print(b)
print(c)
结果:
x + 1
3
t + 1
from sympy import pi, exp, limit, oo
#from sympy.abc import x, y 可以从sympy.abc模块导入符号。 它将所有拉丁字母和希腊字母导出为符号,因此我们可以方便地使用它们。
from sympy.abc import x, y
a = (1 + x*y).subs(x, pi)
b = (1 + x*y).subs({x:pi, y:2})
c = (1 + x*y).subs([(x, pi), (y, 2)])
print(a)
print(b)
print(c)
结果:
pi*y + 1
1 + 2*pi
1 + 2*pi
from sympy.abc import x, y
reps = [(y, x ** 2), (x, 2)] #x=2,y=x^2=4
a = (x + y).subs(reps) #a=x+y=6
b = (x + y).subs(reversed(reps)) #y=2,x=x^2
print(a)
print(b)
c = (x**2 + x**4).subs(x**2, y)
d = (x**2 + x**4).xreplace({x**2: y})
print(c)
print(d)
结果:
6
x**2 + 2
y**2 + y
x**4 + y
SymPy 规范表达形式
SymPy 会自动将表达式转换为规范形式。 SymPy 仅执行廉价操作; 因此,表达式可能无法求值为最简单的形式。
from sympy.abc import a, b
expr = b*a + -4*a + b + a*b + 4*a + (a + b)*3
print(expr)
结果:
2*a*b + 3*a + 4*b
SymPy 扩展代数表达式
使用expand(),我们可以扩展代数表达式; 即该方法尝试消除幂和乘法。
from sympy import expand
from sympy.abc import x
expr = (x + 1) ** 2
print(expr)
print(expand(expr))
结果:
(x + 1)**2
x**2 + 2*x + 1
SymPy 简化表达式
可以使用simplify()将表达式更改为更简单的形式。
from sympy import sin, cos, simplify, pprint
from sympy.abc import x,y
expr = sin(x+y) / (sin(y)*cos(x))
print(expr)
pprint(expr)
print('-----------------------')
expr = simplify(expr)
print(expr)
pprint(expr)
结果:
sin(x + y)/(sin(y)*cos(x))
sin(x + y)
─────────────
sin(y)⋅cos(x)
-----------------------
tan(x)/tan(y) + 1
tan(x)
────── + 1
tan(y)
SymPy 比较表达式
SymPy 表达式与equals()而不是==运算符进行比较。
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)) # 在应用该方法之前,SymPy 尝试简化表达式。
# we cannot use == operator
print(a == b)
结果:
True
False
SymPy 求值表达式
可以通过替换符号来求值表达式。
# 通过用数字替换a和b符号来求值表达式
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)]))
结果:
29
SymPy 求解方程
用solve()或solveset()求解方程。
from sympy import Symbol, solve
x = Symbol('x')
sol = solve(x**2 - x, x) #x^2 - x = 0
print(sol) #x=0 , x=1
结果:
[0, 1]
solve()的第一个参数是公式。 该公式以适合 SymPy 的特定形式编写; 即x2 - x代替x2 = x。 第二个参数是我们需要解决的符号。
或者,我们可以将Eq用于公式。
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
[3]
使用solveset(),我们找到了给定求目标区间内的解的解决方案。
from sympy.solvers import solveset
from sympy import Symbol, Interval, pprint
x = Symbol('x')
sol = solveset(x**2 - 1, x, Interval(0, 50)) #解在区间(0,50)
print(sol)
sol2 = solveset(x**2 - 1, x, Interval(-10, 50)) #解在区间(-10,50)
print(sol2)
结果:
FiniteSet(1)
FiniteSet(-1, 1)
SymPy 序列
序列是其中允许重复的对象的枚举集合。 序列可以是有限的或无限的。 元素的数量称为序列的长度。 与集合不同,同一元素可以在序列中的不同位置出现多次。 元素的顺序很重要。
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)))
结果:
SeqFormula(x, (x, 1, 10))
[1, 2, 3, 4, …]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
10
55
55
SymPy 极限
极限是函数(或序列)“接近”作为输入(或索引)“接近”某个值的值。
from sympy import sin, limit, oo
from sympy.abc import x
l1 = limit(1/x, x, oo)
print(l1)
l2 = limit((1+x)**(1/x), x, 0)
print(l2)
结果:
0
E
SymPy 矩阵
在 SymPy 中,我们可以使用矩阵。 矩阵是数字或其他数学对象的矩形数组,为其定义了运算(例如加法和乘法)。
矩阵用于计算,工程或图像处理。
from sympy import Matrix, pprint
N = Matrix([2, 2])
pprint(N)
M = Matrix([[2],[2]])
pprint(M)
结果:
⎡2⎤
⎢ ⎥
⎣2⎦
⎡2⎤
⎢ ⎥
⎣2⎦
矩阵计算:
from sympy import Matrix, pprint
M = Matrix([[1, 2], [3, 4], [0, 3]])
pprint(M)
N = Matrix([2, 2])
pprint(N)
print("---------------------------")
print(M*N)
print("---------------------------")
pprint(M*N)
结果:
⎡1 2⎤
⎢ ⎥
⎢3 4⎥
⎢ ⎥
⎣0 3⎦
⎡2⎤
⎢ ⎥
⎣2⎦
---------------------------
Matrix([[6], [14], [6]])
---------------------------
⎡6 ⎤
⎢ ⎥
⎢14⎥
⎢ ⎥
⎣6 ⎦
SymPy 绘图
SymPy 包含用于绘图的模块。 它基于 Matplotlib 构建。
from sympy import sin
from sympy.abc import x
from sympy.plotting import plot
plot(sin(x))
结果:
函数的求导
函数求导要用到sympy中的diff
diff的基本用法
diff(func,x,n)
其中:
- func是要求导的函数
- x是要对其求导的变量
- n是可选的,表示求n阶导数,默认为1阶导数
【注意】在用diff进行求导之前,需要用symbols函数定义变量
1、一元函数一阶导数
from sympy import diff
from sympy import symbols
x = symbols("x")
a = diff(x**4,x)
print(a)
结果:
4*x**3
2、一元函数多阶求导
from sympy import diff
from sympy import symbols
def func(x):
return x**4
x = symbols("x")
print(diff(func(x),x,3))
结果:
24*x
3、对多变量函数求偏导
from sympy import diff
from sympy import symbols
def func(x,y):
return x**4*y+x*y**3
x,y = symbols("x,y")
print(diff(func(x,y),x)) #函数对x求偏导
print(diff(func(x,y),y)) #函数对y求偏导
print(diff(func(x,y),x,y)) #函数对x先求偏导,然后对y求偏导
结果:
4*x**3*y + y**3
x**4 + 3*x*y**2
4*x**3 + 3*y**2
4、将导数带入具体的值求某一点处的导数
from sympy import diff
from sympy import symbols
x = symbols("x")
print(diff(x**4,x).subs(x,2)) # 表示将x = 2,带入导函数4*x**3中
结果:
32
求不定积分
from sympy import *
x = symbols('x')
expr = exp(x) * sin(x) + exp(x) * cos(x)
print(integrate(expr, x)) #integrate是积分的意思
pprint(integrate(expr, x))
结果:
exp(x)*sin(x)
x
ℯ ⋅sin(x)
求定积分
import sympy
from sympy import *
x = symbols('x')
expr = exp(x) * sin(x) + exp(x) * cos(x)
print(integrate(expr, x, (x,-oo,oo)))
pprint(integrate(expr, x, (x,-oo,oo)))
a = sympy.log(x)
print(integrate(a, x, (x,1,2)))
pprint(integrate(a, x, (x,1,2)))
print(integrate(a, x, (x,1,oo)))
pprint(integrate(a, x, (x,1,oo)))
结果:
AccumBounds(-oo, oo)
<-∞, ∞>
-9/4 + 2*log(2)
-9/4 + 2⋅log(2)
oo
∞
求微分方程的解
from sympy import *
y = Function('y')
t = Symbol('t')
pprint(y(t).diff(t)) #y'
pprint(y(t).diff(t,t)) #y''
sol = dsolve(Eq(y(t).diff(t,t) - y(t), exp(t)), y(t)) #求解y''-y=e^t
print(sol)
结果:
d
──(y(t))
dt
2
d
───(y(t))
2
dt
Eq(y(t), C2*exp(-t) + (C1 + t/2)*exp(t))
打印latex公式
from sympy import *
x = symbols('x')
expr = cos(x)**2
pprint(Integral(expr, (x, 0, pi)))
print('//---------------------------//')
print(latex(Integral(expr, (x, 0, pi))))
结果:
π
⌠
⎮ 2
⎮ cos (x) dx
⌡
0
//---------------------------//
\int\limits_{0}^{\pi} \cos^{2}{\left(x \right)}\, dx
因式分解
from sympy import *
from sympy.abc import x,y,z
print(factor(x**3 - x**2 + x - 1))
print(factor(x**2*z + 4*x*y*z + 4*y**2*z))
结果:
(x - 1)*(x**2 + 1)
z*(x + 2*y)**2
降幂排列
from sympy import *
from sympy.abc import x,y,z
expr = x*y + x - 3 + 2*x**2 - z*x**2 + x**3
print(collect(expr, x)) #按x降幂排列
print(collect(expr, x).coeff(x,2)) #和 coeff搭配使用,可以求n次项系数, 这里就是求x^2项的系数
结果:
x**3 + x**2*(2 - z) + x*(y + 1) - 3
2 - z
约分
from sympy import *
from sympy.abc import x
print(cancel((x**2 + 2*x + 1)/(x**2 + x)))
结果:
(x + 1)/x
三角函数化简
from sympy import *
from sympy.abc import x
print(trigsimp(sin(x)**4 - 2*cos(x)**2*sin(x)**2 + cos(x)**4))
print(trigsimp(cosh(x)**2 + sinh(x)**2)) #可用于双曲函数化简
结果:
cos(4*x)/2 + 1/2
cosh(2*x)
三角函数展开
from sympy import *
from sympy.abc import x,y
print(expand_trig(sin(x + y)))
print(expand_trig(tan(2*x)))
结果:
sin(x)*cos(y) + sin(y)*cos(x)
2*tan(x)/(1 - tan(x)**2)
特殊函数
factorial(n) #阶乘
binomial(n, k) #二项分布函数
gamma(x) #伽玛函数(Gamma函数),也叫欧拉第二积分
伽玛函数(Gamma函数),也叫欧拉第二积分,是阶乘函数在实数与复数上扩展的一类函数。该函数在分析学、概率论、偏微分方程和组合数学中有重要的应用。与之有密切联系的函数是贝塔函数,也叫第一类欧拉积分,可以用来快速计算同伽马函数形式相类似的积分。
伽玛函数(Gamma Function)作为阶乘的延拓,是定义在复数范围内的亚纯函数,通常写成Γ(x)。
当函数的变量是正整数时,函数的值就是前一个整数的阶乘,或者说Γ(n+1)=n!。
Γ(x+1)=xΓ(x),Γ⑴=1,Γ(1/2)=√π,对正整数n,有Γ(n+1)=n!,Γ(1-x)Γ(x)=π/sin(πx)
对于x>0,伽马函数是严格凸函数。
伽马函数是亚纯函数,在复平面上,除了零和负整数点以外,它全部解析,而伽马函数在-k处的留数为(-1)^k/k!
from sympy import *
print(factorial(5))
print(binomial(20, 1/3))
print(gamma(5))
结果:
120
3.05661679604108
24
方程(组)求解
from sympy import *
from sympy.abc import x,y
print(solve(x**3 - 4*x**2 - 3*x + 18))
print(roots(x**3 - 4*x**2 - 3*x + 18)) #如果要求多重根重复次数可以用roots
print(solve([x - y + 2, x + y - 3], [x, y])) #求解方程组
结果:
[-2, 3] #如果有重根仅显示一个
{-2: 1, 3: 2} #表示 -2 是1重根,3 是2重根
#因此x**3 - 4*x**2 - 3*x + 18 = 0 的解:-2,3,3
{x: 1/2, y: 5/2}
求解多元多次方程组
from sympy import Symbol, solve
#from sympy import *
x = Symbol('x')
y= Symbol('y')
z = Symbol('z')
# x, y, z = symbols("x, y ,z")
def solve_function():
return [
x**2+y**2-10,
y**2+z**2-34,
x**2+z**2-26,]
solved_value=solve(solve_function(), [x,y,z])
print(solved_value)
[(-1, -3, -5), (-1, -3, 5), (-1, 3, -5), (-1, 3, 5), (1, -3, -5), (1, -3, 5), (1, 3, -5), (1, 3, 5)]