【问题标题】:python: integrating a piecewise functionpython:集成分段函数
【发布时间】:2013-10-09 06:53:53
【问题描述】:

我想对一个已定义的函数进行分段积分,该函数乘以勒让德多项式。 不幸的是,我在documentation 中找不到如何使用 x 的第 n 个勒让德多项式。我想在n = 1,..., 50 时对x 的每个勒让德多项式进行积分,所以我设置了n = np.arange(1, 51, 1)

import numpy as np
import pylab
from scipy import integrate

n = np.arange(1, 51, 1)                                                   


def f(x):
    if 0 <= x <= 1:
        return 1
    if -1 <= x <= 0:
        return -1

我想我需要定义另一个函数,比如说u(x)

c = []


def u(x):
    c.append((2. * n + 1) / 2. * integrate.quad(f(x) * insert Legendre polynomials here, -1., 1.)) 
    return sum(c * Legendre poly, for nn in range(1, 51)) 

所以我会返回一些 u(x),前 50 个项通过勒让德多项式扩展我的分段函数。

编辑 1:

如果这不能完成,我可以使用罗德里格斯公式来计算第 n 个勒让德多项式。但是,当我在 Python 中寻找计算 n 次导数时,我找不到任何有用的东西。

P_n(x) = \frac{1}{2^n n!}\frac{d^n}{dx^n}(x^2 - 1)^n

所以如果有人知道如何在 Python 中实现这样的方案,这是一个选择。

编辑 2:

使用 Saullo Castro 的回答,我有:

import numpy as np
from scipy.integrate import quad

def f(x, coef):
    global p
    p = np.polynomial.legendre.Legendre(coef=coef)
    if 0 <= x <= 1:
        return 1*p(x)
    if -1 <= x <= 0:
        return -1*p(x)

c = []
for n in range(1, 51):
    c.append((2. * n + 1.) / 2. * quad(f, -1, 1, args=range(1,n+1))[0])

def g(x)
    return sum(c * p(x) for n in range(1, 51))

但是,如果我打印 c,则值是错误的。值应为1.5, 0, -7/8, 0, ...

另外,当我绘制g时,我想做x = np.linspace(-1, 1, 500000),所以情节很详细,但c只有50。如何实现?

【问题讨论】:

    标签: python numpy scipy numerical-integration


    【解决方案1】:

    如果我正确理解您的问题,您想计算 f(x) * Ln(x) 的积分,其中 f(x) 是您使用 python 函数定义的分段函数。我假设您对这个特定的步进函数并不特别感兴趣。

    您可以使用 legval 和系数参数的单位矩阵来获取勒让德多项式的值。

    import numpy as np
    import matplotlib
    
    x = np.linspace(-1, 1, 201)
    
    L = np.polynomial.legendre.legval(x, np.identity(50))
    
    plt.plot(x, L.T)
    

    然后您可以执行积分积分。使用 gauss-legendre 求积可能更有效,因为 Legendre 多项式的积分对于 Ln(x) 将是精确的,其中 n 小于求积大小。

    import numpy as np    
    from numpy.polynomial.legendre import leggauss, legval
    
    def f(x):
        if 0 <= x <= 1:
            return 1
        if -1 <= x <= 0:
            return -1
    
    # of course you could write a vectorized version of
    # this particular f(x), but I assume you have a more
    # general piecewise function
    f = np.vectorize(f)
    
    deg = 100
    x, w = leggauss(deg) # len(x) == 100
    
    L = np.polynomial.legendre.legval(x, np.identity(deg))
    # Sum L(xi)*f(xi)*wi
    integral = (L*(f(x)*w)[None,:]).sum(axis=1)
    
    c = (np.arange(1,51) + 0.5) * integral[1:51]
    
    x_fine = np.linspace(-1, 1, 2001) # 2001 points
    Lfine = np.polynomial.legendre.legval(x_fine, np.identity(51))
    
    # sum_1_50 of c(n) * Ln(x_fine)
    cLn_sum = (c[:,None] * Lfine[1:51,:]).sum(axis=0)
    

    c = 1.5, 0, -8.75e-1, 0, ... 我认为这是您正在寻找的结果。

    【讨论】:

    • 如何绘制sum(c * p(x) for n in range(1, 51)) 其中p(x) 是勒让德多项式或n阶?
    • L 的行包含 L(x),从第一行的 L0 开始。你做总和并绘制它们。
    • 我遇到的问题是我们没有 n 来求和,那么我该如何求和?
    • 我真的不明白“我们没有一个可以总结的 n”。 L 的第 n 行表示 Ln(x) 的值,其中每一列对应于不同的 x 值。即,L[n, i] == Ln(x[i])。我已经修改了答案以显示如何在 numpy 中获得这个总和。你也可以只写一个循环。在这一点上,我对你想要完成的事情有点困惑,但我希望这能回答你的问题。
    • 当然你可以用更精细的 x 间距重新计算 L。有两种方法可以做到这一点。您可以只增加用于积分的程度,这将增加正交点。你也可以用更细的间距重新计算 L,就像我在上面所做的那样。我没有检查积分是否收敛,所以你可能想增加 deg 看看是否有任何变化。
    【解决方案2】:

    您可以像这样进行集成:

    import numpy as np
    from scipy.integrate import quad
    
    def f(x, coef):
        n = coef[-1]
        p = (2*n+1)/2.*np.polynomial.legendre.Legendre(coef=coef)
        if 0 <= x <= 1:
            return 1*p(x)
        if -1 <= x <= 0:
            return -1*p(x)
    
    c = []
    for n in range(1, 51):
        c.append(quad(f, -1, 1, args=range(1,n+1))[0])
    

    这给出了:

    print c
    #[0.0, 5.0, 6.9999999999999991, 4.5, ... , 62.975635570615466, 64.274102283412574, 77.143785770271251]
    

    【讨论】:

    • 有些东西没有写。第一个系数应该是 1.5 但这会打印出 0, 5, 7, 4.5, .. 此外,由于我忘记输入 (2.*n + 1.)/2,你会得到一些稍微不同的东西。在我的第一篇文章中的集成之前。所以我有c.append((2. * n + 1.) / 2. * quad(f, -1, 1, args=range(1,n+1))[0])
    • 这是整合n吗?如果是这样,那就是问题所在。我需要整合x
    • 其实就是将x-1整合到+1。 (请参阅此处的quad 文档)[docs.scipy.org/doc/scipy/reference/generated/…。被积函数在我的回答中是错误的,现在我修复了它,它给出了 c 的预期结果...
    猜你喜欢
    • 1970-01-01
    • 2015-05-24
    • 2021-06-09
    • 2019-11-15
    • 2018-04-22
    • 2015-10-16
    • 2012-06-23
    • 1970-01-01
    • 2021-03-07
    相关资源
    最近更新 更多