hans

hans

【Python】四、Sympy——《用Python進行科學計算》


SymPy 是 Python 的數學符號計算庫,用它可以進行數學公式的符號推導。為了調用方便,下面所有的實例程序都假設事先從 sympy 庫導入了所有內容:

>>> from sympy import *

* 表示所有的意思


1. 經典公式#

1668632086147.jpg
叫做歐拉恆等式,其中 e 是自然指數的底,i 是虛數單位,pi 是圓周率。此公式被譽為數學最奇妙的公式,它將 5 個基本數學常數用加法、乘法和幂運算聯繫起來。下面用 SymPy 驗證一下這個公式。

載入的符號中,E 表示自然指數的底,I 表示虛數單位,pi 表示圓周率,因此上述的公式可以直接如下計算:

>>> E**(I*pi)+1
0

歐拉恆等式可以下面的公式進行計算,
1668632127887.jpg
為了用 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) 計算出。
1668632183810.jpg
因此我們需要對 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

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。