我有一个函数f(x),我知道它在一个区间内有两个零,我需要计算两个x值,函数越过0。
我通常使用
import scipy.optimize as opt
opt.brentq(f, xmin, xmax)
但问题是如果函数在区间中有一个0,这个方法是有效的,并且知道在哪里分成两部分并不是很简单。
该功能的评估时间也很昂贵......
答案 0 :(得分:1)
我认为一个好方法是在搜索零之前通过采样f预处理零搜索。在该预处理期间,您评估f以检测函数的符号是否已更改。
def preprocess(f,xmin,xmax,step):
first_sign = f(xmin) > 0 # True if f(xmin) > 0, otherwise False
x = xmin + step
while x <= xmax: # This loop detects when the function changes its sign
fstep = f(x)
if first_sign and fstep < 0:
return x
elif not(first_sign) and fstep > 0:
return x
x += step
return x # If you ever reach here, that means that there isn't a zero in the function !!!
使用此功能,您可以将您的初始间隔分成几个较小的间隔。例如:
import scipy.optimize as opt
step = ...
xmid = preprocess(f,xmin,max,step)
z0 = opt.brentq(f,xmin,xmid)
z1 = opt.brentq(f,xmid,xmax)
根据您使用的函数f
,您可能需要在两个以上的子间隔中分隔您的间隔。只需像这样迭代[xmin,xmax]:
x_list = []
x = x_min
while x < xmax: # This discovers when f changes its sign
x_list.append(x)
x = preprocess(f,x,xmax,step)
x_list.append(xmax)
z_list = []
for i in range(len(x_list) - 1):
z_list.append(opt.brentq(f,x_list[i],x_list[i + 1]))
最后,z_list
包含给定间隔[xmin,xmax]中的所有零。
请记住,这个算法非常耗时,但可以完成这项工作。