SymPy 是 Python 的數學符號計算庫,用它可以進行數學公式的符號推導。為了調用方便,下面所有的實例程序都假設事先從 sympy 庫導入了所有內容:
>>> from sympy import *
* 表示所有的意思
1. 經典公式#
叫做歐拉恆等式,其中 e 是自然指數的底,i 是虛數單位,pi 是圓周率。此公式被譽為數學最奇妙的公式,它將 5 個基本數學常數用加法、乘法和幂運算聯繫起來。下面用 SymPy 驗證一下這個公式。
載入的符號中,E 表示自然指數的底,I 表示虛數單位,pi 表示圓周率,因此上述的公式可以直接如下計算:
>>> E**(I*pi)+1
0
歐拉恆等式可以下面的公式進行計算,
為了用 SymPy 求證上面的公式,我們需要引入變量 x。在 SymPy 中,數學符號是 Symbol 類的對象,因此必須先創建之後才能使用:
>>> x = Symbol('x')
expand 函數可以將公式展開,我們用它來展開 E**(I*x) 試試看:
>>> expand( E**(I*x) )
exp(I*x)
沒有成功,只是換了一種寫法而已。這裡的 exp 不是 math.exp 或者 numpy.exp,而是 sympy.exp,它是一個類,用來表述自然指數函數。
math.exp (x): 返回 x 的指數,x 必須是一個數。
numpy.exp (x): 返回 x 的指數,x 可以是數組,可以是一個數。
>>> import math
>>> import numpy as np
>>> x = 2
>>> y = np.array([1,2,3,4])
>>> z = np.array([2])
>>> math.exp(x)
7.38905609893065
>>> math.exp(z)
7.38905609893065
>>> math.exp(y)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: only length-1 arrays can be converted to Python scalars
>>> np.exp(x)
7.3890560989306504
>>> np.exp(z)
7.3890560989306504
>>> np.exp(y)
array([ 2.71828183, 7.3890561 , 20.08553692, 54.59815003])
numpy 就是 python 的數組運算包!
expand 函數有關鍵字參數 complex (帶有虛部的參數類型,本質就是複數,NumPy 裡講過),當它為 True 時,expand 將把公式分為實數和虛數兩個部分:
>>> expand(exp(I*x), complex=True)
I*exp(-im(x))*sin(re(x)) + cos(re(x))*exp(-im(x))
這次得到的結果相當複雜,其中 sin, cos, re,
im 都是 sympy 定義的類,re 表示取實數部分,im 表示取虛數部分。顯然這裡的運算將符號 x 當作複數了。為了指定符號 x 必須是實數,我們需要如下重新定義符號 x:
>>> x = Symbol("x", real=True)
>>> expand(exp(I*x), complex=True)
I*sin(x) + cos(x)
python 中單引號 '' 和雙引號 "" 用法:
它們其實並沒有明確的區別和特別用法,絕大部分情況是可以互相替換的。但是有一種情況需要注意:
>>> str = "Hello,world!"
>>> str1 = 'Hello,world!'
>>> str2 = "Let's go!"
>>> str3 = 'Let\'s go!' # \是轉意符號,告訴系統其後'的作用不是引號。
>>> str4 = "Say:\"Hello!\""
>>> str5 = 'Say:"Hello"'
>>> print str
Hello,world!
>>> print str1
Hello,world!
>>> print str2
Let's go!
>>> print str3
Let's go!
>>> print str4
Say:"Hello!"
>>> print str5
Say:"Hello"
下面不加轉意符號會出現報錯提示:
>>> str6 ='Let's go!'
File "<stdin>", line 1
str6 ='Let's go!'
^
SyntaxError: invalid syntax
2. 積分運算#
SymPy 的符號積分函數 integrate 可以幫助我們進行符號積分。integrate 可以進行不定積分:
>>> integrate(x*sin(x), x)
-x*cos(x) + sin(x)
如果指定 x 的取值範圍的話,integrate 則進行定積分運算:
>>> integrate(x*sin(x), (x, 0, 2*pi))
-2*pi
為了計算球體體積,首先讓我們來看看如何計算圓形面積,假設圓形的半徑為 r,則圓上任意一點的 Y 坐標函數為:
>>> x, y, r = symbols('x,y,r')
>>> 2 * integrate(sqrt(r*r-x**2), (x, -r, r))
2*Integral((r**2 - x**2)**(1/2), (x, -r, r))
很遺憾,integrate 函數沒有計算出結果,而是直接返回了我們輸入的算式。這是因為 SymPy 不知道 r 是大於 0 的,如下重新定義 r,就可以得到正確答案了:
>>> r = symbols('r', positive=True)
>>> circle_area = 2 * integrate(sqrt(r**2-x**2), (x, -r, r))
>>> circle_area
pi*r**2
接下來對此面積公式進行定積分,就可以得到球體的體積,但是隨著 X 軸坐標的變化,對應的切面的的半徑會發生變化,現在假設 X 軸的坐標為 x,球體的半徑為 r,則 x 處的切面的半徑為可以使用前面的公式 y (x) 計算出。
因此我們需要對 circle_area 中的變量 r 進行替代:
>>> circle_area = circle_area.subs(r, sqrt(r**2-x**2))
>>> circle_area
pi*(r**2 - x**2)
然後對 circle_area 中的變量 x 在區間 - r 到 r 上進行定積分,得到球體的體積公式:
>>> integrate(circle_area, (x, -r, r))
4*pi*r**3/3
用 subs 進行算式替換
subs 函數可以將算式中的符號進行替換,它有 3 種調用方式:
expression.subs (x, y) : 將算式中的 x 替換成 y
expression.subs({x,u}) : 使用字典進行多次替換
expression.subs ([(x,y),(u,v)]) : 使用列表進行多次替換
請注意多次替換是順序執行的,因此:
expression.sub([(x,y),(y,x)])
並不能對兩個符號 x,y 進行交換。
我這裡舉一些例子就明白了。
>>> from sympy import *
>>> a,b,c = symbols('a,b,c') #首字母小寫
>>> y = a + 10*b + 100*c
>>> y = y.subs(a,b)
>>> y
11*b + 100*c
>>> y = a + 10*b + 100*c
>>> y = y.subs([(a,b),(b,c)])
>>> y
111*c
>>> y = a + 10*b + 100*c
>>> y = y.subs([(a,b),(b,a)])
>>> y
11*a + 100*c
>>> x=Symbol('x') #注意這個首字母大寫
>>> y = a + 10*b + 100*c
>>> y = y.subs([(a,x),(b,a),(x,b)])
>>> y
10*a + b + 100*c
最後這個按順序用筆寫寫。
想看完整內容,請去原文地址: http://old.sebug.net/paper/books/scipydoc/sympy_intro.html