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

发布于 2024-09-08 11:55:06 字数 621 浏览 2 评论 0原文

我正在尝试使用 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)

I am trying to use scipy.integrate.quad to integrate a function over a very large range (0..10,000). The function is zero over most of its range but has a spike in a very small range (e.g. 1,602..1,618).

When integrating, I would expect the output to be positive, but I guess that somehow quad's guessing algorithm is getting confused and outputting zero. What I would like to know is, is there a way to overcome this (e.g. by using a different algorithm, some other parameter, etc.)? I don't usually know where the spike is going to be, so I can't just split the integration range and sum the parts (unless somebody has a good idea on how to do that).

Thanks!

Sample output:

>>>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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

↙厌世 2024-09-15 11:55:06

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

或者,您可以使用 weighted_ftag_2(x_samples).argmax() 获取函数较大点的位置,然后使用一些启发式方法来缩短函数最大值附近的积分区间 (它位于 x_samples[….argmax()],您必须根据您的问题调整采样横坐标 (x_samples) 列表:它必须始终包含位于 。

更一般地说,有关要集成的函数的任何具体信息都可以帮助您获得其积分的良好值,我将结合一种适合您的函数的方法(Scipy 提供的许多方法),并合理分割积分区间(例如沿着上面建议的行)。

You might want to try other integration methods, such as the integrate.romberg() method.

Alternatively, you can get the location of the point where your function is large, with weighted_ftag_2(x_samples).argmax(), and then use some heuristics to cut the integration interval around the maximum of your function (which is located at x_samples[….argmax()]. You must taylor the list of sampled abscissas (x_samples) to your problem: it must always contain points that are in the region where your function is maximum.

More generally, any specific information about the function to be integrated can help you get a good value for its integral. I would combine a method that works well for your function (one of the many methods offered by Scipy) with a reasonable splitting of the integration interval (for instance along the lines suggested above).

杀手六號 2024-09-15 11:55:06

如何在每个整数范围 [x, x+1) 上评估函数 f(),
并相加,例如 romb(),正如 EOL 所建议的,其中 > 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 )

How about evaluating your function f() over each integer range [x, x+1),
and adding up e.g. romb(), as EOL suggests, where it's > 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 )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文