python中的根查找
编辑:这里的一个大问题是python中的根查找,python,optimization,numpy,Python,Optimization,Numpy,编辑:这里的一个大问题是scipy.optimize.brentq要求搜索间隔的限制具有相反的符号。如果你将搜索间隔分割成任意部分,并像我下面所做的和Dan在评论中所做的那样在每个部分上运行brentq,你最终会抛出许多无用的ValueErrors。在Python中有没有一种巧妙的方法来处理这个问题 原职: 我在python中反复搜索函数中最大的零。现在我正在使用查找根,如果初始边界不起作用,则使用野蛮搜索方法: #function to find the largest root of f d
scipy.optimize.brentq
要求搜索间隔的限制具有相反的符号。如果你将搜索间隔分割成任意部分,并像我下面所做的和Dan在评论中所做的那样在每个部分上运行brentq
,你最终会抛出许多无用的ValueErrors。在Python中有没有一种巧妙的方法来处理这个问题
原职:
我在python中反复搜索函数中最大的零。现在我正在使用查找根,如果初始边界不起作用,则使用野蛮搜索方法:
#function to find the largest root of f
def bigRoot(func, pars):
try:
root = brentq(func,0.001,4,pars)
except ValueError:
s = 0.1
while True:
try:
root = brentq(func,4-s,4,pars)
break
except ValueError:
s += 0.1
continue
return root
这有两个大问题
首先,我假设如果在一个区间中有多个根,brentq将返回最大的根。我做了一些简单的测试,除了最大的根,我从未看到它返回任何东西,但我不知道这是否在所有情况下都是正确的
第二个问题是,在脚本中,我使用的这个函数在某些情况下总是返回零,即使传递给bigRoot
的函数在0处发散。如果我将搜索的步长从0.1更改为0.01,那么在这些情况下,它将返回一个常量非零值。我意识到细节取决于我传递给bigRoot
的函数,但我认为问题可能在于我执行搜索的方式
问题是,在python中查找函数最大根的更聪明的方法是什么
谢谢丹;更多信息请参见下文 我正在搜索的函数在我感兴趣的区域中表现良好。下面绘制了一个示例(文章末尾的代码) 唯一的奇点是在0处(图顶部的峰值是有限的),并且有两个或三个根。最大的根通常不大于1,但它从来不会像跑向无穷远那样。根之间的间隔在域的低端变得更小,但它们永远不会变得非常小(我想说它们总是大于10^-3)
好问题,但这是一个数学问题,而不是Python问题 在没有函数根的解析公式的情况下,即使在给定的有限区间内,也无法保证找到该函数的最大根。例如,我可以构造一个在±1当它接近1时,速度越来越快
f(x) = sin(1/(1-x))
这将阻碍任何试图在区间[0,1]上找到最大根的数值方法,因为对于任何根,区间中总是有较大的根
因此,为了更深入地了解这个一般性问题,您必须提供一些关于所讨论函数的特征的背景知识
更新:看起来函数表现良好。brentq
文档表明,无法保证找到区间中最大/最小的根。请尝试对区间进行分区,并递归搜索更小和更大的其他根
from scipy.optimize import brentq
# This function should recursively find ALL the roots in the interval
# and return them ordered from smallest to largest.
from scipy.optimize import brentq
def find_all_roots(f, a, b, pars=(), min_window=0.01):
try:
one_root = brentq(f, a, b, pars)
print "Root at %g in [%g,%g] interval" % (one_root, a, b)
except ValueError:
print "No root in [%g,%g] interval" % (a, b)
return [] # No root in the interval
if one_root-min_window>a:
lesser_roots = find_all_roots(f, a, one_root-min_window, pars)
else:
lesser_roots = []
if one_root+min_window<b:
greater_roots = find_all_roots(f, one_root+min_window, b, pars)
else:
greater_roots = []
return lesser_roots + [one_root] + greater_roots
sin
函数的根应该是0,π,2π,3π。但是这种方法只找到了前两个。我意识到问题就在那里:f(a)和f(b)必须有相反的符号。看来scipy.optimize
根查找函数的所有都有相同的要求,所以任意划分区间是行不通的。@wnnmaw:可能吧。如果OP提供了更多关于他在这里使用的函数类约束的详细信息,我们可能可以具体使用scipy
了解如何使用它们。感谢您的帮助,Dan;您的最后一点就是我对这个问题如此关注的原因。我希望有人以前在Python中这样做过,并且实现了一种很好的方法来处理间隔,因为您必须使用相反的方法给出brentq限制标志…我显然应该在之前说。原稿编辑。
from scipy.optimize import brentq
# This function should recursively find ALL the roots in the interval
# and return them ordered from smallest to largest.
from scipy.optimize import brentq
def find_all_roots(f, a, b, pars=(), min_window=0.01):
try:
one_root = brentq(f, a, b, pars)
print "Root at %g in [%g,%g] interval" % (one_root, a, b)
except ValueError:
print "No root in [%g,%g] interval" % (a, b)
return [] # No root in the interval
if one_root-min_window>a:
lesser_roots = find_all_roots(f, a, one_root-min_window, pars)
else:
lesser_roots = []
if one_root+min_window<b:
greater_roots = find_all_roots(f, one_root+min_window, b, pars)
else:
greater_roots = []
return lesser_roots + [one_root] + greater_roots
print find_all_roots(sin, 0, 10, ())
Root at 0 in [0,10] interval
Root at 3.14159 in [0.01,10] interval
No root in [0.01,3.13159] interval
No root in [3.15159,10] interval
[0.0, 3.141592653589793]