sympy的实用用法

Posted by wyj on May 3, 2019

我现在觉得我的python使用算是基本入了门。所以可以使用python完成很多c++做不到的事了。

发现sympy和numpy这两个库是真的好用。下面列举几个实例。

FFT

>>> from numpy.fft import *
>>> b=[2,1,0,0]
>>> a=[1,2,0,0]
>>> map(int,ifft(fft(a)*fft(b)))
__main__:1: ComplexWarning: Casting complex values to real discards the imaginary part
[2, 5, 2, 0]

矩阵

>>> from numpy import *
>>> from numpy.linalg import *
>>> m=array([[1,1],[1,0]]) #矩阵或普通高维数组
>>> matmul(m,m) #矩阵乘法
array([[2, 1],
       [1, 1]])
>>> det(m) #矩阵行列式
-1.0
>>> inv(m) #矩阵的逆
array([[ 0.,  1.],
       [ 1., -1.]])

生成函数

这里执行的是isympy,不是普通python解释器

#从OEIS上复制一个生成函数
>>> s="(2*x*(1 - 6*x^3 + 14*x^4 - 11*x^5 + 3*x^6))/(1 - x)^4"
>>> eval(s.replace("^","**")).series(x,0,10)
         2       3       4       5       6        7        8        9     10
2x + 8x  + 20x  + 28x  + 50x  + 82x  + 126x  + 184x  + 258x  + Ox  

其实可以直接sympify,当时不知道

其他的数学函数

>>> integrate(sin(x)/x,x) #不定积分
Si(x)
>>> integrate(E**(-x**2),(x,-oo,oo)) #定积分,oo是无穷大
π
>>> diff(E**(-x**2)) #微分
        2
      -x 
-2x   
>>> apart(x*(x+1)*(x+2)/6) #多项式乘法
 3    2    
x    x    x
── + ── + 
6    2    3
>>> factor(x**3/6+x**2/2+x/3) #因式分解
x(x + 1)(x + 2)
─────────────────
        6        
>>> dsolve(f(x)+1/f(x).diff(x),f(x)) #微分方程,f+1/f'=0
          __________           __________
f(x) = -╲╱ C - 2x , f(x) = ╲╱ C - 2x 
>>> summation(x**-2,(x,1,oo)) #求和,oo是无穷大
 2
π 
──
6 
>>> summation(x**-3,(x,1,oo)) #求和,他认得黎曼ζ函数
ζ(3)
>>> print(solve([x*y+2*x-3,x*x+y*y-2],[x,y])) #解任意方程
[(1, 1), (-(-2 + (-5/3 + (-1/2 - sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3) + 4/(9*(-1/2 - sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3)))**2)*(1/3 + (-1/2 - sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3) + 4/(9*(-1/2 - sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3)))/3, -5/3 + (-1/2 - sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3) + 4/(9*(-1/2 - sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3))), (-(-2 + (-5/3 + 4/(9*(-1/2 + sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3)) + (-1/2 + sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3))**2)*(1/3 + 4/(9*(-1/2 + sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3)) + (-1/2 + sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3))/3, -5/3 + 4/(9*(-1/2 + sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3)) + (-1/2 + sqrt(3)*I/2)*(2*sqrt(57)/9 + 46/27)**(1/3)), (-(-2 + (-5/3 + 4/(9*(2*sqrt(57)/9 + 46/27)**(1/3)) + (2*sqrt(57)/9 + 46/27)**(1/3))**2)*(4/(9*(2*sqrt(57)/9 + 46/27)**(1/3)) + 1/3 + (2*sqrt(57)/9 + 46/27)**(1/3))/3, -5/3 + 4/(9*(2*sqrt(57)/9 + 46/27)**(1/3)) + (2*sqrt(57)/9 + 46/27)**(1/3))]
# 刚才的输出太反人类了?
>>> for x,y in solve([x*y+2*x-3,x*x+y*y-2],[x,y]): print x.evalf(),y.evalf()
... 
1.00000000000000 1.00000000000000
-1.20409463685499 + 2.22291304593744*I -2.56519771738364 - 1.04342743589303*I
-1.20409463685499 - 2.22291304593744*I -2.56519771738364 + 1.04342743589303*I
1.40818927370998 0.130395434767279

计算几何

可以把sympy和numpy配合起来搞定数学作业

>>> A=[1,0,0]
>>> B=[1,1,0]
>>> E=[x,x,1]
>>> t=Rational(1)/2 
# 实际上使用S()就行了
>>> F=[x+t,x+t,1]
# 我错误的把array声明成了list,下面开始补救
>>> from numpy import *
>>> z=zeros(3)
>>> A=A+z
>>> B=B+z
>>> E=E+z
>>> F=F+z
>>> def cross(x,y):
...     return [x[1]*y[2]-x[2]*y[1],x[2]*y[0]-x[0]*y[2],x[0]*y[1]-x[1]*y[0]]
>>> sum(cross(A-E,B-E)*(F-E)) #我当时不会det,也不会np.cross
0.500000000000000
# 所以说体积是一个定值

其实numpy有cross函数,sympy也有几何运算,不需要这么麻烦。