scipy 中的有界根查找

Bounded root finding in scipy

Scipy 提供了几个看似等效的函数来求函数在给定区间内的根:

brentq(f, a, b[, args, xtol, rtol, maxiter, ...]) Find a root of a function in given interval.

brenth(f, a, b[, args, xtol, rtol, maxiter, ...]) Find root of f in [a,b].

ridder(f, a, b[, args, xtol, rtol, maxiter, ...]) Find a root of a function in an interval.

bisect(f, a, b[, args, xtol, rtol, maxiter, ...]) Find root of a function within an interval.

(参见 this webpage。)

任何人都可以提供一些指南来选择其中之一而不是其他吗?找到适合我的案例的最佳策略是简单的反复试验吗?

brentq

brentq 声称是问题中四个函数中最好的。它的文档字符串是

Generally considered the best of the rootfinding routines here.

但是,它有(至少)两个烦人的特性:

1) 要求f(a)f(b)符号不同。

2) 如果 a 是一个非常小的正数(与 1e-3 一样大),它偶尔会 returns 0.0 作为解决方案——即,它 return 是超出提交范围的解决方案。

brenth

brenth 分享 brentq 上面的特征 1。

ridder

ridder 分享 brentq 上面的特征 1。

bisect

bisect 与上述 brentq 的功能 1 相同,但比其他功能慢。

最小化方法

我意识到我可以通过取函数输出的绝对值将求根问题转化为最小化问题 f。 (另一种选择是取 f 输出的平方。)Scipy 提供了几个用于标量函数有界最小化的函数:

fminbound(func, x1, x2[, args, xtol, ...]) Bounded minimization for scalar functions.

brent(func[, args, brack, tol, full_output, ...]) Given a function of one-variable and a possible bracketing interval, return the minimum of the function isolated to a fractional precision of tol.

brute(func, ranges[, args, Ns, full_output, ...]) Minimize a function over a given range by brute force.

fminbound

我唯一的抱怨是它太慢了。它没有要求 f(a)f(b).

符号不同的限制

brent

对于它的包围间隔 [a, b]brent 要求 f(a) 小于 f(b)。其解不保证在[a, b].

以内

brute

brute 当然非常慢(取决于 Ns 参数的值),而且奇怪的是,可能 return 一个解决方案超出了提交的范围。

结论

综上所述,我使用 中的方法获得了最好的结果——即,在尚未发布的版本中使用函数 least_squares scipy。此功能具有上述限制的 none。