优化 Mathematica 中的内循环计算

发布于 2024-09-09 02:39:46 字数 718 浏览 2 评论 0原文

我目前正在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凉月流沐 2024-09-16 02:39:46

似乎用余弦变换交换傅里叶变换是错误的优化时间,因为它隐藏了这样一个事实:该相关性计算实际上只是两个傅里叶变换的乘积(这是我所知道的计算相关性的唯一有效方法) .
使用 ir1=Angle[i] r1ir2=Angle[j] r2 你的表达式相当于

Sum[Cos[f[x1, x2] ir1 + f[y1, y2] ir2], {x1, HL}, {x2, HL}, {y1, HL+1, 2 HL}, {y2, HL+1, 2 HL}]
== Re@Sum[Exp[I f[x1, x2] ir1] Exp[I f[y1, y2] ir2], {x1, HL}, {x2, HL},{y1, HL+1, 2 HL}, {y2, HL+1, 2 HL}]
== Re[corr1[ir1] corr2[ir2]]

corr1[ir_]:=Sum[Exp[I f[x1, x2] ir], {x1, HL}, {x2, HL}];
corr2[ir_]:=Sum[Exp[I f[y1, y2] ir], {y1, HL+1, 2 HL}, {y2, HL+1, 2 HL}];

已经将你的缩放指数减半,我希望你很高兴:),但如果 f 是实值,您可以削减另一个指数的两倍:
在这种情况下,我们可以将 corr1 表示为 f 值的积分 - 假设您可以以某种方式获得权重函数 w 。如果没有别的事,您可以通过简单的分箱过程以数字方式完成此操作。

corr1v2[ir_]:=Sum[ w[fval] Exp[I fval ir], {fval,fvals}],

这清楚地表明,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 and ir2=Angle[j] r2 your expression is equivalent to

Sum[Cos[f[x1, x2] ir1 + f[y1, y2] ir2], {x1, HL}, {x2, HL}, {y1, HL+1, 2 HL}, {y2, HL+1, 2 HL}]
== Re@Sum[Exp[I f[x1, x2] ir1] Exp[I f[y1, y2] ir2], {x1, HL}, {x2, HL},{y1, HL+1, 2 HL}, {y2, HL+1, 2 HL}]
== Re[corr1[ir1] corr2[ir2]]

where

corr1[ir_]:=Sum[Exp[I f[x1, x2] ir], {x1, HL}, {x2, HL}];
corr2[ir_]:=Sum[Exp[I f[y1, y2] ir], {y1, HL+1, 2 HL}, {y2, HL+1, 2 HL}];

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 of f -- given that you can somehow get at the weight function w. If nothing else, you can do this numerically with a simple binning procedure.

corr1v2[ir_]:=Sum[ w[fval] Exp[I fval ir], {fval,fvals}],

which makes it clear that corr1 is really just the Fourier transform of the weight function of f (so you should compute it with FFT rather than the sum above). Same goes for corr2.
Alternatively, if f is not real-valued but has enough symmetry to allow you to reparameterize in a form so f only depends on one of the new parameters (say, r,phi), you will also cut down the corr1 integrals to one dimension, although it might not be a simple Fourier transform.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文