【问题标题】:Comparing convolutions in Mathematica and Python比较 Mathematica 和 Python 中的卷积
【发布时间】:2019-07-01 19:11:17
【问题描述】:

我将 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)之间没有一致:

我的 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 上。另一种 Pythonic 方法是对两个 数组 进行卷积,这似乎与 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 比本文中定义的洛伦兹要复杂得多。)

【问题讨论】:

标签: python numpy wolfram-mathematica sympy convolution


【解决方案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

【讨论】:

  • 谢谢,这是一个有趣的解决方案。就速度而言,您的函数会评估卷积积分本身,所以这是最有效的方法吗?我特别选择使用 scipy 的 fftconvolve 而不是 numpy 的 convolve,因为我最终将处理大型数组(最多包含数百万个元素)。
  • @MedullaOblongata 一旦计算了卷积,它就不应该再包含积分的信息(这是耗时的部分)。但是,这可能会导致表达式过长。这样的表达式,在羔羊化之后,是否优于数值 fftconvolve 方法还有待证明。但是,当在您的代码中插入此代码时,我收到来自 sympy 的错误,指向 sympy 中的错误:github.com/sympy/sympy/issues/7999 ... 运气不好!
  • 您是否也收到raise PolynomialDivisionFailed(f, g, K) 错误?我使用 sympy v.1.3,错误信息是 PolynomialDivisionFailed: couldn't reduce degree in a polynomial division algorithm when dividing [...] by [...]. This can happen when it's not possible to detect zero in the coefficient domain. The domain of computation is RR[w,_t]. Zero detection is guaranteed in this coefficient domain. This may indicate a bug in SymPy or the domain is user defined and doesn't implement zero detection properly.
  • 您可以通过定义x = symbols('x', real=True) 来消除该错误,但您会得到另一个与上述问题相关的错误。您可以通过将 ad 定义为 symbols 来摆脱它们,此时我从昨天开始一直在等待 SymPy 找到解决方案……也许您应该尝试改用 Mathematica 结果。跨度>
猜你喜欢
  • 1970-01-01
  • 2013-06-08
  • 2018-05-06
  • 2019-08-07
  • 1970-01-01
  • 2021-04-05
  • 1970-01-01
  • 2015-04-06
  • 2018-11-11
相关资源
最近更新 更多