在给定范围内查找函数的根



我有一组f_t的函数,它们有几个根(实际上是两个)。我想找到"第一个"根,并且在大多数情况下fsolve可以正常工作。问题是,两个根会聚,因为t走向无穷大。(我的函数的简单示例将是f_t(x) = x^2 - 1/t)。因此,t越大,fsolve犯的错误就越多。是否有一个预定义的函数,类似于我可以告诉它应该只在给定范围内查找的fsolve(例如,始终在[0, inf中找到根))。

这个问题本质上与 https://mathematica.stackexchange.com/questions/91784/how-to-find-numerically-all-roots-of-a-function-in-a-given-range?noredirect=1&lq=1 相同,但是Mathematica的答案,我希望它们在Python中。

PS:我现在如何编写自己的算法,但由于这些算法往往比内置算法慢,我希望找到一个做同样事情的内置算法。特别是我读过这篇文章 在给定间隔内查找函数的根

人们普遍认为,对于平滑、行为良好的函数,布伦特方法是保证给出根的最快方法。 与列出的其他两种方法一样,您必须提供一个区间 [a,b],该区间函数是连续的并更改符号。

此处记录了 Scipy 实现。 您提到的函数的示例用例如下所示:

from __future__ import division
import scipy
def func(x,t):
return(x**2 - 1/t)
t0 = 1
min = 0
max = 100000 # set max to some sufficiently large value
root = scipy.optimize.brentq(func, min, max, args = (t0)) # args just supplies any extra
# argument for the function that isn't the varied parameter

您可以使用scipy.optimize.bisect,它采用定义起始间隔的两个参数ab。但是,有一些限制:

  • 间隔必须是有限的。不能在 [0, inf] 中搜索。
  • 该函数必须在根部使用反转符号(f(a)f(b)必须具有相反的符号),因此,例如,您无法找到f(x) = abs(x)的根(如果这甚至是数学意义上的"根")。此外,它不适用于f(x) = x**2 - 1和 [a, b] 与 a<-1 和 b>1 的间隔。
  • 该方法不是基于梯度的。如果函数非常锯齿状或评估成本很高,这可能是一个优势,但在其他函数上可能会慢一些。

另一种方法是使用scipy.optimize.minimize来最小化abs(f(x)).此函数可以采用包含无穷大bounds。但最小化可能最终导致函数的非根本地最小值。

传统上,您可以使用root

import numpy as np
from scipy.optimize import root
def func(x, t):
return x ** 2 - 1. / t
t = 5000
res = root(func, 0.5, args=(t, )).x[0]
print res

这将打印正数,在本例中为0.0141421356237.

如果要指定范围并确定此区间内的所有根,可以使用chebpy

from chebpy import chebfun
x = chebfun('x', [-100000, 100000])
t = 5000
f = x ** 2 - 1. / t
rts = f.roots()
print rts

在这种情况下,这将同时打印正根和负根

[-0.01413648  0.01413648]

如果您只想查看正范围,则可以更改

x = chebfun('x', [-100000, 100000])

x = chebfun('x', [0, 100000])

然而,我不确定如何使用无穷大,但我认为你可以出于实际目的使用非常高的数字。

最新更新