scipy.optimize.

newton#

scipy.optimize.newton(func, x0, fprime=None, args=(), tol=1.48e-08, maxiter=50, fprime2=None, x1=None, rtol=0.0, full_output=False, disp=True)[原始碼]#

使用牛頓-拉弗森(Newton-Raphson)(或正割或哈雷)法尋找實數或複數函數的根。

給定附近的純量起始點 x0,尋找純量值函數 func 的根。如果提供了 func 的導數 fprime,則使用牛頓-拉弗森法;否則使用正割法。如果也提供了 func 的二階導數 fprime2,則使用哈雷法。

如果 x0 是包含多個項目的序列,newton 會傳回一個陣列:來自 x0 中每個(純量)起始點的函數根。在這種情況下,func 必須向量化,以傳回與其第一個引數形狀相同的序列或陣列。如果給定了 fprime (fprime2),則其傳回值也必須具有相同的形狀:每個元素是 func 對其唯一變數在每個第一個引數元素處求值的一階(二階)導數。

newton 用於尋找單變數純量值函數的根。對於涉及多個變數的問題,請參閱 root

參數:
func可呼叫物件

想要尋找根的函數。它必須是單變數函數,形式為 f(x,a,b,c...),其中 a,b,c... 是可以在 args 參數中傳遞的額外引數。

x0浮點數、序列或 ndarray

根的初始估計值,應接近實際根。如果不是純量,則 func 必須向量化,並傳回與其第一個引數形狀相同的序列或陣列。

fprime可呼叫物件,選用

函數的導數(如果可用且方便)。如果為 None(預設值),則使用正割法。

args元組,選用

在函數呼叫中使用的額外引數。

tol浮點數,選用

根值允許的誤差。如果 func 是複數值,建議使用較大的 tol,因為 x 的實部和虛部都會影響 |x - x0|

maxiter整數,選用

最大迭代次數。

fprime2可呼叫物件,選用

函數的二階導數(如果可用且方便)。如果為 None(預設值),則使用常規牛頓-拉弗森法或正割法。如果不為 None,則使用哈雷法。

x1浮點數,選用

根的另一個估計值,應接近實際根。如果未提供 fprime,則使用此值。

rtol浮點數,選用

終止的容差(相對)。

full_output布林值,選用

如果 full_output 為 False(預設值),則傳回根。如果為 True 且 x0 為純量,則傳回值為 (x, r),其中 x 是根,rRootResults 物件。如果為 True 且 x0 為非純量,則傳回值為 (x, converged, zero_der)(請參閱「傳回值」章節以了解詳細資訊)。

disp布林值,選用

如果為 True,則當演算法未收斂時引發 RuntimeError,錯誤訊息包含迭代次數和目前函數值。否則,收斂狀態會記錄在 RootResults 傳回物件中。如果 x0 不是純量,則忽略此參數。注意:這與顯示無關,但是,`disp` 關鍵字為了向後相容性而無法重新命名。

傳回值:
root浮點數、序列或 ndarray

函數為零的估計位置。

rRootResults,選用

如果 full_output=Truex0 為純量,則存在。包含收斂資訊的物件。特別是,如果常式收斂,則 r.converged 為 True。

converged布林值 ndarray,選用

如果 full_output=Truex0 為非純量,則存在。對於向量函數,指示哪些元素成功收斂。

zero_der布林值 ndarray,選用

如果 full_output=Truex0 為非純量,則存在。對於向量函數,指示哪些元素的導數為零。

另請參閱

root_scalar

純量函數的尋根求解器介面

root

多輸入、多輸出函數的尋根求解器介面

註釋

牛頓-拉弗森法的收斂速度是二次的,哈雷法是三次的,而正割法是次二次的。這表示如果函數表現良好,則在第 n 次迭代後,估計根的實際誤差約為 (n-1) 步後誤差的平方(哈雷法為立方)。但是,此處使用的停止準則是步長大小,並且不保證已找到根。因此,應驗證結果。更安全的演算法是 brentq、brenth、ridder 和 bisect,但它們都要求首先將根括在函數變號的區間中。建議在已找到此類區間的一維問題中,一般使用 brentq 演算法。

newton 與陣列一起使用時,它最適合以下類型的問題

  • 初始猜測值 x0 與根的距離都相對相同。

  • 某些或所有額外引數 args 也是陣列,以便可以一起解決一類相似的問題。

  • 初始猜測值 x0 的大小大於 O(100) 個元素。否則,樸素迴圈的效能可能與向量化一樣好或更好。

範例

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from scipy import optimize
>>> def f(x):
...     return (x**3 - 1)  # only one real root at x = 1

fprime 未提供,使用正割法

>>> root = optimize.newton(f, 1.5)
>>> root
1.0000000000000016
>>> root = optimize.newton(f, 1.5, fprime2=lambda x: 6 * x)
>>> root
1.0000000000000016

僅提供 fprime,使用牛頓-拉弗森法

>>> root = optimize.newton(f, 1.5, fprime=lambda x: 3 * x**2)
>>> root
1.0

同時提供 fprime2fprime,使用哈雷法

>>> root = optimize.newton(f, 1.5, fprime=lambda x: 3 * x**2,
...                        fprime2=lambda x: 6 * x)
>>> root
1.0

當我們想要為一組相關的起始值和/或函數參數尋找根時,我們可以同時提供它們作為輸入陣列

>>> f = lambda x, a: x**3 - a
>>> fder = lambda x, a: 3 * x**2
>>> rng = np.random.default_rng()
>>> x = rng.standard_normal(100)
>>> a = np.arange(-50, 50)
>>> vec_res = optimize.newton(f, x, fprime=fder, args=(a, ), maxiter=200)

以上等效於在 for 迴圈中分別求解 (x, a) 中的每個值,只是速度更快

>>> loop_res = [optimize.newton(f, x0, fprime=fder, args=(a0,),
...                             maxiter=200)
...             for x0, a0 in zip(x, a)]
>>> np.allclose(vec_res, loop_res)
True

繪製為 a 的所有值找到的結果

>>> analytical_result = np.sign(a) * np.abs(a)**(1/3)
>>> fig, ax = plt.subplots()
>>> ax.plot(a, analytical_result, 'o')
>>> ax.plot(a, vec_res, '.')
>>> ax.set_xlabel('$a$')
>>> ax.set_ylabel('$x$ where $f(x, a)=0$')
>>> plt.show()
../../_images/scipy-optimize-newton-1.png