日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

解非线性方程的两种方法与python实现

發(fā)布時(shí)間:2024/3/26 python 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 解非线性方程的两种方法与python实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

寫(xiě)在開(kāi)頭: 非線性方程,就是因變量與自變量之間的關(guān)系不是線性的關(guān)系,這類(lèi)方程很多,例如平方關(guān)系、對(duì)數(shù)關(guān)系、指數(shù)關(guān)系、三角函數(shù)關(guān)系等等。求解此類(lèi)方程往往很難得到精確解,經(jīng)常需要求近似解問(wèn)題。本文將從一道數(shù)列題開(kāi)始,引出一種求解非線性方程的基礎(chǔ)方法:簡(jiǎn)單迭代法。然后講解科學(xué)計(jì)算器的求解方法:牛頓切線法。最后會(huì)用python實(shí)現(xiàn)兩種方法并可視化。


不動(dòng)點(diǎn)迭代法

引子

先來(lái)看一道簡(jiǎn)單的數(shù)列題。

已知數(shù)列an的遞推公式an+1=1an+1,且a1=1,求lim?x→∞an已知數(shù)列a_{n}的遞推公式a_{n+1}=\frac{1}{a_{n}+1} ,且a_{1}=1,求\lim_{x \to \infty}a_{n} 已知數(shù)列an?的遞推公式an+1?=an?+11?,a1?=1,xlim?an?

解此題只需令lim?x→∞an=A,解方程A=1A+1\lim_{x \to \infty}a_{n} =A,解方程A=\frac{1}{A+1}limx?an?=A,解方程A=A+11?即可。但借助科學(xué)計(jì)算器還有一種投機(jī)取巧的方法:利用遞推公式不斷求ana_{n}an?。當(dāng)n足夠大時(shí),an(如a100)a_{n}(如a_{100})an?(a100?)即可近似為ana_{n}an?的極限。而這一過(guò)程借助科學(xué)計(jì)算器的“Ans”功能可以很方便地實(shí)現(xiàn)。

可以發(fā)現(xiàn):我們用這種方法繞開(kāi)了二次方程的求根公式解出了方程x=1x+1x=\frac{1}{x+1}x=x+11?的一個(gè)實(shí)數(shù)數(shù)值解。那么對(duì)于任意形如x=g(x)x=g(x)x=g(x)的方程,是不是也可以用構(gòu)造數(shù)列an+1=g(an)a_{n+1}=g(a_{n})an+1?=g(an?)來(lái)求解呢?這就是不動(dòng)點(diǎn)迭代法了。

具體操作

不動(dòng)點(diǎn)迭代又稱(chēng)為簡(jiǎn)單迭代,用以求解方程f(x)=0f(x)=0f(x)=0。方法如下:

  • 方程轉(zhuǎn)換為x=g(x)x=g(x)x=g(x)
  • x0x_{0}x0?設(shè)定一個(gè)初值
  • xi+1=g(xi)x_{i+1}=g(x_{i})xi+1?=g(xi?)
  • 若滿(mǎn)足結(jié)束條件(i大于某個(gè)預(yù)設(shè)的值,或∣xi+1?xi∣|x_{i+1}-x_{i}|xi+1??xi?小于某個(gè)預(yù)設(shè)的值)xi+1x_{i+1}xi+1?為解,否則返回第3步
  • 這里將方程f(x)=0f(x)=0f(x)=0轉(zhuǎn)換為x=g(x)x=g(x)x=g(x)是很容易的,比如對(duì)于f(x)=x?cos(x)f(x)=x-cos(x)f(x)=x?cos(x),求解f(x)=0f(x)=0f(x)=0即為求解x?cos(x)=0x-cos(x)=0x?cos(x)=0,即x=cos(x)x=cos(x)x=cos(x),因此g(x)=cos(x)g(x)=cos(x)g(x)=cos(x);但是需要注意轉(zhuǎn)換方法不唯一,這可能會(huì)影響計(jì)算結(jié)果。

    缺點(diǎn)

    • 只能求一個(gè)解
    • 函數(shù)φ(x)在區(qū)間[a,b]內(nèi)\varphi(x)在區(qū)間[a,b]內(nèi)φ(x)在區(qū)間[a,b]內(nèi)必須滿(mǎn)足以下的收斂條件:
      1. 有一階導(dǎo)數(shù)
      2. 對(duì)任意x∈[a,b]x\in[a,b]x[a,b],總存有φ(x)∈[a,b]\varphi(x)\in[a,b]φ(x)[a,b]
      3. 對(duì)任意x∈[a,b]x\in[a,b]x[a,b],總存有0<L<1,使得∣φ(x)′∣≤L<1|{\varphi(x)}'|\le L<1φ(x)L<1
    • 為滿(mǎn)足收斂條件,需要選取適當(dāng)初始值

    牛頓切線法

    鑒于不動(dòng)點(diǎn)迭代法有時(shí)無(wú)法滿(mǎn)足的收斂條件,科學(xué)計(jì)算器在求解非線性方程時(shí)會(huì)運(yùn)用另一種方法–牛頓切線法,又稱(chēng)牛頓法。
    牛頓切線法也是一種迭代法。它的操作很簡(jiǎn)單,首先通過(guò)移項(xiàng)把方程轉(zhuǎn)化成求函數(shù)f(x)f(x)f(x)的零點(diǎn)的問(wèn)題。在給定一個(gè)迭代點(diǎn)xix_{i}xi?時(shí),作f(x)f(x)f(x)xix_{i}xi?的切線y?f(xi)=f′(xi)(x?xi)y-f(x_{i})=f'(x_{i})(x-x_{i})y?f(xi?)=f(xi?)(x?xi?)xi+1x_{i+1}xi+1?為切線與x軸的交點(diǎn)xi?f(xi)f′(xi)x_{i}-\frac{f(x_{i})}{f'(x_{i})}xi??f(xi?)f(xi?)?。與不動(dòng)點(diǎn)迭代法一樣,在滿(mǎn)足結(jié)束條件時(shí)終止迭代。

    如何理解這種操作呢?可以把f(x)f(x)f(x)的切線看作f(x)f(x)f(x)xix_{i}xi?的一階泰勒近似,既然函數(shù)的切線與函數(shù)是相似的,他們的零點(diǎn)也是相近的。那就把切線的零點(diǎn)當(dāng)做目標(biāo)值的近似。

    接下來(lái)是一個(gè)例子,所求方程為0.1x2?x?3=0,x0=10.1x^2-x-3=0,x_{0}=10.1x2?x?3=0,x0?=1,共迭代了兩次。

    可以看到,迭代兩次后的x2x_{2}x2?已經(jīng)相當(dāng)接近xtargetx_{target}xtarget?了。

    一般我們希望x盡可能接近理論值xtargetx_{target}xtarget?,但是有時(shí)確切的理論值是未知的,所以也可以令∣y∣|y|y盡可能小。現(xiàn)在我們知道了在使用卡西歐計(jì)算器時(shí),可以使用L-R的功能來(lái)估算∣y∣|y|y(即誤差)。而輸入x的功能是為了設(shè)置迭代的初始點(diǎn)。

    除了求解方程,牛頓法還有更廣泛的應(yīng)用。在已知某函數(shù)的導(dǎo)數(shù)時(shí),可以令導(dǎo)數(shù)為零,解方程得函數(shù)的極值。將一元函數(shù)推廣到多元函數(shù),用向量,梯度,Heese矩陣替換自變量,導(dǎo)數(shù),二階導(dǎo)數(shù),就可以把牛頓法用于多維無(wú)約束最優(yōu)化問(wèn)題。


    python實(shí)現(xiàn)

    調(diào)用了numpy庫(kù)與matplotlib庫(kù)。使用同一個(gè)函數(shù)接口solve實(shí)現(xiàn)牛頓法與不動(dòng)點(diǎn)迭代法,作為示例的方程為arctan(x?7)?0.3x=0arctan(x-7)-0.3x=0arctan(x?7)?0.3x=0。在以迭代次數(shù)作為結(jié)束條件的基礎(chǔ)上,這里增加了一種終止迭代的條件:兩次x的差值∣xi+1?xi∣|x_{i+1}-x_{i}|xi+1??xi?小于某個(gè)預(yù)設(shè)的值deltadeltadelta

    由于牛頓法涉及導(dǎo)數(shù)運(yùn)算,我們用數(shù)值微分公式f′(x)≈f(x+h)?f(x?h)2hf'(x)≈\frac{f(x+h)-f(x-h)}{2h}f(x)2hf(x+h)?f(x?h)?近似導(dǎo)數(shù),由二階泰勒展開(kāi)公式可推得其誤差為O(h2)O(h^2)O(h2)

    主要函數(shù)與大致流程:

    • 輸入:在func函數(shù)中輸入需要為零的函數(shù),即方程f(x)=0f(x)=0f(x)=0中的f(x)f(x)f(x),在solve函數(shù)中輸入初始迭代點(diǎn)x0x_{0}x0?,迭代次數(shù)上限iteration(默認(rèn)100),終止迭代的誤差delta(默認(rèn)1e-5)。
    • 輸出:牛頓法與不動(dòng)點(diǎn)迭代法各自的解,和兩張圖ax[0],ax[1]
    • 函數(shù)func():表示f(x)f(x)f(x)
    • 函數(shù)derivate():對(duì)func使用數(shù)值微分求導(dǎo)
    • 函數(shù)solve():繪制ax[0]的一組迭代點(diǎn)與ax[1]的一條折線
    • 子圖ax[0]:函數(shù)圖像與迭代點(diǎn)
    • 子圖ax[1]:f(x)f(x)f(x)隨迭代次數(shù)變化的曲線,若能有效求解,曲線將收斂與0
    import numpy as np import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來(lái)正常顯示中文標(biāo)簽 plt.rcParams['axes.unicode_minus'] = False # 用來(lái)正常顯示負(fù)號(hào)def func(x):#需要為0的函數(shù)y=np.arctan(x-7)-0.3*x#自定義要求解的函數(shù)return y def derivate(x):#數(shù)值微分求導(dǎo),h取1e-6return (func(x+1e-6)-func(x-1e-6))/2e-6 def solve(x,iteration=100,delta=1e-5,method='fixed_point'):#繪制迭代點(diǎn)和下降曲線doty=[func(x)]#保存迭代點(diǎn)的縱坐標(biāo),用來(lái)繪制折線圖,先記錄初始點(diǎn)n=1#記錄迭代次數(shù)for i in range(iteration):if(method=='fixed_point'):#不動(dòng)點(diǎn)迭代xnext=func(x)+xcolors="blue"if(method=='newton'):#牛頓迭代xnext=x-func(x)/derivate(x)colors="orange"ax[0].scatter(xnext,func(xnext),marker='o',s=10,color=colors,alpha=1,zorder=3)doty.append(func(xnext))#添加迭代點(diǎn)的縱坐標(biāo)n=n+1if(abs(x-xnext)<delta):#新增的終止條件breakx=xnextax[1].plot(np.arange(0,n),doty,'o-',markersize=3)#繪制函數(shù)值下降曲線return x;#畫(huà)布的基礎(chǔ)設(shè)置 X=np.linspace(-15,20,500) # X軸坐標(biāo)數(shù)據(jù) Y =func(X) # Y軸坐標(biāo)數(shù)據(jù) fig, ax = plt.subplots(1, 2, figsize=(10, 4),dpi=120)#創(chuàng)建畫(huà)布 ax[0].tick_params(labelsize=12)#坐標(biāo)字號(hào) ax[1].tick_params(labelsize=12) ax[0].set_xlabel('$x$')#坐標(biāo)名稱(chēng) ax[0].set_ylabel('$y$') ax[1].set_xlabel('迭代次數(shù)') ax[1].set_ylabel('函數(shù)值') ax[0].grid()#增加網(wǎng)格 ax[1].grid()ax[0].plot(X,0*X,color="black",linewidth=1,zorder=1)#作圖y=0 ax[0].plot(X,Y,label="$f(x)$",color="black",linewidth=1,zorder=2)#作出函數(shù)圖像#繪制兩種方法的迭代點(diǎn)與函數(shù)下降曲線 ax[0].scatter(8,func(8),color="red",s=10,label="初始點(diǎn)")#繪制初始點(diǎn) ans1=solve(8,100,method='fixed_point') ans2=solve(8,100,method='newton') ax[0].legend(fontsize=8)#設(shè)置圖例 ax[1].legend(['不動(dòng)點(diǎn)迭代法','牛頓法'],fontsize=8)print('不動(dòng)點(diǎn)迭代法的結(jié)果:'+str(ans1)) print('牛頓法的結(jié)果:'+str(ans2))plt.show()

    結(jié)果如下

    總結(jié)

    以上是生活随笔為你收集整理的解非线性方程的两种方法与python实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。