find_root#
- scipy.optimize.elementwise.find_root(f, init, /, *, args=(), tolerances=None, maxiter=None, callback=None)[source]#
查找实变量单调实值函数的根。
对于 f 输出的每个元素,
find_root
寻找使该元素为 0 的标量根。此函数当前使用 Chandrupatla 的区间算法 [1],因此要求参数 init 提供一个包含根的区间:两个端点处的函数值必须具有相反的符号。如果提供了一个有效区间,并且函数在该区间内是连续的,则
find_root
保证收敛到满足所提供 tolerances 的解。当 init 和 args 包含(可广播的)数组时,此函数按元素工作。
- 参数:
- f可调用对象
需要求根的函数。签名必须是
f(x: array, *args) -> array
其中
x
的每个元素都是一个有限实数,args
是一个元组,可能包含任意数量的与x
可广播的数组。f 必须是逐元素函数:对于所有索引
i
,f(x)[i]
必须等于f(x[i])
。它不得修改数组x
或args
中的数组。find_root
寻找一个数组x
,使得f(x)
是一个零数组。- init2-元组,浮点数组类
包围所需根的区间的下限和上限。如果数组
xl, xr = init
逐元素满足xl < xr
和sign(f(xl)) == -sign(f(xr))
,则该区间有效。数组必须可相互广播并与 args 广播。- args数组类元组,可选
要传递给 f 的附加位置数组参数。数组必须可相互广播并与 init 的数组广播。如果需要求根的可调用对象需要与 x 不可广播的参数,则将该可调用对象用 f 包装,使得 f 只接受 x 和可广播的
*args
。- tolerances浮点数字典,可选
根和函数值的绝对和相对容差。字典的有效键是
xatol
- 根的绝对容差xrtol
- 根的相对容差fatol
- 函数值的绝对容差frtol
- 函数值的相对容差
有关默认值和明确终止条件,请参阅注释。
- maxiter整型,可选
要执行的算法的最大迭代次数。默认值是相关 dtype 的(正常)浮点数内可能的最大二分法次数。
- callback可调用对象,可选
一个可选的用户提供函数,在第一次迭代之前和每次迭代之后调用。以
callback(res)
的形式调用,其中res
是一个_RichResult
,类似于find_root
返回的对象(但包含当前迭代的所有变量值)。如果 callback 引发StopIteration
,算法将立即终止,并且find_root
将返回结果。callback 不得修改 res 或其属性。
- 返回:
- res_RichResult
一个类似于
scipy.optimize.OptimizeResult
实例的对象,具有以下属性。描述假定值为标量;但是,如果 f 返回一个数组,则输出将是相同形状的数组。- success布尔数组
算法成功终止(状态
0
)的位置为True
;否则为False
。- status整型数组
表示算法退出状态的整数。
0
:算法收敛到指定的容差。-1
:初始区间无效。-2
:达到最大迭代次数。-3
:遇到非有限值。-4
:迭代被 callback 终止。1
:算法正常进行中(仅在 callback 中)。
- x浮点数组
如果算法成功终止,则为函数的根。
- f_x浮点数组
在 x 处求得的 f 的值。
- nfev整型数组
为找到根而对 f 求值时的横坐标数量。这与 f 的调用次数不同,因为函数可以在一次调用中在多个点处求值。
- nit整型数组
执行的算法迭代次数。
- bracket浮点数组元组
最终区间的下限和上限。
- f_bracket浮点数组元组
在区间的下限和上限处求得的 f 的值。
另请参阅
注释
根据 Chandrupatla 的原始论文 [1] 实现。
令
a, b = init
为初始区间的左端点和右端点,xl
和xr
为最终区间的左端点和右端点,xmin = xl if abs(f(xl)) <= abs(f(xr)) else xr
为函数值较小的最终区间端点,以及fmin0 = min(f(a), f(b))
为在初始区间端点处求得的函数值的最小值。
当满足以下条件时,算法被认为已收敛:
abs(xr - xl) < xatol + abs(xmin) * xrtol
或fun(xmin) <= fatol + abs(fmin0) * frtol
.
这等效于 [1] 中描述的终止条件,其中
xrtol = 4e-10
,xatol = 1e-5
, 且fatol = frtol = 0
。然而,tolerances 字典的默认值是xatol = 4*tiny
,xrtol = 4*eps
,frtol = 0
, 和fatol = tiny
,其中eps
和tiny
分别是函数输入和输出结果dtype
的精度和最小正规数。参考文献
[1] (1,2,3)Chandrupatla, Tirupathi R. “A new hybrid quadratic/bisection algorithm for finding the zero of a nonlinear function without using derivatives”. Advances in Engineering Software, 28(3), 145-149. https://doi.org/10.1016/s0965-9978(96)00051-8
示例
假设我们希望找到以下函数的根。
>>> def f(x, c=5): ... return x**3 - 2*x - c
首先,我们必须找到一个有效区间。该函数不是单调的,但
bracket_root
可能能够提供一个区间。>>> from scipy.optimize import elementwise >>> res_bracket = elementwise.bracket_root(f, 0) >>> res_bracket.success True >>> res_bracket.bracket (2.0, 4.0)
实际上,函数在区间端点处的值具有相反的符号。
>>> res_bracket.f_bracket (-1.0, 51.0)
一旦我们有了一个有效区间,就可以使用
find_root
来提供精确的根。>>> res_root = elementwise.find_root(f, res_bracket.bracket) >>> res_root.x 2.0945514815423265
最终区间只有几个 ULPs 宽,因此在此值与真实根之间的误差在双精度算术可表示的值内不可能小得多。
>>> import numpy as np >>> xl, xr = res_root.bracket >>> (xr - xl) / np.spacing(xl) 2.0 >>> res_root.f_bracket (-8.881784197001252e-16, 9.769962616701378e-15)
bracket_root
和find_root
接受数组作为大多数参数。例如,一次性查找参数c
的几个值的根>>> c = np.asarray([3, 4, 5]) >>> res_bracket = elementwise.bracket_root(f, 0, args=(c,)) >>> res_bracket.bracket (array([1., 1., 2.]), array([2., 2., 4.])) >>> res_root = elementwise.find_root(f, res_bracket.bracket, args=(c,)) >>> res_root.x array([1.8932892 , 2. , 2.09455148])