Scipy quad returns(接近)零,即使有 points 参数

Scipy quad returns (near) zero, even with points argument

有时 scipy.integrate.quad 错误地 returns 接近 0 的值。这已在 中得到解决,并且似乎会在积分技术未在与 0 显着不同的狭窄范围内评估函数时发生。在这个问题和类似问题中,公认的解决方案始终是使用points 参数告诉 scipy 去哪里看。然而,对我来说,这似乎实际上让事情变得更糟。

指数分布积分pdf(答案应该在1以下):

from scipy import integrate
import numpy as np
t2=.01
#initial problem: fails when f is large
f=5000000
integrate.quad(lambda t:f*np.exp(-f*(t2-t)),0,t2)
#>>>(3.8816838175855493e-22, 7.717972744727115e-22)

现在,“修复”使它失败,即使在原始工作的较小 f 值上也是如此:

f=2000000
integrate.quad(lambda t:f*np.exp(-f*(t2-t)),0,t2)
#>>>(1.00000000000143, 1.6485317987792634e-14)
integrate.quad(lambda t:f*np.exp(-f*(t2-t)),0,t2,points=[t2])
#>>>(1.6117047218907458e-17, 3.2045611390981406e-17)
integrate.quad(lambda t:f*np.exp(-f*(t2-t)),0,t2,points=[t2,t2])
#>>>(1.6117047218907458e-17, 3.2045611390981406e-17)

这是怎么回事?我怎样才能告诉 scipy 做什么,以便计算 f 的任意值?

这不是一个通用的解决方案,但我已经能够通过使用 points=np.geomspace 来为给定的函数修复这个问题,以引导数值算法在感兴趣的区域进行更重的采样。我会把这个打开一点,看看是否有人找到了通用的解决方案。

为 t2 和 f 生成随机值,然后检查应该非常接近 1 的子集的最小值和最大值:

>>> t2s=np.exp((np.random.rand(20)-.5)*10)
>>> fs=np.exp((np.random.rand(20)-.1)*20)
>>> min(integrate.quad(lambda t:f*np.exp(-f*(t2-t)),0,t2,points=t2-np.geomspace(1/f,t2,40))[0] for f in fs for t2 in t2s if f>(1/t2)*10)
0.9999621825009719
>>> max(integrate.quad(lambda t:f*np.exp(-f*(t2-t)),0,t2,points=t2-np.geomspace(1/f,t2,40))[0] for f in fs for t2 in t2s if f>(1/t2)*10)
1.000000288722783