gpt4 book ai didi

python - 在 python 中查找根

转载 作者:太空狗 更新时间:2023-10-30 02:45:31 25 4
gpt4 key购买 nike

编辑:这里的一个大问题是 scipy.optimize.brentq 要求搜索区间的限制具有相反的符号。如果您将搜索间隔分成任意部分并像我在下面和 Dan 在评论中所做的那样在每个部分上运行 brentq,您最终会抛出很多无用的 ValueErrors。在 Python 中有没有巧妙的方法来处理这个问题?

原帖:我在 python 中反复搜索函数以寻找最大的零。现在我正在使用 scipy.optimize.brentq寻找根,然后在我的初始边界不起作用时使用粗暴的搜索方法:

#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 中寻找函数的最大根的更聪明的方法是什么?


谢谢丹;根据要求,下面提供了更多信息。

我正在搜索的函数在我感兴趣的区域中表现良好。下面绘制了一个示例(代码在帖子末尾)。

I'd like to find the largest root of this function

唯一的奇异点位于 0(离开图顶部的峰值是有限的)并且有两个或三个根。最大的根通常不大于 1,但它绝不会跑到无穷大。根之间的间隔在域的低端变小,但它们永远不会变得非常小(我会说它们总是大于 10^-3)。

from numpy import exp as e
#this isn't the function I plotted
def V(r):
return 27.2*(
23.2*e(-43.8*r) +
8.74E-9*e(-32.9*r)/r**6 -
5.98E-6*e(-0.116*r)/r**4 +
0.0529*( 23*e(-62.5*r) - 6.44*e(-32*r) )/r -
29.3*e(-59.5*r)
)

#this is the definition of the function in the plot
def f(r,b,E):
return 1 - b**2/r**2 - V(r)/E

#the plot is of f(r,0.1,0.06)

最佳答案

好问题,但这是一个数学问题而不是 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

我在你的函数上试过了,它找到了最大的根,在 ~0.14 处。

不过,brentq 有一些棘手的地方:

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]

sin 函数的根应该在 0、π、2π、3π。但是这种方法只是找到前两个。我意识到问题就在那里in the docs : f(a) 和 f(b) 必须有相反的符号。 看起来 所有 scipy.optimize 寻根函数都有同样的要求,所以任意划分间隔是行不通的。

关于python - 在 python 中查找根,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24332809/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com