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]