scipy.optimize.

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, 可选

求解器选项的字典。例如,xtolmaxiter,有关详细信息,请参阅 show_options()

返回值::
solOptimizeResult

表示为 OptimizeResult 对象的解。重要的属性有:x 解数组、success 指示算法是否成功退出的布尔标志以及 message 描述终止原因。有关其他属性的描述,请参阅 OptimizeResult

另请参阅

show_options

求解器接受的其他选项

备注

本节描述了可以通过 ‘method’ 参数选择的可用求解器。默认方法是 hybr

方法 hybr 使用 MINPACK 中实现的 Powell 混合方法的修改 [1]

方法 lm 使用 MINPACK 中实现的 Levenberg-Marquardt 算法的修改,以最小二乘意义求解非线性方程组 [1]

方法 df-sane 是一种无导数谱方法。 [3]

方法 broyden1broyden2andersonlinearmixingdiagbroydenexcitingmixingkrylov 是不精确牛顿方法,具有回溯或全线搜索 [2]。每种方法对应于特定的雅可比矩阵近似值。

  • 方法 broyden1 使用 Broyden 的第一个雅可比矩阵近似值,称为 Broyden 的好方法。

  • 方法 broyden2 使用 Broyden 的第二个雅可比矩阵近似值,称为 Broyden 的坏方法。

  • 方法 anderson 使用(扩展的)Anderson 混合。

  • 方法 Krylov 使用 Krylov 近似来求解逆雅可比矩阵。它适用于大规模问题。

  • 方法 diagbroyden 使用对角 Broyden 雅可比矩阵近似值。

  • 方法 linearmixing 使用标量雅可比矩阵近似值。

  • 方法 excitingmixing 使用经过调优的对角雅可比矩阵近似值。

警告

diagbroydenlinearmixingexcitingmixing 方法实现的算法可能对特定问题有用,但它们是否有效可能很大程度上取决于问题。

在版本 0.11.0 中添加。

参考文献

[1] (1,2)

More, Jorge J., Burton S. Garbow 和 Kenneth E. Hillstrom。1980。MINPACK-1 用户指南。

[2]

C. T. Kelley。1995。线性与非线性方程的迭代方法。工业与应用数学学会。 <https://archive.siam.org/books/kelley/fr16/>

[3]
  1. 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()
../../_images/scipy-optimize-root-1.png