查找给定区间内任意插值函数的所有根
Find all roots of an arbitrary interpolated function in a given interval
我试图在定义的区间内找到任意函数的 所有 根。我已经在寻找解决方案,但没有找到任何可以轻松解决我的问题的方法。
例如,我得到了积分,我使用 interp1d 创建了这些积分的函数。假设一个余弦函数:
x_p = np.linspace(0,2*pi,100)
y_p = np.cos(x_p)
接下来,我使用 interp1d 生成所需的函数
f = interp1d(x_p,y_p,kind="cubic")
我已经尝试使用 fsolve,但它只能根据起点找到一个根
fsolve(lambda x: f(x),0.1)
当我尝试时
brentq(f,0,6)
我收到错误
f(a) and f(b) must have different signs
我猜 brentq 不是正确答案,因为在区间内我得到了不止 1 个根。
这个问题有没有优雅的解决方案?
非常感谢您。
一般来说,找到任意函数的所有根是不可能的(参见 1 & 2)。
对于插值函数,它们通常由多项式串联构成,可以确定根数并找到所有根。但是你必须知道interp1d
下的多项式系数才能解决问题。
现实中,一个未知函数被采样得到一系列数据点。在您的例子中,未知函数的样本由 cos()
给出。插值函数 f
用于模拟行为。可发现根的最小间距受采样间隔限制。这是因为root-finding的存在性定理告诉我们,如果f(a) * f(b) <= 0
,那么[a, b]
之间就有一个根。换句话说,如果符号在f(a)
和f(b)
处没有变化,我们对[a,b]
之间的根没有结论。这解释了错误 f(a) and f(b) must have different signs
.
对于fsolve(lambda x: f(x),0.1)
,我得到了
ValueError: A value in x_new is above the interpolation range.
这意味着初始猜测 0.1
是错误的,背后的算法可能 运行 x
在区间 [0, 2*pi]
.
之外
为了做出有根据的猜测,它应该尽可能靠近根。因此,应该选择符号变化的左/右点。
f_p = f(x_p)
indices, = np.nonzero(f_p[:-1] * f_p[1:] <= 0)
for i in range(indices.shape[0]):
guess = x_p[indices[i]]
print('root', i + 1, 'x=', fsolve(f, guess))
输出:
root 1 x= [1.57079633]
root 2 x= [4.71238898]
我试图在定义的区间内找到任意函数的 所有 根。我已经在寻找解决方案,但没有找到任何可以轻松解决我的问题的方法。
例如,我得到了积分,我使用 interp1d 创建了这些积分的函数。假设一个余弦函数:
x_p = np.linspace(0,2*pi,100)
y_p = np.cos(x_p)
接下来,我使用 interp1d 生成所需的函数
f = interp1d(x_p,y_p,kind="cubic")
我已经尝试使用 fsolve,但它只能根据起点找到一个根
fsolve(lambda x: f(x),0.1)
当我尝试时
brentq(f,0,6)
我收到错误
f(a) and f(b) must have different signs
我猜 brentq 不是正确答案,因为在区间内我得到了不止 1 个根。 这个问题有没有优雅的解决方案?
非常感谢您。
一般来说,找到任意函数的所有根是不可能的(参见 1 & 2)。
对于插值函数,它们通常由多项式串联构成,可以确定根数并找到所有根。但是你必须知道interp1d
下的多项式系数才能解决问题。
现实中,一个未知函数被采样得到一系列数据点。在您的例子中,未知函数的样本由 cos()
给出。插值函数 f
用于模拟行为。可发现根的最小间距受采样间隔限制。这是因为root-finding的存在性定理告诉我们,如果f(a) * f(b) <= 0
,那么[a, b]
之间就有一个根。换句话说,如果符号在f(a)
和f(b)
处没有变化,我们对[a,b]
之间的根没有结论。这解释了错误 f(a) and f(b) must have different signs
.
对于fsolve(lambda x: f(x),0.1)
,我得到了
ValueError: A value in x_new is above the interpolation range.
这意味着初始猜测 0.1
是错误的,背后的算法可能 运行 x
在区间 [0, 2*pi]
.
为了做出有根据的猜测,它应该尽可能靠近根。因此,应该选择符号变化的左/右点。
f_p = f(x_p)
indices, = np.nonzero(f_p[:-1] * f_p[1:] <= 0)
for i in range(indices.shape[0]):
guess = x_p[indices[i]]
print('root', i + 1, 'x=', fsolve(f, guess))
输出:
root 1 x= [1.57079633]
root 2 x= [4.71238898]