我正在将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))
analytic
(fogA
,Mathematica)和sympy
(fogS
,Python)之间没有约定:
我的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))))
fogS
和fogA
的图形与Python的图形相同。
为什么analytic
和sympy
解决方案之间有如此大的分歧?我怀疑问题出在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。我要卷积的实际f
和g
比本文中定义的洛伦兹定律复杂得多。)
答案 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。