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

时间:2017-04-07 06:48:09

标签: python function numpy scipy

我有一组函数f_t,有几个根(实际上是两个)。我想找到"第一个" root并使用fsolve执行此操作大部分时间都可以正常工作。问题是,两个根会合,因为t变为无穷大。 (我的函数的一个简单例子是f_t(x) = x^2 - 1/t)。因此,t越大,fsolve犯的错误就越多。是否存在预定义函数,类似于fsolve我可以告诉它只应查看给定范围(例如,始终查找[0, inf中的根)。) p>

这个问题与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:我现在如何编写自己的算法,但由于这些内容往往比内置的慢,我希望找到一个同样的内置函数。特别是我已经阅读了这篇文章Find root of a function in a given interval

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

人们普遍认为,对于平滑,表现良好的函数,Brent method是保证提供根的最快方法。与列出的其他两种方法一样,您必须提供一个间隔[a,b],函数是连续的并且会改变符号。

Scipy实现记录在案here。您提到的函数的示例用例可能如下所示:

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

答案 2 :(得分:1)

经典地说,您可以使用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])

然而,我不知道如何使用无穷大,但我认为你可以在实际目的中使用非常高的数字。