root#
- scipy.optimize.root(fun, x0, args=(), method='hybr', jac=None, tol=None, callback=None, options=None)[source]#
查找向量函数的根。
- 参数::
- funcallable
要查找根的向量函数。
- x0ndarray
初始猜测。
- argstuple, 可选
传递给目标函数及其雅可比矩阵的额外参数。
- methodstr, 可选
求解器类型。应该是以下之一:
- jacbool 或 callable, 可选
如果 jac 是布尔值且为 True,则假设 fun 返回雅可比矩阵的值以及目标函数。如果为 False,则雅可比矩阵将使用数值方法进行估计。jac 也可以是返回 fun 雅可比矩阵的可调用函数。在这种情况下,它必须接受与 fun 相同的参数。
- tolfloat, 可选
终止容差。要进行详细控制,请使用特定于求解器的选项。
- callbackfunction, 可选
可选回调函数。它在每次迭代时都会被调用,例如
callback(x, f)
,其中 x 是当前解,f 是相应的残差。对于除 ‘hybr’ 和 ‘lm’ 之外的所有方法。- optionsdict, 可选
求解器选项的字典。例如,xtol 或 maxiter,有关详细信息,请参阅
show_options()
。
- 返回值::
- solOptimizeResult
表示为
OptimizeResult
对象的解。重要的属性有:x
解数组、success
指示算法是否成功退出的布尔标志以及message
描述终止原因。有关其他属性的描述,请参阅OptimizeResult
。
另请参阅
show_options
求解器接受的其他选项
备注
本节描述了可以通过 ‘method’ 参数选择的可用求解器。默认方法是 hybr。
方法 hybr 使用 MINPACK 中实现的 Powell 混合方法的修改 [1]。
方法 lm 使用 MINPACK 中实现的 Levenberg-Marquardt 算法的修改,以最小二乘意义求解非线性方程组 [1]。
方法 df-sane 是一种无导数谱方法。 [3]
方法 broyden1、broyden2、anderson、linearmixing、diagbroyden、excitingmixing、krylov 是不精确牛顿方法,具有回溯或全线搜索 [2]。每种方法对应于特定的雅可比矩阵近似值。
方法 broyden1 使用 Broyden 的第一个雅可比矩阵近似值,称为 Broyden 的好方法。
方法 broyden2 使用 Broyden 的第二个雅可比矩阵近似值,称为 Broyden 的坏方法。
方法 anderson 使用(扩展的)Anderson 混合。
方法 Krylov 使用 Krylov 近似来求解逆雅可比矩阵。它适用于大规模问题。
方法 diagbroyden 使用对角 Broyden 雅可比矩阵近似值。
方法 linearmixing 使用标量雅可比矩阵近似值。
方法 excitingmixing 使用经过调优的对角雅可比矩阵近似值。
警告
为 diagbroyden、linearmixing 和 excitingmixing 方法实现的算法可能对特定问题有用,但它们是否有效可能很大程度上取决于问题。
在版本 0.11.0 中添加。
参考文献
[2]C. T. Kelley。1995。线性与非线性方程的迭代方法。工业与应用数学学会。 <https://archive.siam.org/books/kelley/fr16/>
[3]La Cruz, J.M. Martinez, M. Raydan。数学计算。75, 1429 (2006)。
示例
以下函数定义了非线性方程组及其雅可比矩阵。
>>> import numpy as np >>> def fun(x): ... return [x[0] + 0.5 * (x[0] - x[1])**3 - 1.0, ... 0.5 * (x[1] - x[0])**3 + x[1]]
>>> def jac(x): ... return np.array([[1 + 1.5 * (x[0] - x[1])**2, ... -1.5 * (x[0] - x[1])**2], ... [-1.5 * (x[1] - x[0])**2, ... 1 + 1.5 * (x[1] - x[0])**2]])
可以通过以下方式获得解。
>>> from scipy import optimize >>> sol = optimize.root(fun, [0, 0], jac=jac, method='hybr') >>> sol.x array([ 0.8411639, 0.1588361])
大型问题
假设我们需要在正方形 \([0,1]\times[0,1]\) 上求解以下积分微分方程
\[\nabla^2 P = 10 \left(\int_0^1\int_0^1\cosh(P)\,dx\,dy\right)^2\]其中 \(P(x,1) = 1\) 并且 \(P=0\) 在正方形边界上的其他位置。
可以使用
method='krylov'
求解器找到解>>> from scipy import optimize >>> # parameters >>> nx, ny = 75, 75 >>> hx, hy = 1./(nx-1), 1./(ny-1)
>>> P_left, P_right = 0, 0 >>> P_top, P_bottom = 1, 0
>>> def residual(P): ... d2x = np.zeros_like(P) ... d2y = np.zeros_like(P) ... ... d2x[1:-1] = (P[2:] - 2*P[1:-1] + P[:-2]) / hx/hx ... d2x[0] = (P[1] - 2*P[0] + P_left)/hx/hx ... d2x[-1] = (P_right - 2*P[-1] + P[-2])/hx/hx ... ... d2y[:,1:-1] = (P[:,2:] - 2*P[:,1:-1] + P[:,:-2])/hy/hy ... d2y[:,0] = (P[:,1] - 2*P[:,0] + P_bottom)/hy/hy ... d2y[:,-1] = (P_top - 2*P[:,-1] + P[:,-2])/hy/hy ... ... return d2x + d2y - 10*np.cosh(P).mean()**2
>>> guess = np.zeros((nx, ny), float) >>> sol = optimize.root(residual, guess, method='krylov') >>> print('Residual: %g' % abs(residual(sol.x)).max()) Residual: 5.7972e-06 # may vary
>>> import matplotlib.pyplot as plt >>> x, y = np.mgrid[0:1:(nx*1j), 0:1:(ny*1j)] >>> plt.pcolormesh(x, y, sol.x, shading='gouraud') >>> plt.colorbar() >>> plt.show()