优化 Mathematica 中的内循环计算
我目前正在 Mathematica 中进行一些与量子力学相关的计算。随着我们从一维晶格模型转向二维晶格模型,问题大小变得有问题。
目前,我们有一个如下所示的求和:
corr[r1_, r2_, i_, j_] = Sum[Cos[f[x1, x2] Angle[i] r1 + f[y1, y2] Angle[j] r2], {x1, HL}, {x2, HL}, {y1, HL + 1, 2 HL}, {y2, HL + 1, 2 HL}];
f[. , .] 是预先计算的相关函数的查找函数,Angle[.] 也是预先计算的。
根本没有办法以任何方式进一步简化这个过程。我们已经通过将复指数(虚部为零)转换为上面的余弦表达式进行了简单的优化。
最大的问题是这些 HL 基于尺寸大小:对于沿轴的线性尺寸 L,HL 对应于 L^d(此处 d = 2)。所以我们的计算实际上是 O(n^8),忽略 i, j 的总和。
对于 L = 8,这通常不会太糟糕,如果不是因为我们对 125 个 r1 值和 125 个 r2 值进行迭代以创建 125 x 125 图像。
我的问题是:如何在 Mathematica 中最有效地计算它?我会用另一种语言来做这件事,但如果我用 C++ 之类的语言尝试的话,有些问题会让它变得同样慢。
额外信息:这是 ND-ND(数密度)相关性计算。所有 x 和 y 均指离散 2D 网格上的离散点。这里唯一的非离散的东西是我们的 r 。
I'm currently doing some computation in Mathematica related to Quantum Mechanics. As we've moved from a 1D to 2D lattice model, the problem size is becoming problematic
Currently, we have a summation that looks something like this:
corr[r1_, r2_, i_, j_] = Sum[Cos[f[x1, x2] Angle[i] r1 + f[y1, y2] Angle[j] r2], {x1, HL}, {x2, HL}, {y1, HL + 1, 2 HL}, {y2, HL + 1, 2 HL}];
f[. , .] is a lookup function for a pre-computed correlation function, and Angle[.] is precomputed as well.
There's no way at all to simplify this further in any way. We already took a simple optimization by converting a complex exponential (which had zero imaginary part) to the cosine expression above.
The big problem is that those HL's are based on dimension size: For linear dimension L along an axis, HL corresponds to L^d (d = 2 here). So our computation is O(n^8) in reality, neglecting the sum over i, j.
This normally isn't too bad for L = 8, if it weren't for the fact that we iterate this for 125 values of r1, and 125 of r2 to create an 125 x 125 image.
My question is: How can I most efficiently calculate this in Mathematica? I would do this in another language but there are certain problems that will make it just as slow if I tried it in something like C++.
Extra info: This is a ND-ND (number density) correlation calculation. All of the x's and y's refer to discete points on a discrete 2D grid. The only non-discrete thing here is our r's.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
似乎用余弦变换交换傅里叶变换是错误的优化时间,因为它隐藏了这样一个事实:该相关性计算实际上只是两个傅里叶变换的乘积(这是我所知道的计算相关性的唯一有效方法) .
使用
ir1=Angle[i] r1
和ir2=Angle[j] r2
你的表达式相当于我
已经将你的缩放指数减半,我希望你很高兴:),但如果
f
是实值,您可以削减另一个指数的两倍:在这种情况下,我们可以将
corr1
表示为f
值的积分 - 假设您可以以某种方式获得权重函数w
。如果没有别的事,您可以通过简单的分箱过程以数字方式完成此操作。这清楚地表明,corr1实际上只是f的权重函数的傅立叶变换(因此您应该使用FFT而不是上面的总和来计算它)。
corr2
也是如此。或者,如果
f
不是实值,但具有足够的对称性,允许您以某种形式重新参数化,因此f
仅取决于新参数之一(例如,f
>r,phi
),您还将把corr1
积分减少到一维,尽管它可能不是简单的傅里叶变换。It seems that swapping the Fourier transform with a Cosine transform was the wrong time to optimize, as it hides the fact that this correlation calculation is really just a product of two Fourier transforms (which is the only efficient way to calculate correlations I know of).
With
ir1=Angle[i] r1
andir2=Angle[j] r2
your expression is equivalent towhere
As I have already cut your scaling exponent in half, I expect you are happy :), but if
f
is real-valued, you can cut another factor of two of the exponent:In this case, we can express
corr1
as an integral over the values off
-- given that you can somehow get at the weight functionw
. If nothing else, you can do this numerically with a simple binning procedure.which makes it clear that
corr1
is really just the Fourier transform of the weight function off
(so you should compute it with FFT rather than the sum above). Same goes forcorr2
.Alternatively, if
f
is not real-valued but has enough symmetry to allow you to reparameterize in a form sof
only depends on one of the new parameters (say,r
,phi
), you will also cut down thecorr1
integrals to one dimension, although it might not be a simple Fourier transform.