比较Mathematica和Python中的卷积

时间:2019-07-01 10:56:39

标签: python numpy wolfram-mathematica sympy convolution

我正在将Python(using sympy's symbolic variables)和Mathematica中的卷积结果与其Convolve函数进行比较。

在Python中,我的MWE是

from numpy import linspace, pi
from numpy.random import randn
from scipy.signal import fftconvolve
import matplotlib.pyplot as plt
from sympy import symbols
from sympy.utilities.lambdify import lambdify

a = 0.43
b = 0.41
c = 0.65
d = 0.71

x = symbols('x')
f = 2*b / ((x-a)**2 + b**2)
g = 2*d / ((x-c)**2 + d**2)
fog = fftconvolve(f,g,mode='same')
fog_fun = lambdify(x,fog,'numpy') # returns a numpy-ready function
x = linspace(-20,20,int(1e3))
dx = x[1]-x[0]
fogS = fog_fun(x)

fogA = 4*pi*(b+d)/((x-a-c)**2+(b+d)**2) # correct analytic solution

plt.figure()
plt.plot(x,fogA,lw=2,label='analytic')
plt.plot(x,fogS,lw=2,label='sympy')
plt.grid()
plt.legend(loc='best')
plt.show()

使用符号变量x计算卷积。生成的函数(在lambdifying之前)是

fog = 1.1644/(((x - 0.65)**2 + 0.5041)*((x - 0.43)**2 + 0.1681))

analyticfogA,Mathematica)和sympyfogS,Python)之间没有约定:

enter image description here

我的Mathematica代码是:

a = 0.43; b = 0.41; c = 0.65; d = 0.71;
fogA = FullSimplify[Convolve[2*b/((t-a)^2+b^2),2*d/((t-c)^2+d^2), t, x]];
fogS = 1.1644/(((x - 0.65)^2 + 0.5041)*((x - 0.43)^2 + 0.1681));

其中

fogA = (17.683+x*(-30.4006+14.0743*x))/(3.04149+x*(-7.9428+x*(8.3428+x*(-4.32+1.*x))))

fogSfogA的图形与Python的图形相同。

为什么analyticsympy解决方案之间有如此大的分歧?我怀疑问题出在sympy上。另一种Python方法是对两个 array 进行卷积,这似乎与analytic解决方案相符。

f = 2*b / ((x-a)**2 + b**2)
g = 2*d / ((x-c)**2 + d**2)
fogN = fftconvolve(f,g,mode='same')*dx # numeric

(注意:这是MWE。我要卷积的实际fg比本文中定义的洛伦兹定律复杂得多。)

1 个答案:

答案 0 :(得分:1)

我认为这不是使用scipy + sympy的合理方法。 实际上,您对lambdify的结果完全感到惊讶。

您应该做的是使用卷积的符号定义,而不是使用scipy.signal.fftconvolve(),例如:

from sympy import oo, Symbol, integrate

def convolve(f, g, t, lower=-oo, upper=oo):
    tau = Symbol('__very_unlikely_name__', real=True)
    return integrate(
        f.subs(t, tau) * g.subs(t, t - tau), (tau, lower, upper))

改编自here