振荡功能的集成无法在python中收敛

AnS*_*nSy 2 python scipy

我想使用scipy.integrate.quad评估函数的积分。这是被积数的样子: 振荡功能的积分 我们可以注意到,该被积物的大部分贡献将来自.1到4或5 ish。当x = 10或更大时,尽管该函数具有振荡性(很难在图片上说出),但它非常小并且会越来越小。

这是从0到某个上限的积分结果。积分的上限在x轴上。 将被积物积分到某个上限 在这里,虽然结果对于前一百个x来说似乎是稳定的,但即使我期望一条直线,情况也不再如此。

我是python的新手,我不知道什么是最好的操作方法。现在,我最好的猜测是将小于100的某个值作为我的积分的上限,并舍弃其他值,因为这只是来自tegral.quad的不良收敛。

编辑: 要绘制第二张图,我使用了scipy.integrate.quad函数。但是,如果仅用生成的点来绘制被积物(第一个图),然后在scipy.integrate.simps中使用该点,并改变最大积分倍数,我将得到一致的结果。

小智 5

当被积物具有比积分范围小得多的重要特征时,自适应quad例程可能会“忽略”它。相反,simps如果使用足够精细的网格,不要错过它们,但是可能需要更长的时间进行评估。我将描述两种解决方法,第二种是更实际的方法。

点参数

您可以使用的points参数quad来确保不会发生这种情况。这是一个示例,其中我exp(-x**2)在区间[-1000,5000]上积分了高斯函数。该函数位于0附近。几乎所有这些都在[-5,5]区间内,所以我包括points=[-5, 5]确保不会忽略此范围。(这些点必须在积分范围内,因此在的范围内if)。

import numpy as np
from scipy.integrate import quad
import matplotlib.pyplot as plt

f = lambda x: np.exp(-x**2) 
numpoints = 1000
t = np.linspace(-1000, 5000, numpoints)
y = np.zeros((numpoints,))

for i in range(numpoints):
    y[i] = quad(f, -1000, t[i])[0]      # integration without points
plt.plot(t, y, 'r') 

for i in range(numpoints):            # using points if upper bound is above 5 
    y[i] = quad(f, -1000, t[i], points=[-5,5])[0] if t[i] > 5 else quad(f, -1000, t[i])[0]
plt.plot(t, y, 'b') 
plt.show()
Run Code Online (Sandbox Code Playgroud)

红色曲线是不带输出points,蓝色曲线是带points。后者的行为应为:从0上升到pi / 2并停留在那里。

结果

重用以前的计算

在多个点上计算反导数的一种更有效的方法是使用先前计算的值,并向其添加未积分的区间的贡献。

y = np.zeros((numpoints,))
for i in range(1, numpoints):
    y[i] = y[i-1] + quad(f, t[i-1], t[i])[0]
plt.plot(t, y, 'g') 
Run Code Online (Sandbox Code Playgroud)

与上面的蓝色曲线具有相同的输出。