1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Sympy代数符号运算库

Sympy代数符号运算库

时间:2024-07-06 07:39:32

相关推荐

Sympy代数符号运算库

Python之Sympy代数符号运算库 计算器与数学计算机代数系统 CASSympy符号运算的基本使用指南 Sympy 与 Math 函数的区别定义变量 Symbol(‘x’), symbols(‘u v w’) 函数基本数值类型(real-rational-integer-positive-negative-complex-zero)构造抽象函数(Function(‘f’))数学符号与代数式变量替换(.subs)多项式排序重组 单变量情形多变量情形 因式分解与展开(factor-expand)expand()的参数factor()的参数有理式的简化、分解与合并(cancel-apart-together)多种特殊代数式化简代数式求值(替换subs)代数方程和方程组 解一元一次方程解多元一次方程组解一元二次方程组 微积分Calculus 高阶微分与偏导求不定积分求定积分求多重积分求极限求和 复数函数 三角函数球谐函数阶乘和伽马函数Zeta函数 多项式常微分ODE方程偏微分PDE方程数论线性代数 矩阵 集合 定义闭区间和开区间(Interval(s,e),Interval.open(s,e))长度用 .measure方法来表示其闭包用 .closure方法来表示其内点用 .interior方法来表示判断其边界条件可以使用 left_open 或者 right_open 来做两个集合之间的操作 逻辑级数 级数展开级数收敛级数求和级数连乘 求代数式的浮点数.evalf(n)方法SymPy的范畴论工具系数匹配打印输出 标准 print字符艺术打印(Pretty Printing) pprintPython字符串打印成一行Python printing输出成LaTeX形式LaTeX printing输出成MathML形式MathML数学符号相关参考链接

Python之Sympy代数符号运算库

人的一生中学习数学很多时候都浪费在反复解题、不断运算上。现在计算机普及,手机流行,很多计算方法、运算技巧、笔算能力以及数学公式都可以方便获取。笔算与解题在人工智能AI、图形图像、数据分析等上被软件所取代。

计算器与数学

APP中无数的数学计算器,常见的是加减乘除四则运算,有了它,我们就可以摆脱笔算和心算的痛苦。

数学的应用应该生活化、普及化,而不是只属于天才的专利,计算器帮我们改变了这一切。

计算器还可以做科学运算,比如乘方、开方、指数、对数、三角函数等,尽管这些知识在我们初中时代,通过纸笔也是能运算起来的,但是也仅限于一些极其常用和简单的运算,一旦复杂起来,通过纸笔来运算就是一项复杂的工程了。所以说,计算器可以让我们离数学的应用更近

但是学生时代所学的数学可远不止这些,尤其是高等数学(微积分)、线性代数、概率统计等数学知识应用非常广泛,但是由于其运算非常复杂,我们即便掌握了这些知识,想要应用它又谈何容易,那有没有 微积分、线性代数、概率统计 等的计算器呢?

答案是有的,它们就是计算机代数系统Computer Algebra System,简称CAS,Python的Sympy库也支持带有数学符号的微积分、线性代数等进行运算。

有了计算器,我们才能真正脱离数学复杂的解题本身,把精力花在对数学原理和应用的学习上,而这才是(在工作方面)数学学习的意义。

计算机代数系统 CAS

Python语言在 专业数学(数学、数据科学等)领域,由于其拥有非常多而且强大的第三方库,譬如Numpy,构成了一个极其完善的生态链。

Sympy是基于 Python之上的数学库,可以实现数学符号的运算,用它来进行数学代数式的符号推导和验算,处理带有数学符号的导数、极限、微积分、方程组、矩阵等,就像科学计算器一样简单,可以完成计算机代数系统CAS的绝大部分功能。

Sympy符号运算的基本使用指南

如果之前是学数学相关专业了解计算机代数系统CAS,就会对数学符号的运算比较熟悉,而如果之前是程序员,可能会有点不太明白,下面我们就来了解一下。

Sympy 与 Math 函数的区别

我们先来看一下Sympy库和Python内置的 Math 函数对数值计算的处理有什么不同。为了让代码可执行,下面的代码都是基于Python3的完整代码。

import sympy,mathprint(math.sqrt(8))print(sympy.sqrt(8))

执行之后,结果显示为:

2.8284271247461903 2*sqrt(2)

math 模块是直接求解出一个浮点值,而 Sympy 则是用数学符号表示出结果,结合LaTex的语法就可以得出我们在课本里最熟悉的的:222\sqrt{2}22​

定义变量 Symbol(‘x’), symbols(‘u v w’) 函数

Symbol('x')函数定义单个数学符号symbols('x y z)函数定义多个数学符号

对比与其他的计算机代数系统,在SymPy中要明确声明符号变量:

>>> x = Symbol('x')>>> x + 1x + 1>>> x,y,z=symbols('x y z')>>> crazy = symbols('unrelated')>>> crazy + 1unrelated + 1>>> x = symbols('x')>>> expr = x + 1>>> x = 2>>> print(expr)x + 1 #将x赋值2,并没有改变 expr变量. 因为 x = 2 是改变 Python 变量 x 为 2, 但是不影响 #SymPy的expr中的符号 x

基本数值类型(real-rational-integer-positive-negative-complex-zero)

SymPy 有三个内建的数值类型:实数,有理数和整数。有理数类用 两个整数 来表示一个有理数。分子与分母,所以Rational(1,2)代表1/2Rational(5,2)代表5/2,等等。

>>>from sympy import *>>>a = Rational(1,2)>>>a1/2>>>a*21>>>Rational(2)**50/Rational(10)**501/88817841970012523233890533447265625

还可以通过设置得到复数,实数,有理数,整数,正数,负数,非零数,零,非负数,非正数等的变量。

>>> from sympy import Symbol>>> from sympy.abc import x>>> x.assumptions0{'commutative': True}>>> r=Symbol('r', real=True)>>> n=Symbol('n', Integer=True) # 整数>>> n.assumptions0{'Integer': True, 'commutative': True}>>> y=Symbol('y', positive=True) # 正数>>> y.assumptions0{'positive': True, 'imaginary': False, 'commutative': True, 'zero': False, 'nonzero': True, 'complex': True, 'real': True, 'nonpositive': False, 'hermitian': True, 'nonnegative': True, 'negative': False}

commutative - Bing dictionary

US[kə’mju:tətɪv]UK[kə’mju:tətɪv]

adj.交换的(排列次序不影响结果)

网络可交换的;交换律;交换性Hermitian Matrix

埃尔米特矩阵主对角线上的元素都是实数的,其特征值也是实数。

构造抽象函数(Function(‘f’))

构造抽象函数 Function(),直接用f=Function(“f”),注意一点,在python之中和 C 中的不同之处,C 的创建对象实例有点像定义一个变量,和函数调用是不一样的,所以发现奇奇怪怪的比如student zhangsan; 我们就知道这肯定是创建zhangsan这个对象。而python的是和函数的一样的,所以注意分辨。再要注意的是,这个 Function 创建的是 类而不是对象实例。也就是说 f 是一个继承下来的类。还需要用t=f(x,y)去创建函数t这个对象。最终我们才能得到 t 这个抽象函数。

数学符号与代数式

我们要对数学方程组、微积分等进行运算时,就会遇到变量比如 x,y,z,u,v,w,f,g,hx,y,z,u,v,w,f,g,hx,y,z,u,v,w,f,g,h 等的问题,也会遇到求导、积分等代数符号代数式,而 Sympy 就可以保留变量,计算有代数符号的代数式。

>>> from sympy import *>>> from sympy.abc import x,y,z,a,b,c,k,m,n>>> print(a*x**m+b*y**n+c*z)a*x**m + b*y**n + c*z>>> x = Symbol('x') #只申请一个符号变量>>> y = Symbol('y')>>> k, m, n = symbols('k m n') #同时申请多个符号变量

输出的结果为:a∗x∗∗m+b∗y∗∗n+c∗za*x**m + b*y**n + c*za∗x∗∗m+b∗y∗∗n+c∗z,转化为 LaTex 表示法之后结果为 axm+byn+czax^m+by^n+czaxm+byn+cz,输出的结果就带有 x,y,z,a,b,cx, y, z, a,b,cx,y,z,a,b,c 等符号变量。

变量替换(.subs)

当个变量替换用expr.subs(var,value); 多个变量替换用词典expr.subs({v1:val1, v2:val2, ...}), 或者用列表方式expr.subs([(v1,val1), (v2,val2), ...]

>>> x = symbols('x')>>> expr = x + 1>>> expr.subs(x, 2)3>>> from sympy import pi, exp, limit, oo>>> from sympy.abc import x, y>>> (1 + x*y).subs(x, pi)pi*y + 1>>> (1 + x*y).subs({x:pi, y:2})1 + 2*pi>>> (1 + x*y).subs([(x, pi), (y, 2)])1 + 2*pi>>> reps = [(y, x**2), (x, 2)]>>> (x + y).subs(reps)6>>> (x + y).subs(reversed(reps))x**2 + 2>>> (x**2 + x**4).subs(x**2, y)y**2 + y>>> (x**2 + x**4).xreplace({x**2: y})x**4 + y>>> (x/y).subs([(x, 0), (y, 0)])0>>> (x/y).subs([(x, 0), (y, 0)], simultaneous=True)nan>>> ((x + y)/y).subs({x + y: y, y: x + y})1>>> ((x + y)/y).subs({x + y: y, y: x + y}, simultaneous=True)y/(x + y)>>> limit(x**3 - 3*x, x, oo)oo

多项式排序重组

单变量情形

>>> collect(a*x**2 + b*x**2 + a*x - b*x + c, x)c + x**2*(a + b) + x*(a - b)#The same result can be achieved in dictionary form::>>> d = collect(a*x**2 + b*x**2 + a*x - b*x + c, x, evaluate=False)>>> d[x**2]a + b>>> d[x]a - b>>> d[S.One]c

多变量情形

>>> myexpr = x*y + x -3 + 2*x**2 - x**2 + x**3 + y**2 + x**2*y**2>>> sympy.collect(myexpr,x) # 按照变量 x 排序x**3 + x**2*(y**2 + 1) + x*(y + 1) + y**2 - 3>>> sympy.collect(myexpr,y) # 按照变量 y 排序x**3 + x**2 + x*y + x + y**2*(x**2 + 1) - 3>>> myexpr.coeff(x,2) # x*2的系数y**2 + 1>>> myexpr.coeff(y,1) # y的系数x>>> collect(x**2 + y*x**2 + x*y + y + a*y, [x, y])x**2*(y + 1) + x*y + y*(a + 1)#Also more complicated expressions can be used as patterns::>>> from sympy import sin, log>>> collect(a*sin(2*x) + b*sin(2*x), sin(2*x))(a + b)*sin(2*x)>>> collect(a*x*log(x) + b*(x*log(x)), x*log(x))x*(a + b)*log(x)#You can use wildcards in the pattern::>>> w = Wild('w1')>>> collect(a*x**y - b*x**y, w**y)x**y*(a - b)#It is also possible to work with symbolic powers, although it has more #complicated behavior, because in this case power's base and symbolic #part of the exponent are treated as a single symbol::>>> collect(a*x**c + b*x**c, x)a*x**c + b*x**c>>> collect(a*x**c + b*x**c, x**c)x**c*(a + b)#However if you incorporate rationals to the exponents, then you will get well#known behavior::>>> collect(a*x**(2*c) + b*x**(2*c), x**c)x**(2*c)*(a + b)#Note also that all previously stated facts about :func:`collect` function#apply to the exponential function, so you can get::>>> from sympy import exp>>> collect(a*exp(2*x) + b*exp(2*x), exp(x))(a + b)*exp(2*x)>>> from sympy import Derivative as D, collect, Function>>> f = Function('f') (x)>>> collect(a*D(f,x) + b*D(f,x), D(f,x)) #求导(a + b)*Derivative(f(x), x)>>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), f)(a + b)*Derivative(f(x), (x, 2))>>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), D(f,x), exact=True)a*Derivative(f(x), (x, 2)) + b*Derivative(f(x), (x, 2))>>> collect(a*D(f,x) + b*D(f,x) + a*f + b*f, f)(a + b)*f(x) + (a + b)*Derivative(f(x), x)#Or you can even match both derivative order and exponent at the same time::>>> collect(a*D(D(f,x),x)**2 + b*D(D(f,x),x)**2, D(f,x))(a + b)*Derivative(f(x), (x, 2))**2#Finally, you can apply a function to each of the collected coefficients.#For example you can factorize symbolic coefficients of polynomial::>>> f = expand((x + a + 1)**3)>>> collect(f, x, factor)x**3 + 3*x**2*(a + 1) + 3*x*(a + 1)**2 + (a + 1)**3

因式分解与展开(factor-expand)

factor()函数可以合并代数式,也就是因式分解;而expand()函数可以展开代数式,比如代数式: x4+xy+8xx^4+xy+8xx4+xy+8x ,合并之后应该是 x(x3+y+8)x(x^3+y+8)x(x3+y+8),可见它们是互逆过程。我们来看具体的代码:

from sympy import *x, y = symbols('x y')>>> factor(x**4+x*y+8*x) #合并同类型,即因式分解x*(x**3 + y + 8)>>> expand(_) #展开代数式,_ 代表上一次的输出结果x**4 + x*y + 8*x

代数式的合并与展开,对应的数学知识就是因式分解。用 Python 学习数学专栏的目的就是要 Python 与 初高中、大学的数学学习结合起来,让数学变得更加简单生动。

expand()的参数

multinomial 多项式展开

展开多项式 (x+y+...)n,n∈Z+(x + y + ...)^n,n\in \mathbb{Z}^+(x+y+...)n,n∈Z+

>>> ((x + y + z)**2).expand(multinomial=True)x**2 + 2*x*y + 2*x*z + y**2 + 2*y*z + z**2。

power_exp 幂函数展开

展开指数加为幂的乘积: ex+y→ex⋅ey,2x+y→2x×2ye^{x+y}\to e^x\cdot e^y, 2^{x+y}\to 2^x\times2^yex+y→ex⋅ey,2x+y→2x×2y

>>> exp(x + y).expand(power_exp=True)exp(x)*exp(y)>>> (2**(x + y)).expand(power_exp=True)2**x*2**y

power_base 幂指数分解

(xy)z→xz⋅yz,(2y)z→2zyz(xy)^z\to x^z\cdot y^z, (2y)^z\to 2^zy^z(xy)z→xz⋅yz,(2y)z→2zyz

This only happens by default if assumptions allow, or if the

forcemeta-hint is used:

>>> ((x*y)**z).expand(power_base=True)(x*y)**z>>> ((x*y)**z).expand(power_base=True, force=True)x**z*y**z>>> ((2*y)**z).expand(power_base=True)2**z*y**z

Note that in some cases where this expansion always holds, SymPy performs it automatically:

>>> (x*y)**2x**2*y**2

log 对数函数展开

将幂指数变成系数,对数乘积变成对数加法:log⁡(x2y)→2log⁡(x)+log(y),x>0,y>0\log(x^2y)\to 2\log(x)+log(y), x>0,y>0log(x2y)→2log(x)+log(y),x>0,y>0

Note that these only work if the arguments of the log function have the proper assumptions–the arguments must be positive and the exponents must be real–or else theforcehint must beTrue:

>>> from sympy import log, symbols>>> log(x**2*y).expand(log=True)log(x**2*y)>>> log(x**2*y).expand(log=True, force=True)2*log(x) + log(y)>>> x, y = symbols('x,y', positive=True)>>> log(x**2*y).expand(log=True)2*log(x) + log(y)

complex 复数展开

将复数分解为实部和虚部(real and imaginary parts).

>>> x, y = symbols('x,y')>>> (x + y).expand(complex=True)re(x) + re(y) + I*im(x) + I*im(y)>>> cos(x).expand(complex=True)-I*sin(re(x))*sinh(im(x)) + cos(re(x))*cosh(im(x))

Note that this is just a wrapper aroundas_real_imag(). Most objects that wish to redefine_eval_expand_complex()should consider redefiningas_real_imag()instead.

func 函数展开 Expand other functions.

>>> from sympy import gamma>>> gamma(x + 1).expand(func=True)x*gamma(x)

trig 三角函数展开

Do trigonometric expansions.

>>> cos(x + y).expand(trig=True)-sin(x)*sin(y) + cos(x)*cos(y)>>> sin(2*x).expand(trig=True)2*sin(x)*cos(x)

Note that the forms ofsin(n*x)andcos(n*x)in terms ofsin(x)andcos(x)are not unique, due to the identity sin⁡2(x)+cos⁡2(x)=1\sin^2(x) + \cos^2(x)= 1sin2(x)+cos2(x)=1. The current implementation uses the form obtained fromChebyshevpolynomials, but this may change. See this MathWorld article for more information.

factor()的参数

>>> from sympy import factor, sqrt, exp>>> from sympy.abc import x, y>>> factor(2*x**5 + 2*x**4*y + 4*x**3 + 4*x**2*y + 2*x + 2*y) # 一般多项式因式分解2*(x + y)*(x**2 + 1)**2>>> factor(x**2 + 1) # 有理数范围内的因式分解x**2 + 1#The ``modulus`` meta-hint can be used to reduce the coefficients of an #expression post-expansion::>>> factor(x**2 + 1, modulus=2)(x + 1)**2>>> factor(x**2 + 1, gaussian=True) # 复数范围内的因式分解(x - I)*(x + I)>>> factor(x**2 - 2, extension=sqrt(2)) # 指定范围(x - sqrt(2))*(x + sqrt(2))>>> factor((x**2 - 1)/(x**2 + 4*x + 4))(x - 1)*(x + 1)/(x + 2)**2>>> factor((x**2 + 4*x + 4)**10000000*(x**2 + 1))(x + 2)**20000000*(x**2 + 1)#By default, factor deals with an expression as a whole:>>> eq = 2**(x**2 + 2*x + 1)>>> factor(eq)2**(x**2 + 2*x + 1)#If the ``deep`` flag is True then subexpressions will be factored:>>> factor(eq, deep=True)2**((x + 1)**2)#If the ``fraction`` flag is False then rational expressions won't be combined. #By default it is `True`.>>> factor(5*x + 3*exp(2 - 7*x), deep=True)(5*x*exp(7*x) + 3*exp(2))*exp(-7*x)>>> factor(5*x + 3*exp(2 - 7*x), deep=True, fraction=False)5*x + 3*exp(2)*exp(-7*x)

有理式的简化、分解与合并(cancel-apart-together)

去除公因子用cancel()不消除公因子(公式合并)用tegother()

化简有理式 expr=x2+3x+2x2+xexpr=\dfrac{x^2+3x+2}{x^2+x}expr=x2+xx2+3x+2​

x,y,z = sympy.Symbol('x y z')>>> expr = (x**2+3*x+2)/(x**2+x)>>> cancel(expr)(x + 2)/x>>> together(expr)(x**2 + 3*x + 2)/(x*(x + 1))>>> together(1/x+1/y+1/z)(x*y + x*z + y*z)/(x*y*z)

部分分式展开(Partial Fraction Decomposition)

用函数sympy.apart(expr, x),它是把有理式分解成多个次数较低的有理式的和的形式;

展开的逆运算就是代数式的合并,用sympy.together(expr, x)

公式展开用apart方法, 和 expand 区别不是很大,常用于分数(或分式)进行展开或分离;

>>> apart( 1/((x+2)*(x+1)) )-1/(x + 2) + 1/(x + 1)>>> (x+1)/(x-1)(x + 1)/(x - 1)>>> apart((x+1)/(x-1),x)1 + 2/(x - 1)>>> together(apart((x+1)/(x-1), x), x)(x + 1)/(x - 1)>>> together(apart(1/( (x+2)*(x+1) ), x), x)1/((x + 1)*(x + 2))

多种特殊代数式化简

simplify()函数可以化简代数式。有一些代数式看起来会比较复杂,简化 (2x)3(−5xy2)(2x)^3(-5xy^2)(2x)3(−5xy2) 。

多项式化简simplify(expr)

from sympy import *x,y = symbols('x y')>>> expr = (2*x)**3*(-5*x*y**2)>>> simplify(expr)-40*x**4*y**2

三角函数化简与展开trigsimp(expr),expand_trig(expr)

from sympy import trigsimp,sin,cosfrom sympy.abc import x,yy = sin(x)/cos(x)trigsimp(y)tan(x)>>> expand_trig(cos(x+y))-sin(x)*sin(y) + cos(x)*cos(y)>>> trigsimp(_)cos(x + y)>>> expand_trig(sin(x+y))sin(x)*cos(y) + sin(y)*cos(x)>>> trigsimp(_)sin(x + y)>>> trigsimp(sin(x)/cos(x))tan(x)>>> expand_trig(_)tan(x)>>> expand_trig(tan(x+y))(tan(x) + tan(y))/(-tan(x)*tan(y) + 1)>>> trigsimp(_) #???(tan(x) + tan(y))/(-tan(x)*tan(y) + 1)

指数函数化简与展开powsimp(expr),expand_power_exp()

powsimp 与 simplify 一样。除此之外,还可以根据

底数来做合并,即分别使用expand_power_exp函数与expand_power_base函数。

>>> from sympy import powsimp>>> from sympy.abc import x,y,z>>> powsimp(x**z*y**z*x**z)x**(2*z)*y**z>>> simplify(x**z*y**z*x**z)x**(2*z)*y**z>>> expand_power_exp(x**(y+z))x**y*x**z>>> expand_power_base(x**(y+z))x**(y + z)

对数函数log 展开与化简

指数的反函数就是 log,sympy 也是有着类似的展开合并函数,expand_log,logcombine承担了这样的角色。

ln⁡(xy)=ln⁡(x)+ln⁡(y),ln⁡(xy)=ln⁡(x)−ln⁡(y)\ln(xy) = \ln(x) + \ln(y), \ln( \dfrac{x}{y}) = \ln(x) − \ln(y)ln(xy)=ln(x)+ln(y),ln(yx​)=ln(x)−ln(y)

>>> from sympy import log,expand_log>>> from sympy.abc import x,y,a>>> expand_log(log(x**3))log(x**3)#expand_log为展开log,但需要将force=True,展开才能发生>>> expand_log(log(a**x),force=True)x*log(a)>>> expand_log(sympy.log(x*y), force=True)log(x) + log(y)>>> expand_log(sympy.log(x/y), force=True)log(x) - log(y)>>> expand_log(sympy.log(x/y))log(x/y)

代数式求值(替换subs)

如果想进行变量替换,例如把 xxx 变成 yyy ,那么可以使用substitution--subs方法。也常用来赋值求值

#--------多项式求解--------#定义变量>>> x=sympy.Symbol('x')>>> (5*x+4).subs(x,6)34#使用evalf函数传值>>> (5*x+4).evalf(subs={x:6})34.0000000000000#多元代数式>>> y=sympy.Symbol('y')>>> (x*x+y*y).subs({x:3,y:4})25>>> (x*x+y*y).evalf(subs={x:3,y:4})25.0000000000000>>> f=1/x>>> f.subs(x,y)1/y>>> f.subs(x,5)1/5

代数方程和方程组

在初等数学中,通常都存在一元一次方程,一元二次方程等,并且在不同的域上有着不同的解。SymPy 里面的

相应函数就是 solveset,根据定义域的不同,可以获得完全不同的解。

初一学习一元一次方程组、二元一次方程、三元一次方程组,初三学习一元二次方程,使用 Sympy 的solve()函数就能轻松解题。

解一元一次方程

函数solve(expr,var), solveset(expr,var,domain=S.x)用来求解一元一次方程。

x∈R:x3−1=0,x∈C:x3−1=0,x∈R:ex−x=0,x∈R:ex−1=0,x∈C:ex−1=0x ∈ \mathbb{R} : x^3 − 1 = 0,\\ x ∈ \mathbb{C} : x^3 − 1 = 0,\\ x ∈ \mathbb{R} : e^x − x = 0,\\ x ∈ \mathbb{R} : e^x − 1 = 0,\\ x ∈ \mathbb{C} : e^x − 1 = 0x∈R:x3−1=0,x∈C:x3−1=0,x∈R:ex−x=0,x∈R:ex−1=0,x∈C:ex−1=0

>>> from sympy import *>>> from sympy.abc import x,y>>> from sympy import solve,linsolve,Eq>>> x = Symbol('x')>>> solve(x**4-1,x)[-1, 1, -I, I]>>> solve([x+5*y-2,-3*x+6*y-15],[x,y]){x: -3, y: 1}>>> solve(6*x+6*(x-2000)-150000,x) #默认 expr=0[13500]#对一个方程求解,使用solve>>> solve(Eq(6*x+6*(x-2000),150000),x) #Eq可以解决左右表达式,建议用默认方式[13500]>>> solve(Eq(2*x-1,3), x) #2x-1=3[2]>>> solveset(Eq(x**3,1),x, domain=S.Reals)FiniteSet(1)>>> solveset(Eq(x**3,1),x, domain=plexes)FiniteSet(1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2)>>> solveset(Eq(exp(x),x),x, domain=plexes)ConditionSet(x, Eq(-x + exp(x), 0), Complexes)>>> solveset(exp(x),x)EmptySet()>>> solveset(exp(x)-1,x) #缺省为ComplexesImageSet(Lambda(_n, 2*_n*I*pi), Integers)>>> solveset(exp(x)-1,x,domain=S.Reals){0}>>> solveset(exp(x)-1,x,domain=plexes)ImageSet(Lambda(_n, 2*_n*I*pi), Integers)

在这里,Lambda 表示的是数学公式,第一个是自变量,第二个是函数,最后是自变量的定义域。

我们需要掌握Python的代码符号和数学符号之间的对应关系, 解一元一次方程就非常简单。

解多元一次方程组

在线性代数中,最常见的还是多元一次方程组。解多元一次方程组,方法同上。还可以用linsolve([eq1,eq2,...],[x,y,z,...])

{x+y=102x+y=16\begin{cases} x+y=10\\ 2x+y=16 \end{cases}{x+y=102x+y=16​

>>> from sympy import *>>> x,y = symbols('x y')>>> solve([x+y-10,2*x+y-16],[x,y]){x: 6, y: 4} #解为 $x=6, y=4$#对多个方程求解,也可以使用linsolve。方程的解为x=-1,y=3>>> linsolve([x+2*y-5,2*x+y-1],[x,y]){(-1, 3)} #解为 x=-1,y=3>>> linsolve([x+2*y-5,2*x+y-1],(x,y)){(-1, 3)}>>> solve([sin(x+y),cos(x-y)],[x,y])[(-3*pi/4, 3*pi/4), (-pi/4, pi/4), (pi/4, 3*pi/4), (3*pi/4, pi/4)]>>> solve([sin(x-y),cos(x+y)],[x,y])[(-pi/4, 3*pi/4), (pi/4, pi/4), (3*pi/4, 3*pi/4), (5*pi/4, pi/4)]>>> solve([sin(x-y),cos(x-y)],[x,y])[]>>> solve([sin(x+y),cos(x+y)],[x,y])[]

解三元一次方程组:

{x+y+z=12x+2y+5z=22x=4y\begin{cases} x+y+z=12\\ x+2y+5z=22\\ x=4y \end{cases}⎩⎪⎨⎪⎧​x+y+z=12x+2y+5z=22x=4y​

>>> linsolve([x+y+z-12,x+2*y+5*z-22,x-4*y],[x,y,z]){(8, 2, 2)} #解为x=8,y=2,z=2

解一元二次方程组

一元二次方程一般式求解:ax2+bx+c=0,a≠0ax^2+bx+c=0, a\ne0ax2+bx+c=0,a​=0.

>>> from sympy import *>>> x,y = symbols('x y')>>> a,b,c = symbols('a b c')>>> solve(a*x**2+b*x+c,x)[(-b + sqrt(-4*a*c + b**2))/(2*a), -(b + sqrt(-4*a*c + b**2))/(2*a)]

结果为[(-b + sqrt(-4*a*c + b**2))/(2*a), -(b + sqrt(-4*a*c + b**2))/(2*a)], 二次方程有两个解,这里的格式就是一个列表。转为我们常见的数学公式即为:

−b+b2−4ac2a,−b−b2−4ac2a\dfrac{-b+\sqrt{b^2-4ac}}{2a},\dfrac{-b-\sqrt{b^2-4ac}}{2a}2a−b+b2−4ac​​,2a−b−b2−4ac​​

常记 Δ=b2−4ac\Delta=b^2-4acΔ=b2−4ac,称为判别式。则有两根为

x1=−b+Δ2a,x2=−b−Δ2ax_1=\dfrac{-b+\sqrt{\Delta}}{2a},x_2=\dfrac{-b-\sqrt{\Delta}}{2a}x1​=2a−b+Δ​​,x2​=2a−b−Δ​​

满足根与系数的关系式:x1+x2=−ba,x1⋅x2=cax_1+x_2=-\dfrac{b}{a}, x_1\cdot x_2=\dfrac{c}{a}x1​+x2​=−ab​,x1​⋅x2​=ac​

微积分Calculus

微积分是大学高等数学里非常重要的学习内容,比如求极限、导数、微分、不定积分、定积分等都是可以使用 Sympy 来运算的。

高阶微分与偏导

可以使用diff(代数式, 变量, 求导的次数)函数对代数式求导,一阶微分可以省略求导次数。比如我们要对 sin⁡(x)ex\sin(x)e^xsin(x)ex 进行 xxx 求导,以及求导两次。

求导一次的结果就是exp(x)*sin(x) + exp(x)*cos(x),也就是 exsin⁡(x)+excos⁡(x)e^x\sin(x)+e^x\cos(x)exsin(x)+excos(x) ;

求导两次的结果是2*exp(x)*cos(x),也就是 2excos⁡(x)2e^x\cos(x)2excos(x)

代码如下:

>>> from sympy import *>>> x,y = symbols('x y')>>> diff(sin(x)*exp(x),x)# 初等函数exp(x)*sin(x) + exp(x)*cos(x)>>> diff(sin(x)*exp(x),x,2) # 2阶导数2*exp(x)*cos(x)>>> diff(sin(x),x)cos(x)>>> diff(sin(2*x),x)2*cos(2*x)>>> diff(tan(2*x),x)2*tan(2*x)**2 + 2>>> diff(tan(x),x)tan(x)**2 + 1

可以通过以下验证:

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

计算高阶微分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)

求偏导如下:

>>> diff(3*x**2*y*z,x,y)6*x*z

求不定积分

SymPy支持不定积分,超越函数与特殊函数的定积分。SymPy有力的扩展了Risch-Norman 算法和模型匹配算法

Sympy是使用integrate(代数式,变量)来求不定积分的。

初等函数

比如我们要求∫(exsin⁡(x)+excos⁡(x))dx\int(e^x\sin{(x)} + e^x\cos{(x)})\,dx∫(exsin(x)+excos(x))dx

>>> from sympy import *>>> x = Symbol('x')>>> integrate(exp(x)*sin(x)+ exp(x)*cos(x),x)exp(x)*sin(x)>>> integrate(1/x,x)log(x)>>> integrate(1/x,(x,1,2))log(2)

执行之后的结果为:exp(x)*sin(x)转化之后为:exsin⁡(x)e^x\sin(x)exsin(x)

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

特殊函数

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

求定积分

Sympy同样是使用integrate()函数来做定积分的求解,只是语法不同:integrate(代数式,(变量,下区间,上区间)),我们来看如果求解 ∫−∞+∞sin⁡(x2)dx\int_{-\infty}^{+\infty}\sin(x^2)\mathbf{d}x∫−∞+∞​sin(x2)dx

>>> from sympy import *>>> from sympy.abc import pi>>> x,y = symbols('x y')>>> expr=sin(x**2)>>> i_expr=integrate(expr, (x, -oo, oo))>>> print(i_expr)>>> integrate(sin(x),(x,0,pi))-cos(pi)+1

执行之后的结果为sqrt(2)*sqrt(pi)/2,也就是 2π2\dfrac{\sqrt{2}\sqrt{\pi}}{2}22​π​​

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

也支持广义积分:

∫−∞0e−x2dx=π2,∫0+∞e−xdx=1,∫−∞+∞∫−∞+∞e−x2−y2dxdy=π\int_{-\infty}^0 e^{-x^2}\mathbf{d}x=\dfrac{\sqrt{\pi}}{2},\qquad \int_{0}^{+\infty}e^{-x} \mathbf{d}x=1,\qquad \int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty}e^{-x^2-y^2}\mathbf{d}x\mathbf{d}y=\pi∫−∞0​e−x2dx=2π​​,∫0+∞​e−xdx=1,∫−∞+∞​∫−∞+∞​e−x2−y2dxdy=π

>>> integrate(cos(x**2),(x,-oo,oo))sqrt(2)*sqrt(pi)/2>>> integrate(sin(x**2),(x,-oo,oo))sqrt(2)*sqrt(pi)/2>>> integrate(exp(-x**2),(x,-oo,0))sqrt(pi)/2>>> integrate(exp(-x),(x,0,oo))1>>> integrate(exp(-x**2-y**2),(x,-oo,+oo),(y,-oo,+oo))pi>>> integrate(log(x),(x,0,1))-1

求多重积分

求多重积分,先求里面的积分,再求外面的

例如:f(x)=∫0x2xdx,∫03f(x)dxf(x)=\int_0^x 2x \mathbf{d}x, \qquad\int_0^3 f(x)\mathbf{d}xf(x)=∫0x​2xdx,∫03​f(x)dx

>>> x,t=sympy.symbols('x t')>>> f=2*t>>> g(x + 1)**(1/x)>>> g=integrate(f,(t,0,x))>>> integrate(g,(x,0,3))9

求极限

求极限用limit(func,x,x_0)

在sympy中极限容易求出,它们遵循极限语法limit(function, variable, point),所以计算 x→0x\to0x→0 时 f(x)f(x)f(x) 的极限,即limit(f, x, 0)

lim⁡x→0(1+x)1x=e,lim⁡x→∞(1+1x)x=e\displaystyle\lim_{x\to0}(1+x)^{\frac{1}{x}}=e,\qquad \lim_{x\to \infty}\left(1+\dfrac{1}{x}\right)^x=ex→0lim​(1+x)x1​=e,x→∞lim​(1+x1​)x=e

>>> from sympy.abc import x,f,g,h,E>>> from sympy import limit>>> limit(1/x,x,0,'+') # x-->+0oo>>> f=sin(x)/x# 定义函数>>> g=(1+x)**(1/x)>>> h=(1+1/x)**x>>> limit(f,x,0) # 三个参数是 函数,变量,趋向值1>>> limit(g,x,0)E>>> limit(h,x,oo)E

求极限 Sympy 是使用limit(代数式,变量,极限值)函数来求极限的,比如我们要求 lim⁡x→0sin(x)x\displaystyle\lim_{x\to0}\dfrac{sin(x)}{x}x→0lim​xsin(x)​ 的值。

>>> from sympy import *>>> x = symbols('x')>>> limit(sin(x)/x, x, 0)

执行后即可得到结果为 1。

求和

级数求和summation(function,(n,1,100))S=∑n=11002nS=\displaystyle\sum_{n=1}^{100}{2n}S=n=1∑100​2n

>>> import sympy>>> n=sympy.Symbol('n') # 定义变量>>> sympy.summation(2*n,(n,1,100)) # 前面参数放函数,后面放变量的变化范围10100

解带有求和式子的方程

∑i=15x+10x=15\displaystyle\sum_{i=1}^5 x+10x=15i=1∑5​x+10x=15

解释一下,iii 可以看做是循环变量,就是 xxx 自己加五次, 先定义变量,再写出方程。

>>> x=sympy.Symbol('x')>>> i=sympy.Symbol('i')>>> solve(summation(x,(i,1,5))+10*x-15,x)[1]f=sympy.summation(x,(i,1,5))+10*x-15result=sympy.solve(f,x)print(result)

复数

>>>from sympy import Symbol, exp, I>>>x = Symbol("x")>>>exp(I*x).expand()exp(I*x)>>>exp(I*x).expand(complex=True)I*exp(-im(x))*sin(re(x)) + cos(re(x))*exp(-im(x))>>>x = Symbol("x", real=True)>>>exp(I*x).expand(complex=True)I*sin(x) + cos(x)

函数

三角函数

>>> sin(x+y).expand(trig=True)sin(x)*cos(y) + sin(y)*cos(x)>>> cos(x+y).expand(trig=True)-sin(x)*sin(y) + cos(x)*cos(y)>>> sin(I*x)I*sinh(x)>>> sinh(I*x)I*sin(x)>>> asinh(I)I*pi/2>>> asinh(I*x)I*asin(x)>>> sinh(x).series(x,0,10)x + x**3/6 + x**5/120 + x**7/5040 + x**9/362880 + O(x**10)>>> asin(x).series(x,0,10)x + x**3/6 + 3*x**5/40 + 5*x**7/112 + 35*x**9/1152 + O(x**10)>>> asinh(x).series(x,0,10)x - x**3/6 + 3*x**5/40 - 5*x**7/112 + 35*x**9/1152 + O(x**10)

球谐函数

球谐函数建议阅读原文

球谐函数可以看作是将单位球面上的每一点(或者三维空间中的每个方向)映射到一个复数函数值.

从在物理中的来源上看, 球谐函数是 Laplace 算子角项部分的一组正交完备的解.

从数学上看, 球谐函数实际上是 SO(3) 一组不可约表示的基, 而 Laplace 算子角项部分也正好就是 SO(3) 的 Casimir 算子.

Sympy里用Ynm(1, 0, theta, phi)

>>> from sympy.abc import theta,phi>>> Ynm(1, 0, theta, phi)Ynm(1, 0, theta, phi)>>> Ynm(1, 1, theta, phi)Ynm(1, 1, theta, phi)>>> Ynm(2, 1, theta, phi)Ynm(2, 1, theta, phi)

阶乘和伽马函数

>>> x = Symbol('x')>>> y = Symbol('y', integer=True) # 定义整数变量>>> factorial(x)factorial(x)>>> factorial(y)factorial(y)>>> factorial(x).series(x,0,3)1 - EulerGamma*x + x**2*(EulerGamma**2/2 + pi**2/12) + O(x**3)

Zeta函数

>>> zeta(4,x)zeta(4, x)>>> zeta(4,1)pi**4/90>>> zeta(4,2)-1 + pi**4/90>>> zeta(4,3)-17/16 + pi**4/90>>> zeta(4,4)-1393/1296 + pi**4/90

多项式

>>> chebyshevt(2,x)2*x**2 - 1>>> chebyshevt(4,x)8*x**4 - 8*x**2 + 1>>> legendre(2,x)3*x**2/2 - 1/2>>> legendre(8,x)6435*x**8/128 - 3003*x**6/32 + 3465*x**4/64 - 315*x**2/32 + 35/128>>> assoc_legendre(2,1,x)-3*x*sqrt(1 - x**2)>>> assoc_legendre(2,2,x)3 - 3*x**2>>> hermite(3,x)8*x**3 - 12*x

常微分ODE方程

在常微分方程(Ordinary Differential Equation)中,最常见的就是解方程,而解方程主要是靠dsolve函数。

求解下列常微分方程:

dfdx+f(x)=0d2fdx2+f(x)=0d3fdx3+f(x)=0\dfrac{\mathbb{d}f}{\mathbb{d}x}+f(x)=0\\ \dfrac{\mathbb{d}^2f}{\mathbb{d}x^2}+f(x)=0\\ \dfrac{\mathbb{d}^3f}{\mathbb{d}x^3}+f(x)=0dxdf​+f(x)=0dx2d2f​+f(x)=0dx3d3f​+f(x)=0

>>> f=Function('f') #一定要声明f=Function('f')>>> f(x).diff(x,x)+f(x) #注意在使用输入该命令之前,f要先声明f(x) + Derivative(f(x), (x, 2))>>> dsolve(f(x).diff(x,x)+f(x),f(x))Eq(f(x), C1*sin(x) + C2*cos(x))>>> f = sympy.Function('f') # 定义函数f>>> sympy.dsolve(sympy.Derivative(f(x),x) + f(x), f(x))Eq(f(x), C1*exp(-x))>>> sympy.dsolve(sympy.Derivative(f(x),x,2) + f(x), f(x))Eq(f(x), C1*sin(x) + C2*cos(x))>>> sympy.dsolve(sympy.Derivative(f(x),x,3) + f(x), f(x))Eq(f(x), C3*exp(-x) + (C1*sin(sqrt(3)*x/2) + C2*cos(sqrt(3)*x/2))*sqrt(exp(x)))

而常微分方程对于不同的方程类型也有着不同的解法,可以使用classify_ode来判断常微分方程的类型:

>>> sympy.classify_ode(sympy.Derivative(f(x),x)+f(x),f(x))('separable', '1st_exact', '1st_linear', 'almost_linear', '1st_power_series','lie_group', 'nth_linear_constant_coeff_homogeneous', 'separable_Integral','1st_exact_Integral', '1st_linear_Integral', 'almost_linear_Integral')>>> sympy.classify_ode(sympy.Derivative(f(x),x,2)+f(x),f(x))('nth_linear_constant_coeff_homogeneous', '2nd_power_series_ordinary')>>> sympy.classify_ode(sympy.Derivative(f(x),x,3)+f(x),f(x))('nth_linear_constant_coeff_homogeneous',)

偏微分PDE方程

在偏微分方程(Partitial Differential Equation)中,同样可以直接求解和判断偏微分方程的类型,分别使用函数pdsolve() 和 classify_pde()。假设 f=f(x,y)f=f(x,y)f=f(x,y) 是一个二元函数,分别满足以下偏微分方程:

∂f∂x+∂f∂y=0∂f∂x+∂f∂y+f=0∂f∂x+∂f∂y+f+10=0\dfrac{\partial f}{\partial x}+\dfrac{\partial f}{\partial y}=0\\ \dfrac{\partial f}{\partial x}+\dfrac{\partial f}{\partial y}+f=0\\ \dfrac{\partial f}{\partial x}+\dfrac{\partial f}{\partial y}+f+10=0∂x∂f​+∂y∂f​=0∂x∂f​+∂y∂f​+f=0∂x∂f​+∂y∂f​+f+10=0

>>> f = sympy.Function("f")(x,y)>>> ff(x, y)>>> sympy.pdsolve(sympy.Derivative(f,x)+sympy.Derivative(f,y),f)Eq(f(x, y), F(x - y))>>> sympy.pdsolve(f.diff(x)+f.diff(y)+f,f)Eq(f(x, y), F(x - y)*exp(-x/2 - y/2))>>> sympy.pdsolve(f.diff(x)+f.diff(y)+f+10,f)Eq(f(x, y), F(x - y)*exp(-x/2 - y/2) - 10)

查看类型就用classify_pde()函数:

>>> sympy.classify_pde(f.diff(x)+f.diff(y),f)('1st_linear_constant_coeff_homogeneous',)>>> sympy.classify_pde(f.diff(x)+f.diff(y)+f,f)('1st_linear_constant_coeff_homogeneous',)>>> sympy.classify_pde(f.diff(x)+f.diff(y)+f+10,f)('1st_linear_constant_coeff', '1st_linear_constant_coeff_Integral')

不过目前的 PDE 解法貌似只支持一阶偏导数,二阶或者以上的偏导数就不支持了。

数论

在数论中,素数就是一个最基本的概念之一。而素数的批量计算,比较快的方法就是筛法(sieve method)。

在 sympy 中,同样有sympy.sieve这个工具,用于计算素数。如果想输出前100个素数:

>>> sympy.sieve._reset()>>> sympy.sieve.extend_to_no(100)>>> sympy.sieve._listarray('l', [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239,241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337,347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433,439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631])

如果想输出一个区间内的所有素数,可以使用primerange(a,b)函数:

>>> [i for i in sympy.sieve.primerange(50,200)][53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199]

search()函数是为了计算某个数附近是第几个素数:

>>> sympy.sieve.search(10)(4, 5) # 10在第4个素数和第5个素数之间>>> sympy.sieve.search(11)(5, 5) # 5是第5个素数>>> sympy.sieve.search(110)(29, 30) # 110在第29和第30个素数之间>>> sympy.sieve.search(18)(7, 8) # 18在第7和第8个素数之间

如果只想获得第 nnn 个素数,则使用函数sympy.ntheory.generate.prime(n)即可。如果是希望计算 xxx 后面的下一个素数,使用sympy.ntheory.generate.nextprime(x)即可。判断 xxx 是否是素数,可以使用

sympy.ntheory.generate.isprime(x)

>>> sympy.ntheory.generate.prime(10)29>>> sympy.ntheory.generate.nextprime(10)11>>> sympy.ntheory.generate.nextprime(11)13sympy-tutorial.md 2/3/20 / 17>>> sympy.ntheory.generate.isprime(11)True>>> sympy.ntheory.generate.isprime(12)False

除此之外,SymPy 的数论方法还有很多,需要读者根据 SymPy 的官方文档自行探索。

线性代数

矩阵

在矩阵论中,最常见的就是单位矩阵了,而单位矩阵只与一个参数有关,那就是矩阵的大小, Sympy中用函数eye(n,m)创建 n×mn\times mn×m的单位矩阵。

>>> eye(4)Matrix([[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]])>>> eye(2,3)Matrix([[1, 0, 0],[0, 1, 0]])

另外还有全零zeros(n,m)全一ones(n,m)矩阵,意思就是矩阵中的所有值全部是零和一

>>> ones(3,4)Matrix([[1, 1, 1, 1],[1, 1, 1, 1],[1, 1, 1, 1]])>>> zeros(3,2)Matrix([[0, 0],[0, 0],[0, 0]])

而对角矩阵也可以使用diag(n,m,k,...)轻松获得:

>>> diag(1,2,3,4)Matrix([[1, 0, 0, 0],[0, 2, 0, 0],[0, 0, 3, 0],[0, 0, 0, 4]])

一般矩阵由矩阵类Matrix([[],[]]创建

>>>from sympy import Matrix>>> A=Matrix([[1,0],[0,1]])>>> B=Matrix([[1,1],[0,2]])>>> A+B #加Matrix([[2, 1],[0, 3]])>>> A-B #减Matrix([[0, -1],[0, -1]])>>> A*B #乘Matrix([[1, 1],[0, 2]])>>> A*B**-1 #逆矩阵Matrix([[1, -1/2],[0, 1/2]])>>> B**-1Matrix([[1, -1/2],[0, 1/2]])>>> A.T #转置矩阵Matrix([[1, 0],[0, 1]])>>> B.TMatrix([[1, 0],[1, 2]])>>> A.det() #行列式的值1>>> B.det()2

不只是数值矩阵,亦可为代数矩阵,即矩阵中存在符号:

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

在某些情况下,需要对矩阵进行加上一行或者加上一列的操作,在这里就可以使用row_insert或者

col_insert函数:第一个参数表示插入的位置,第二个参数就是相应的行向量或者列向量。

而在删除上就很简单了,直接使用row_del或者col_del即可.

>>> A.row_insert(1,Matrix([[10,10]]))Matrix([[ 1, 0],[10, 10],[ 0, 1]])>>> A.col_insert(0,Matrix([3,5]))Matrix([[3, 1, 0],[5, 0, 1]])>>> A.row_del(0)>>> AMatrix([[0, 1]])>>> A.col_del(1)>>> AMatrix([[0]])

在对角化方面,同样可以使用eigenvals(),eigenvects(), diagonalize()函数

>>> A=sympy.Matrix([[1,1],[0,2]])>>> AMatrix([[1, 1],[0, 2]])>>> A.eigenvals() # 特征值{1: 1, 2: 1}>>> A.eigenvects() # 特征向量[(1, 1, [Matrix([[1],[0]])]), (2, 1, [Matrix([[1],[1]])])]>>> A.diagonalize() # 对角化(Matrix([[1, 1],[0, 1]]), Matrix([[1, 0],[0, 2]]))

eigenvals()返回的结果中,第一个表示特征值,第二个表示该特征值的重数。在特征向量eigenvects()

中,第一个表示特征值,第二个表示特征值的重数,第三个表示特征向量。

在对角化diagonalize()中,第一个矩阵表示 PPP,第二个矩阵表示 D,A=P×D×P−1D, A=P\times D\times P^{-1}D,A=P×D×P−1。

在矩阵中,最常见的还是多元一次方程的解。如果要求 Ax=bAx=bAx=b 的解,可以有以下方案:

>>> AMatrix([[1, 1],[0, 2]])>>> b = sympy.Matrix([3,5])>>> bMatrix([[3],[5]])>>> A**-1*bMatrix([[1/2],[5/2]])>>> sympy.linsolve((A,b))FiniteSet((1/2, 5/2))>>> sympy.linsolve((A,b),[x,y])FiniteSet((1/2, 5/2))

集合

集合论可以说是数学的基础,在任何数学的方向上都能够看到集合论的身影。在 SymPy 里面,有一个类叫做

sympy.sets。在集合论里面,常见的就是边界,补集,包含,并集,交集等常见的操作。但是感觉 SymPy 中的集合论操作主要集中在实数域或者复数域上。

定义闭区间和开区间(Interval(s,e),Interval.open(s,e))

对于闭区间 I=[0,1]I=[0,1]I=[0,1] 和开区间 J=(0,1)J=(0,1)J=(0,1) 而言,在 SymPy 中使用以下方法来表示:

>>> I = sympy.Interval(0,1)>>> IInterval(0, 1)>>> J = sympy.Interval.open(0,1)>>> JInterval.open(0, 1)>>> K = sympy.Interval(0.5,2)>>> KInterval(0.500000000000000, 2)>>> K.start0.500000000000000>>> K.end2

长度用 .measure方法来表示

>>> K.measure1.50000000000000

其闭包用 .closure方法来表示

>>> K.closureInterval(0.500000000000000, 2)

其内点用 .interior方法来表示

>>> K.interiorInterval.open(0.500000000000000, 2)

判断其边界条件可以使用 left_open 或者 right_open 来做

>>> K.left_openFalse>>> K.right_openFalse>>> J.left_openTrue

两个集合之间的操作

#Interval(start, end, left_open=False, right_open=False)#- Only real end points are supported#| - Interval(a, b) with a > b will return the empty set#| - Use the evalf() method to turn an Interval into an mpmath#| 'mpi' interval instance>>> I = sympy.Interval(0,1) # I =[0,1]>>> K = sympy.Interval(0.5,2) # K=[0.5,2]>>> I.intersect(K)Interval(0.500000000000000, 1)>>> I.union(K)Interval(0, 2)>>> I - KInterval.Ropen(0, 0.500000000000000) # [0,0.5)>>> K - IInterval.Lopen(1, 2) #(1,2]>>> I.symmetric_difference(K)Union(Interval.Ropen(0, 0.500000000000000), Interval.Lopen(1, 2))

实数集 R\mathbb{R}R 在 SymPy 中用sympy.S.Reals来表示,自然数 N\mathbb{N}N 使用sympy.S.Naturals,非负整数用sympy.S.Naturals0,整数 Z\mathbb{Z}Z用sympy.S.Integers来表示。补集的计算可以用减号,也可以使用

complement函数。

>>> sympy.S.RealsReals>>> sympy.S.Reals - IUnion(Interval.open(-oo, 0), Interval.open(1, oo))>>> plement(sympy.S.Reals)Union(Interval.open(-oo, 0), Interval.open(1, oo))>>> sympy.plement(I)EmptySet>>> plement(K)Interval.Lopen(1, 2)

逻辑

在逻辑运算中,我们可以使用 A,B,CA,B,CA,B,C 来代表元素。&, |, ~, >>分别表示AND,OR,NOT,imply。而逻辑

运算同样可以使用sympy.simplify_logic简化。

>>> A,B,C=sympy.symbols('A B C')>>> sympy.simplify_logic(A|(A&B))A>>> sympy.simplify_logic((A>>B) & (B>>A))(A & B) | (~A & ~B)>>> A >> BImplies(A, B)

级数

级数展开

高数中Taylor Series 有泰勒展开式,拉格朗日展开式

对于常见函数的 Taylor Series,SymPy 也是有非常简便的方法,那就是series函数。其参数包括 expr,x,x0,n,direxpr, x, x_0 ,n, direxpr,x,x0​,n,dir,分别对应着表达式 expr,函数的自变量 xxx,Taylor Series 的中心点 x0x_0x0​,nnn 表示阶数,dirdirdir 表示方向,包括 “±”,"-","+",分别表示 x→x0,x→x0−,x→x0+x\to x_0,x\to x_0^-, x\to x_0^+x→x0​,x→x0−​,x→x0+​。

ex=1+x+x22!+x33!+x44!+...+xnn!+o(xn)e^x=1+x+\dfrac{x^2}{2!}+\dfrac{x^3}{3!}+\dfrac{x^4}{4!}+...+\dfrac{x^n}{n!}+o(x^n)ex=1+x+2!x2​+3!x3​+4!x4​+...+n!xn​+o(xn)

比如当 n=3n=3n=3 时,

ex=1+x+x22+o(x3)e^x=1+x+\dfrac{x^2}{2}+o(x^3)ex=1+x+2x2​+o(x3)

这里实现的方法是:sympy代数式.series(变量, 0, n)func.series(var,point, order)

>>> from sympy import *>>> from sympy.abc import x,y,z,a,b,c,u,v,w,t,h,k,A,B,C,D,E,F>>> exp(x).series(x,0,6)1 + x + x**2/2 + x**3/6 + x**4/24 + x**5/120 + O(x**6)>>> (1/cos(x)).series(x,0,10)1 + x**2/2 + 5*x**4/24 + 61*x**6/720 + 277*x**8/8064 + O(x**10)>>> (sin(x)).series(x,0,10)x - x**3/6 + x**5/120 - x**7/5040 + x**9/362880 + O(x**10)>>> (cos(x)).series(x,0,10)1 - x**2/2 + x**4/24 - x**6/720 + x**8/40320 + O(x**10)>>> exp(I*x).series(x,0,10)1 + I*x - x**2/2 - I*x**3/6 + x**4/24 + I*x**5/120 - x**6/720 - I*x**7/5040 + x**8/40320 + I*x**9/362880 + O(x**10)

以上可以看出 eix=cos⁡(x)+isin⁡(x),ex=∑n=0∞xnn!\displaystyle e^{ix}=\cos(x)+i \sin(x), \;e^x=\sum_{n=0}^{\infty}\dfrac{x^n}{n!}eix=cos(x)+isin(x),ex=n=0∑∞​n!xn​

级数收敛

计算某个级数是发散的,还是收敛的,就可以使用is_convergent()函数。

>>> n = sympy.Symbol("n", integer =True)>>> nn>>> sympy.Sum(1/n,(n,1,sympy.oo)).is_convergent()False>>> sympy.Sum(1/n**2,(n,1,sympy.oo)).is_convergent()True

级数求和

如果想计算出收敛级数的值,加上doit()函数即可;如果想计算有效数字,加上evalf()函数即可。

>>> sympy.Sum(1/n**2, (n,1,sympy.oo)).evalf()1.64493406684823>>> sympy.Sum(1/n**2, (n,1,sympy.oo)).doit()pi**2/6>>> sympy.Sum(1/n**3, (n,1,sympy.oo)).evalf()1.5690315959>>> sympy.Sum(1/n**3, (n,1,sympy.oo)).doit()zeta(3)

级数连乘

除了加法之外,SymPy 也支持连乘,其符号是sympy.Product

>>> sympy.Product(n/(n+1), (n,1,sympy.oo)).is_convergent()False>>> sympy.Product(sympy.cos(sympy.pi/n), (n,1,sympy.oo)).is_convergent()True>>> sympy.Product(sympy.cos(sympy.pi/n), (n,1,sympy.oo)).doit()Product(cos(pi/n), (n, 1, oo))>>> sympy.Product(sympy.cos(sympy.pi/n), (n,1,sympy.oo)).evalf()Product(cos(pi/n), (n, 1, oo))

求代数式的浮点数.evalf(n)方法

evalf()函数可以用求出代数式的浮点数。

>>> (1/x).evalf(subs={x: 3.0}, n=21)0.333333333333333333333rather than>>> (1/x).subs({x: 3.0}).evalf(21)0.333333333333333314830>>> E.evalf(10)2.718281828>>> pi.evalf(15)3.14159265358979>>> sqrt(2).evalf() #查看实数的有效数字,缺省151.41421 35623 7310>>> sqrt(3).evalf()1.73205080756888

SymPy的范畴论工具

SymPy 还支持 范畴论(Category Theory)的一些计算方法,在这里简要地列举一下。

>>> A = sympy.categories.Object("A")>>> B = sympy.categories.Object("B")>>> f = sympy.categories.NamedMorphism(A,B,"f")>>> f.domainObject("A")>>> f.codomainObject("B")

由于范畴论是数学的“黑话”,因此其余方法留给范畴论的科研人员自行翻阅

系数匹配

使用.match()方法,引用Wild类,来执行表达式的匹配。该方法会返回一个字典。 帮助文档可以访问help(Wild)

>>>from sympy import *>>>x = Symbol('x')>>>p = Wild('p')>>>(5*x**2).match(p*x**2){p_: 5}>>>q = Wild('q')>>>(x**2).match(p*x**q){p_: 1, q_: 2}>>> from sympy import Wild, WildFunction, cos, pi>>> from sympy.abc import x, y, z>>> a = Wild('a')>>> x.match(a){a_: x}>>> pi.match(a){a_: pi}>>> (3*x**2).match(a*x){a_: 3*x}>>> cos(x).match(a){a_: cos(x)}>>> b = Wild('b', exclude=[x])>>> (3*x**2).match(b*x)>>> b.match(a){a_: b_}>>> A = WildFunction('A')>>> A.match(a){a_: A_}

如果匹配不成功,则返回None:

>>>print (x+1).match(p**x)None

可以使用Wild类的exclude参数(排除参数),排除不需要和无意义的匹配结果,来保证结论中的显示是唯一的:

>>>x = Symbol('x')>>>p = Wild('p', exclude=[1,x])>>>print (x+1).match(x+p) # 1 is excludedNone>>>print (x+1).match(p+1) # x is excludedNone>>>print (x+1).match(x+2+p) # -1 is not excluded{p_: -1}

打印输出

有一个打印的有效模块,sympy.printing。用这个模块实现其他的打印。

可以各种方式打印输出,如pprint, print, latex, python, mathml,...

标准 print

str(expression)返回如下:

>>> from sympy import Integral>>> from sympy.abc import x>>> print(x**2)x**2>>> str(x**2)'x**2'>>> print(1/x)1/x>>> print(Integral(x**2, x))Integral(x**2, x)

字符艺术打印(Pretty Printing) pprint

pretty(expr), pretty_print(expr), pprint(expr): 分别返回或者输出,,表达式的漂亮描述。

个人觉得这个打印不是很能接受,仅仅只是 ASCII 艺术模仿 LaTeX 输出。看起来很不是滋味,故不推荐。

pprint函数可以输出不错的 ascii 艺术:

>>>from sympy import Integral, pprint>>>from sympy.abc import x>>>pprint(x**2) #doctest: +NORMALIZE_WHITESPACE2x>>>pprint(1/x)1-x>>>pprint(Integral(x**2, x))/|| 2| x dx|/

在 python 解释器中,为使 pretty printing 为默认输出,使用:

>>> import sys>>> sys.displayhook = pprint>>> var("x")x>>> x**3/33x--3>>> Integral(x**2, x) #doctest: +NORMALIZE_WHITESPACE/|| 2| x dx|/

Python字符串打印成一行Python printing

>>> from sympy.printing.python import python>>> from sympy import Integral>>> from sympy.abc import x>>> print(python(x**2))x = Symbol('x')e = x**2>>> python(x**2)"x = Symbol('x')\ne = x**2">>> print(python(1/x))x = Symbol('x')e = 1/x>>> python(1/x)"x = Symbol('x')\ne = 1/x">>> print(python(Integral(x**2, x)))x = Symbol('x')e = Integral(x**2, x)>>> python(Integral(x**2,x))"x = Symbol('x')\ne = Integral(x**2, x)"

输出成LaTeX形式LaTeX printing

latex(expr), print_latex(expr):分别返回或者输出,LaTex描写的表达式。

个人推荐此种 LaTeX 打印输出方式,方便与LaTeX对接。

>>>from sympy import Integral, latex>>>from sympy.abc import x>>> latex(x**2)'x^{2}'>>> latex(x**2+y**2)'x^{2} + y^{2}'>>> latex(1/x)'\\frac{1}{x}'>>> print(latex(1/x))\frac{1}{x}>>> print(latex(Integral(x**2, x)))\int x^{2}\,dx>>> latex(Integral(x**2,x))'\\int x^{2}\\, dx'

输出成MathML形式MathML

mathml(expr), print_mathml(expr): 分别返回或者输出,MathML描写的表达式.

>>>from sympy.printing.mathml import mathml>>>from sympy import Integral, latex>>>from sympy.abc import x>>>print(mathml(x**2))<apply><power/><ci>x</ci><cn>2</cn></apply>>>> mathml(x**2)'<apply><power/><ci>x</ci><cn>2</cn></apply>'>>> print(mathml(1/x))<apply><power/><ci>x</ci><cn>-1</cn></apply>

数学符号

常用数学符合列表如下:

sympy.I #虚数单位isympy.E #自然对数低esympy.oo #无穷大sympy.pi #圆周率sympy.root(8,3) #求n次方根sympy.log(1024,2) #求对数sympy.factorial(4) #求阶乘sympy.sin(sympy.pi) #三角函数sympy.tan(sympy.pi/4)sympy.cos(sympy.pi/2)pi.evalf(10) #查看否点数的小数值(pi+exp(1)).evalf()>>> E**(I*pi)+1 #欧拉公式 e^{i\pi}+1=00

本文是本人学习过程中,总结了官方教程中的部分内容,目的是方便快速查找需要的内容。主要为一些复杂的符号运算提供机器运算结果,并验证自己的计算结果。后续会提供部分实际应用案例。

相关参考链接

Sympy源码库用Python学数学SymPy库常用函数Sympy’s documentation

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。