python编程求极限_Sympy笔记一
from IPython.display import display
from sympy import *
前置知識
理解這份筆記的內容需,讀者需要具備基礎的python知識并且對函數,微積分和矩陣有一定的基礎。
輔助函數
由于后面的筆記中, 我們會大量將一個Sympy object和應用某個函數之后,調用某個方法之后, 或是和執行計算之后的結果比較。 為了減少代碼的重復,我編寫了helper.py幫忙做這事。
from helper import comparator_factory
func_comparator = comparator_factory('應用函數{}前:','使用后:')
comparator_factory返回的comparator是一個函數, 他否則使用的語法是comparator(target, func, *args, *kwargs)。 target是待處理的Sympy對象, func是希望應用的Sympy函數,args,kwargs是傳給func的額外位置參數和關鍵字參數。
from helper import comparator_method_factory
method_comparator = comparator_method_factory('Before calling {}:','After:')
comparator_method_factory返回的使用的語法是comparator(target, method_name, *args, *kwargs)。 target是待處理的Sympy對象, method_name是希望調用的方法的名字,args,kwargs是傳給調用方法的額外位置參數和關鍵字參數。
from helper import comparator_eval_factory
eval_comparator = comparator_eval_factory('計算前:','計算后')
comparator_eval_factory返回的comparator使用的語法是comparator(uneval)。 uneval是未執行計算的Sympy object。
符號計算是什么?
Sympy能以符號形式進行數學計算。數學表達式中未經計算的變量可以以符號的形式存在。我們看下面的例子。首先,我們用python的內置函數計算開方,我們可能會這么做。
from math import sqrt
sqrt(8)
2.8284271247461903
這個結果并不能精確的表達$\sqrt{8}$而且我們也很難從這一大串float數值推出原來的表達式是什么。這就是為什么我們需要符號計算。在像Sympy這樣的符號計算系統中,不能準確表達的開發運算會保留未經計算的符號形態。
from sympy import sqrt
sqrt(8)
2*sqrt(2)
更好的顯示效果
上面的例子中,結果很棒。但是在Jupyter中的顯示效果看起來并不怎么樣。如果我們要更好的顯示效果,可以調用sympy.init_printing()方法
from sympy import init_printing
init_printing()
sqrt(8)
$2 \sqrt{2}$
看上去棒極了!!
對變量進行符號計算
Sympy能夠對包含符號變量的表達式進行計算。下面是個例子。
from sympy import symbols
x, y = symbols('x y')
expr = x + 2*y
expr
$x + 2 y$
Sympy能自動應用一些明顯的化簡。 所以下面的例子里,我們得到的結果是$y$而不是$x+2y-x-y$
expr-x-y
$$y$$
如果沒有像Sympy這樣的符號計算系統的幫助,我們是實現不了這樣的效果的。因為大部分情況下,編程語言都沒法去處理一個沒有賦上具體值的變量。
Sympy的效果演示
為了滿足你的好奇心,下面挑了一小部分例子,演示Sympy在符號計算的威力。 先創建一寫符號變量。
x, t, z, nu = symbols('x t z nu')
求微分
計算$\sin{(x)}e^x$的微分
s = Derivative(sin(x)*exp(x),x)
eval_comparator(s)
計算前:
$$\fracze8trgl8bvbq{d x}\left(e^{x} \sin{\left (x \right )}\right)$$
計算后
$$e^{x} \sin{\left (x \right )} + e^{x} \cos{\left (x \right )}$$
求積分
計算$\int(e^x\sin{(x)} + e^x\cos{(x)})\,dx$
s = Integral(exp(x)*sin(x) + exp(x)*cos(x))
eval_comparator(s)
計算前:
$$\int e^{x} \sin{\left (x \right )} + e^{x} \cos{\left (x \right )}\, dx$$
計算后
$$e^{x} \sin{\left (x \right )}$$
計算$\int_{-\infty}^\infty \sin{(x^2)}\,dx$
s = Integral(sin(x**2),(x,-oo,oo))
eval_comparator(s)
計算前:
$$\int_{-\infty}^{\infty} \sin{\left (x^{2} \right )}\, dx$$
計算后
$$\frac{\sqrt{2} \sqrt{\pi}}{2}$$
計算$\lim_{x\to 0}\frac{\sin{(x)}}{x}$
求極限
s = Limit(sin(x)/x, x, 0)
eval_comparator(s)
計算前:
$$\lim_{x \to 0^+}\left(\frac{1}{x} \sin{\left (x \right )}\right)$$
計算后
$$1$$
求解 $x^2 - 2 = 0$
求解等式
s = Eq(x**2 - 2, 0)
func_comparator(s, solve, x)
應用函數solve()前:
$$x^{2} - 2 = 0$$
使用后:
$$\left [ - \sqrt{2}, \quad \sqrt{2}\right ]$$
求微分方程
計算微分方程$y'' - y = e^t$
y = Function('y')
s = Eq(y(t).diff(t, t) - y(t), exp(t))
func_comparator(s, dsolve, y(t))
應用函數dsolve()前:
$$- y{\left (t \right )} + \frac{d^{2}}{d t^{2}} y{\left (t \right )} = e^{t}$$
使用后:
$$y{\left (t \right )} = C_{2} e^{- t} + \left(C_{1} + \frac{t}{2}\right) e^{t}$$
矩陣計算
計算$\left[\begin{smallmatrix}1 & 2\2 & 2\end{smallmatrix}\right]$的engenvalue
Matrix([[1, 2], [2, 2]]).eigenvals()
$$\left { \frac{3}{2} + \frac{\sqrt{17}}{2} : 1, \quad - \frac{\sqrt{17}}{2} + \frac{3}{2} : 1\right }$$
用spherical Bessel function jν(z)改寫Bessel function Jν(z)
作圖
畫函數圖像
expr_1 = x**2
range_1 = (x,-2,2)
expr_2 = x
range_2 = (x,-1,1)
p = plot(
(expr_1,range_1),
(expr_2,range_2),
show = False,
legend = True
);
p[0].line_color = 'r'
p[1].line_color = 'b'
p[0].label = 'Line 1'
p[1].label = 'Line 2'
p.show()
畫3D平面
from sympy.plotting import plot3d
x,y = symbols('x y')
plot3d(
(x**2 + y**2, (x, -5, 5), (y, -5, 5)),
(x*y, (x, -3, 3), (y, -3, 3))
);
定義符號
定義變量符號
可以用symbols()去一次性定義多個符號變量。將想要的符號用空格隔開,以字符串的方式傳入函數。
from sympy import symbols
x,y,z = symbols('x y z')
expr = (x+y)**z/(x+1-y/5)
expr
$$\frac{\left(x + y\right)^{z}}{x - \frac{y}{5} + 1}$$
除了用字母,也可以用單詞作為符號名稱。
speed,time = symbols('speed time')
display(speed, time)
$$speed$$
$$time$$
有些字符串是保留字,用于定義諸如$\lambda, \nu$等特殊的符號。
lamda, n = symbols('lamda nu')
display(lamda, n)
$$\lambda$$
$$\nu$$
Python變量名不一定要和符號名保持一致。
y, x = symbols('x y')
display(x, y)
$$y$$
$$x$$
但是為了避免一些不必要的混亂,建議還是讓Python變量名和符號名保持一致比較好。
定義函數符號
傳入cls = Function定義函數符號。
f, g = symbols('f g', cls=Function)
display(f(x))
display(g(x,y))
$$f{\left (y \right )}$$
$$g{\left (y,x \right )}$$
定義數字
可以使用Integer, Float, Rational去定義Sympy中的整數,浮點數和有理數。
from sympy import Integer, Float, Rational
i = Integer(1)
i
$$1$$
f = Float(2.31)
f
$$2.31$$
r = Rational(2,7)
r
$$\frac{2}{7}$$
定義表達式
基本表達式
基本的數學表達式用符號變量和python的運算符就夠構造。
x,y,z = symbols('x y z')
expr = (x+y)**z/(x+1-y/5)
expr
$$\frac{\left(x + y\right)^{z}}{x - \frac{y}{5} + 1}$$
當Python的objects和Sympy的objects相遇的時候,Python objects會被自動轉化成Sympy objects.所以大部分使用我們直接使用python內置的數。
但是,遇到兩個python數值相除的時候,Python會先完成除法運算,將有理數轉變成浮點數。
expr = x+1/2
expr
$$x + 0.5$$
所以如果我們需要使用有理數,需要顯示的去進行定義。
expr = x+Rational(1,2)
expr
$$x + \frac{1}{2}$$
更復雜的表達式例如微積分需要借助Sympy的函數來實現。這部分內容會在后面的教程中介紹。
定義等式
可以用Eq來定義等式。
x,y = symbols('x,y')
eq = Eq(x**2-x,0)
print('等式n:')
display(eq)
等式n:
$$x^{2} - x = 0$$
處理表達式
多項/有理函數
simplify()
Sympy提供了多種函數用于表達式的化簡。simplify()是一個通用的函數,它嘗試“智能”的應用所有這些函數,讓表達式達到一個“最簡化”的狀態。
下面是一些例子。
expr = sin(x)**2 + cos(x)**2
func_comparator(expr, simplify)
應用函數simplify()前:
$$\sin^{2}{\left (x \right )} + \cos^{2}{\left (x \right )}$$
使用后:
$$1$$
expr = (x**3 + x**2 - x - 1)/(x**2 + 2*x + 1)
func_comparator(expr, simplify)
應用函數simplify()前:
$$\frac{x^{3} + x^{2} - x - 1}{x^{2} + 2 x + 1}$$
使用后:
$$x - 1$$
expr = gamma(x)/gamma(x - 2)
func_comparator(expr, simplify)
應用函數simplify()前:
$$\frac{\Gamma{\left(x \right)}}{\Gamma{\left(x - 2 \right)}}$$
使用后:
$$\left(x - 2\right) \left(x - 1\right)$$
由于很難定義什么是"最簡化",所以你可能得不到你想要的結果。
expr = x**2 + 2*x + 1
func_comparator(expr, simplify)
應用函數simplify()前:
$$x^{2} + 2 x + 1$$
使用后:
$$x^{2} + 2 x + 1$$
在上面的例子里。你可能覺得$(x+1)^2$是最簡化的結果但是simplify并不同意。 這種時候,我們就要使用更加具體的化簡函數去更好的控制結果。這些函數后面會介紹。
除此之外,由于simplify()需要把各種各樣的化簡都嘗試一下才能決定哪種方案最好,處理速度會慢。所以如果你已經知道自己想要哪種類型的化簡,直接使用特定的函數就好。
expand()
如果傳入一個多項式, expand()會把它處理成由單項式的和構成的標準型。
from sympy import expand
expr = (x + 1)**2
func_comparator(expr,expand)
應用函數expand()前:
$$\left(x + 1\right)^{2}$$
使用后:
$$x^{2} + 2 x + 1$$
expr = (x + 1)*(x - 2) - (x - 1)*x
func_comparator(expr,expand)
應用函數expand()前:
$$- x \left(x - 1\right) + \left(x - 2\right) \left(x + 1\right)$$
使用后:
$$-2$$
factor()
factor()將表達式在有理數范圍內分解成不可約的因子項。
from sympy import factor
expr = (x**2)*z + 4*x*y*z + 4*y**2*z
func_comparator(expr, factor)
應用函數factor()前:
$$x^{2} z + 4 x y z + 4 y^{2} z$$
使用后:
$$z \left(x + 2 y\right)^{2}$$
factor_list()
factor_list()做和factor()一樣的工作,但是返回的結果不可約因子項組成的list。
from sympy import factor_list
expr = x**2*z + 4*x*y*z + 4*y**2*z
func_comparator(expr, factor_list)
應用函數factor_list()前:
$$x^{2} z + 4 x y z + 4 y^{2} z$$
使用后:
$$\left ( 1, \quad \left [ \left ( z, \quad 1\right ), \quad \left ( x + 2 y, \quad 2\right )\right ]\right )$$
collect()
collect()對表達式進行同類項合并。
from sympy import collect
expr = x*y + x - 3 + 2*x**2 - z*x**2 + x**3
func_comparator(expr, collect, x)
應用函數collect()前:
$$x^{3} - x^{2} z + 2 x^{2} + x y + x - 3$$
使用后:
$$x^{3} + x^{2} \left(- z + 2\right) + x \left(y + 1\right) - 3$$
cancel()
cancel()接受有理函數,然后處理成$p/q$的標準型。做到$p$和$q$是展開的多項式,沒有未合并的同類項。
$p$和$q$的第一個系數不包含分母。
from sympy import cancel
expr = (x*y**2 - 2*x*y*z + x*z**2 + y**2 - 2*y*z + z**2)/(x**2 - 1)
func_comparator(expr, cancel)
應用函數cancel()前:
$$\frac{1}{x^{2} - 1} \left(x y^{2} - 2 x y z + x z^{2} + y^{2} - 2 y z + z^{2}\right)$$
使用后:
$$\frac{1}{x - 1} \left(y^{2} - 2 y z + z^{2}\right)$$
apart
apart()對有理函數進行部分分式分解。它將原表達式表示成若干多項式和若干分母較簡單的分式的和。
from sympy import apart
expr = (4*x**3 + 21*x**2 + 10*x + 12)/(x**4 + 5*x**3 + 5*x**2 + 4*x)
func_comparator(expr, apart)
應用函數apart()前:
$$\frac{4 x^{3} + 21 x^{2} + 10 x + 12}{x^{4} + 5 x^{3} + 5 x^{2} + 4 x}$$
使用后:
$$\frac{2 x - 1}{x^{2} + x + 1} - \frac{1}{x + 4} + \frac{3}{x}$$
三角函數
trigsimp
要根據三角恒等式對三角函數進行化簡的話,可以用trigsimp()。和simplify()很像,trigsimp()嘗試使用各種三角恒等式去處理接受的表達式,然后根據“直覺”找到最好的選擇。
from sympy import trigsimp
expr = sin(x)**4 - 2*cos(x)**2*sin(x)**2 + cos(x)**4
func_comparator(expr, trigsimp)
應用函數trigsimp()前:
$$\sin^{4}{\left (x \right )} - 2 \sin^{2}{\left (x \right )} \cos^{2}{\left (x \right )} + \cos^{4}{\left (x \right )}$$
使用后:
$$\frac{1}{2} \cos{\left (4 x \right )} + \frac{1}{2}$$
trigsimp()也能用在雙曲函數上。
expr = cosh(x)**2 + sinh(x)**2
func_comparator(expr, trigsimp)
應用函數trigsimp()前:
$$\sinh^{2}{\left (x \right )} + \cosh^{2}{\left (x \right )}$$
使用后:
$$\cosh{\left (2 x \right )}$$
expand_trig
如果想展開三角函數,例如,想利用和角公式和倍角公式的話,可以用expand_trig()。
from sympy import expand_trig
expr = sin(x + y)
func_comparator(expr,expand_trig)
應用函數expand_trig()前:
$$\sin{\left (x + y \right )}$$
使用后:
$$\sin{\left (x \right )} \cos{\left (y \right )} + \sin{\left (y \right )} \cos{\left (x \right )}$$
冪函數
假設
介紹針對指數函數的化簡函數之前,得先討論一下和指數有關的幾個等式。
我們有三個等式。$x^ax^b = x^{a + b}$
$x^ay^a = (xy)^a$
$(x^a)^b = x^{ab}$
等式1總是成立。
等式2不總是成立。我們可以舉一個針對等式2的反例。
如果$x=y=?1$ and $a=1/2$, 那么$x^ay^a = \sqrt{-1}\sqrt{-1} = i\cdot i = -1$, 可是$x^ay^a = \sqrt{-1}\sqrt{-1} = i\cdot i = -1$.
等式3也不是一直成立。例如, 如果$x=?1$, $a=2$, and $b=1/2$, 那么$(x^a)^b = {\left ((-1)^2\right )}^{1/2} = \sqrt{1} = 1$且有$x^{ab} = (-1)^{2\cdot1/2} = (-1)^1 = -1$
記得這些很重要,因為默認情況下,Sympy并不會利用并不總是成立的等式用于化簡操作。
但是我們可以添加額外的假設條件,讓等式2和等式3在這些假設條件下做到衡成立。
一套讓等式2滿足的條件是,$x, y \geq 0$ and $a \in \mathbb{R};一套讓等式3滿足的條件是$b \in \mathbb{Z}$
為了讓Sympy利用這些只有在特定假設下才成立的等式進行化簡,我們需要給符號添加假設(默認假設是它們都是復數)。
我們后面會對假設系統進行更細致的探討。下面先舉一個簡單的用法的例子。這個例子里,我們假設$x,y$值為正且$a,b$是實數。
x, y = symbols('x y', positive=True)
a, b = symbols('a b', real=True)
另一個強制進行化簡,無視假設的方法是傳入force = True。這個用法我們后面會遇到。
powsimp
powsimp()會從左到右應用等式1和2.
from sympy import powsimp
expr = x**a*x**b
func_comparator(expr, powsimp)
應用函數powsimp()前:
$$x^{a} x^{b}$$
使用后:
$$x^{a + b}$$
from sympy import powsimp
expr = x**a*y**a
func_comparator(expr, powsimp)
應用函數powsimp()前:
$$x^{a} y^{a}$$
使用后:
$$\left(x y\right)^{a}$$
如果沒有相應的假設讓等式2成立,化簡不會發生。
x, y = symbols('x y')
a, b = symbols('a b')
from sympy import powsimp
expr = x**a*y**a
func_comparator(expr, powsimp)
應用函數powsimp()前:
$$x^{a} y^{a}$$
使用后:
$$x^{a} y^{a}$$
如果你確信希望應用化簡,無論假設條件如何,可以傳入force=True
x, y = symbols('x y')
a, b = symbols('a b')
from sympy import powsimp
expr = x**a*y**a
func_comparator(expr, powsimp,force=True)
應用函數powsimp()前:
$$x^{a} y^{a}$$
使用后:
$$\left(x y\right)^{a}$$
expand_power_exp
expand_power_exp()從右往左應用等式1。
from sympy import expand_power_exp
expr = x**(a + b)
func_comparator(expr, expand_power_exp)
應用函數expand_power_exp()前:
$$x^{a + b}$$
使用后:
$$x^{a} x^{b}$$
expand_power_base
expand_power_base()從左到右應用等式2.
from sympy import expand_power_base
expr = (x*y)**a
func_comparator(expr, expand_power_base)
應用函數expand_power_base()前:
$$\left(x y\right)^{a}$$
使用后:
$$\left(x y\right)^{a}$$
powdenest
powdenest()從左往右應用等式3。
from sympy import powdenest
expr = (x**a)**b
func_comparator(expr, powdenest,force=True)
應用函數powdenest()前:
$$\left(x^{a}\right)^{b}$$
使用后:
$$x^{a b}$$
指數函數和對數函數
對數函數有個主要的等式。$\log{(xy)} = \log{(x)} + \log{(y)}$
$\log{(x^n)} = n\log{(x)}$
它們有和冪函數一樣的問題。為了讓化簡時能利用上這些等式,我們需要傳入force = True或者添加額外的假設。
一套充分條件是
x, y = symbols('x y', positive=True)
n = symbols('n', real=True)
expand_log
expand_log()從左往右應用等式1和2
from sympy import expand_log
expr = log(x*y)
func_comparator(expr,expand_log)
應用函數expand_log()前:
$$\log{\left (x y \right )}$$
使用后:
$$\log{\left (x \right )} + \log{\left (y \right )}$$
from sympy import expand_log
expr = log(x**n)
func_comparator(expr,expand_log)
應用函數expand_log()前:
$$\log{\left (x^{n} \right )}$$
使用后:
$$n \log{\left (x \right )}$$
from sympy import expand_log
expr = log(x/y)
func_comparator(expr,expand_log)
應用函數expand_log()前:
$$\log{\left (\frac{x}{y} \right )}$$
使用后:
$$\log{\left (x \right )} - \log{\left (y \right )}$$
logcombine
expand_log()從右往左應用等式1和2
from sympy import logcombine
expr = log(x) + log(y)
func_comparator(expr, logcombine)
應用函數logcombine()前:
$$\log{\left (x \right )} + \log{\left (y \right )}$$
使用后:
$$\log{\left (x y \right )}$$
from sympy import logcombine
expr = n*log(x)
func_comparator(expr, logcombine)
應用函數logcombine()前:
$$n \log{\left (x \right )}$$
使用后:
$$\log{\left (x^{n} \right )}$$
組合函數
combsimp
要化簡組合函數的話,可以用combsimp()
from sympy import combsimp
expr = factorial(n)/factorial(n - 3)
func_comparator(expr, combsimp)
應用函數combsimp()前:
$$\frac{n!}{\left(n - 3\right)!}$$
使用后:
$$n \left(n - 2\right) \left(n - 1\right)$$
from sympy import combsimp, binomial
n,k = symbols('n k')
expr = binomial(n+1, k+1)/binomial(n, k)
func_comparator(expr, combsimp)
應用函數combsimp()前:
$$\frac{1}{{\binom{n}{k}}} {\binom{n + 1}{k + 1}}$$
使用后:
$$\frac{n + 1}{k + 1}$$
參考資料
相關文章
總結
以上是生活随笔為你收集整理的python编程求极限_Sympy笔记一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 5.7 flashback_
- 下一篇: php去掉编辑器自带样式,phpcms去