Python Mittag-Leffler函数的不稳定性

Python Mittag-Leffler函数的不稳定性,python,numpy,Python,Numpy,在尝试复制和帮助时,我遇到了一些我不理解的数值不稳定性: import numpy as np import matplotlib.pyplot as plt from scipy.special import gamma def MLf(z, a): """Mittag-Leffler function """ k = np.arange(100).reshape(-1, 1) E = z**k / gamma(a*k + 1) return np.s

在尝试复制和帮助时,我遇到了一些我不理解的数值不稳定性:

import numpy as np
import matplotlib.pyplot as plt
from scipy.special import gamma

def MLf(z, a):
    """Mittag-Leffler function
    """
    k = np.arange(100).reshape(-1, 1)
    E = z**k / gamma(a*k + 1)
    return np.sum(E, axis=0)

x = np.arange(-50, 10, 0.1)

plt.figure(figsize=(10,5))
for i in range(5):
    plt.plot(x, MLf(x, i), label="alpha = "+str(i))
plt.legend()
plt.ylim(-5, 5); plt.xlim(-55, 15); plt.grid()
您可以在橙色线中看到不稳定性最好,其中
a=1
,从大约
x=-35
开始,但是
a=0
(蓝色线)也有问题。更改要求和的项数(即
j
)会更改发生不稳定性的
x

发生什么事了?我怎样才能避免这种情况


如果a=0,您使用的MLf系列定义仅在| z | 1或全部(z>0)时适用: k=np.arange(100) 返回np.多项式.多项式.polyval(z,1/伽马(a*k+1)) #一个棘手案件的帮手,来自Gorenflo、Loutchko和Luchko 定义MLf(z,a): 如果z<0: f=λx:(np.exp(-x*(-z)**(1/a))*x**(a-1)*np.sin(np.pi*a) /(x**(2*a)+2*x**a*np.cos(np.pi*a)+1) 返回1/np.pi*quad(f,0,np.inf)[0] elif z==0: 返回1 其他: 返回MLf(z,a) 返回np.vectorize(_MLf)(z,a) x=np.arange(-50,10,0.1) plt.图(figsize=(10,5)) 对于范围(1,5)内的i: plt.plot(x,MLf(x,i/3),label=“alpha=”+str(i/3)) plt.legend() plt.ylim(-5,5);plt.xlim(-55,15);plt.grid() 这里没有数字问题


有趣。。。我很惊讶其他曲线看起来很好(a=0的例外情况比a=1的情况更失败)。我猜高阶粒子不会表现出奇怪的行为,因为它们收敛得很快(分母增长得很快)。遗憾的是,我没有比为`a={0,1}'的情况找到一种显示更好稳定性的替代表示法更好的建议。对于数学来说,一个好的表达方式并不一定是一个好的计算方式。是的,这很有趣!我尝试了使用
gammaln
的对数空间表示法,并将偶数和奇数分开,但a=1的曲线更糟糕。可能有一个很好的理由,但我无法理解。对于0np.polymonel.polyval(-z**a,1/gamma(a*k+1))
k = np.arange(100)
return np.polynomial.polynomial.polyval(z, 1/gamma(a*k + 1))
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import gamma
from scipy.integrate import quad

def MLf(z, a):
    """Mittag-Leffler function
    """
    z = np.atleast_1d(z)
    if a == 0:
        return 1/(1 - z)
    elif a == 1:
        return np.exp(z)
    elif a > 1 or all(z > 0):
        k = np.arange(100)
        return np.polynomial.polynomial.polyval(z, 1/gamma(a*k + 1))

    # a helper for tricky case, from Gorenflo, Loutchko & Luchko
    def _MLf(z, a):
        if z < 0:
            f = lambda x: (np.exp(-x*(-z)**(1/a)) * x**(a-1)*np.sin(np.pi*a)
                          / (x**(2*a) + 2*x**a*np.cos(np.pi*a) + 1))
            return 1/np.pi * quad(f, 0, np.inf)[0]
        elif z == 0:
            return 1
        else:
            return MLf(z, a)
    return np.vectorize(_MLf)(z, a)


x = np.arange(-50, 10, 0.1)

plt.figure(figsize=(10,5))
for i in range(1, 5):
    plt.plot(x, MLf(x, i/3), label="alpha = "+str(i/3))
plt.legend()
plt.ylim(-5, 5); plt.xlim(-55, 15); plt.grid()