Python + Scipy + Integration:处理带尖峰的函数中的精度错误

时间:2010-07-06 12:37:53

标签: python scipy precision integrate numerical-methods

我正在尝试使用scipy.integrate.quad在很大的范围内集成一个函数(0..10,000)。该函数在其大部分范围内为零,但在非常小的范围内具有峰值(例如1,602..1,618)。

当积分时,我希望输出是正的,但我猜不知道,四位猜测算法会混淆并输出零。我想知道的是,有没有办法克服这个问题(例如通过使用不同的算法,其他一些参数等)?我通常不知道尖峰的位置,所以我不能只分割积分范围并对各部分求和(除非有人对如何做到这一点有好主意)。

谢谢!

示例输出:

>>>scipy.integrate.quad(weighted_ftag_2, 0, 10000)
(0.0, 0.0)
>>>scipy.integrate.quad(weighted_ftag_2, 0, 1602)
(0.0, 0.0)
>>>scipy.integrate.quad(weighted_ftag_2, 1602, 1618)
(3.2710994652983256, 3.6297354011338712e-014)
>>>scipy.integrate.quad(weighted_ftag_2, 1618, 10000)
(0.0, 0.0)

2 个答案:

答案 0 :(得分:2)

您可能想尝试其他集成方法,例如integrate.romberg()方法。

或者,您可以使用weighted_ftag_2(x_samples).argmax()获取函数较大的点的位置,然后使用一些启发式方法来减少函数最大值周围的积分间隔(位于{{1您必须将抽样横坐标列表(x_samples[….argmax()])计入您的问题:它必须始终包含您的函数最大的区域中的点。

更一般地说,有关要集成的功能的任何特定信息都可以帮助您获得其积分的良好价值。我将结合一种适用于您的函数的方法(Scipy提供的many methods之一)和合理的积分间隔分割(例如,沿着上面提到的行)。

答案 1 :(得分:1)

如何在每个整数范围[x,x + 1]上计算函数f(), 并加起来,例如正如EOL建议的那样romb(),其中> 0:

from __future__ import division
import numpy as np
from scipy.integrate import romb

def romb_non0( f, a=0, b=10000, nromb=2**6+1, verbose=1 ):
    """ sum romb() over the [x, x+1) where f != 0 """
    sum_romb = 0
    for x in xrange( a, b ):
        y = f( np.arange( x, x+1, 1./nromb ))
        if y.any():
            r = romb( y, 1./nromb )
            sum_romb += r
            if verbose:
                print "info romb_non0: %d %.3g" % (x, r)  # , y
    return sum_romb

#...........................................................................
if __name__ == "__main__":
    np.set_printoptions( 2, threshold=100, suppress=True )  # .2f

    def f(x):
        return x if (10 <= x).all() and (x <= 12).all() \
            else np.zeros_like(x)

    romb_non0( f, verbose=1 )