使用 scipyintegrate.quad 对积分进行重复评估

问题描述

我有一个函数,我需要估计它在许多不同区间的定积分,其中一些区间的端点彼此非常接近,

\int_a^{b_k} f(x) dx

我可以为每个时间间隔重新调用 integrate.quad,但这似乎效率很低,因为 integrate.quad 会为每次调用多次评估函数。有什么方法可以重用 quad 已经评估过的点,以便更快地对 quad 进行后续调用

(如果没有 integrate.quad,也许是另一个 scipy 函数或使用不同的公共 python 库?)

或者我应该缓存我之前的积分值,然后调用 quad 来计算新点和之前计算的最近点之间的差异?

另请注意,所选择的端点并非都是事先知道的,它们是自适应选择的。

解决方法

对于具有不同端点的区间,您可以使用通用自适应积分方法的希望不大。这样做的原因是,一般情况下,如果您稍微更改限制,积分值就会发生很大变化。您必须以某种方式提供您的函数在边界处不是“疯狂”的信息,给出估计等,而我不知道这样的方法。

可以做的是通过变量替换将积分转换为相同的区间,比如 [0,1]。您最终的任务是在 [0,1] 上集成许多(参数化的)函数。

\int_0^1 f_a(x)

然后您可以尝试对函数调用进行向量化,即针对一个点或一组点同时评估所有函数。

quadpy(我的一个项目)支持矢量化正交,可以显着加快集成速度。多个不同指数的 x ** a 示例:

import numpy as np
import quadpy

a = np.arange(1,7)

def f(x):
    return np.power.outer(x,a).T


val,err = quadpy.quad(f,0.0,1.0)

print(val)
print(err)
[0.5        0.33333333 0.25       0.2        0.16666667 0.14285714]
[1.87519478e-20 2.58599737e-20 4.45666434e-20 5.19063171e-20
 5.45158477e-20 4.09060649e-20]

请注意,在 f 中,计算是矢量化的,而不是迭代 a。这大大加快了计算速度。