在Matlab中计算一个复杂的和

在Matlab中计算一个复杂的和,matlab,sum,Matlab,Sum,使用以下变量: m = 1:4; n = 1:32; phi = linspace(0, 2*pi, 100); theta = linspace(-pi, pi, 50); S_mn = <a 4x32 coefficient matrix, corresponding to m and n>; 但这需要θ和φ与m和n的元素数相同,并且它只给了我一个元素作为回报-我想要一个矩阵,大小等于网格(θ,φ),而不管θ和φ的大小如何(即,我希望能够将总和作为theta和phi的函数进行

使用以下变量:

m = 1:4; n = 1:32;
phi = linspace(0, 2*pi, 100);
theta = linspace(-pi, pi, 50);

S_mn = <a 4x32 coefficient matrix, corresponding to m and n>;
但这需要θ和φ与m和n的元素数相同,并且它只给了我一个元素作为回报-我想要一个矩阵,大小等于网格(θ,φ),而不管θ和φ的大小如何(即,我希望能够将总和作为
theta
phi
的函数进行计算)


如何在matlab中进行此计算?

因为我不知道S是什么

S = randn(4,32);

[m,n] = ndgrid(1:4,1:32);
fun = @(theta,phi) sum(sum(S.*exp(sqrt(-1)*(m*theta + n*phi))));
对我来说很好

fun(pi,3*pi/2)
ans =
          -15.8643373238676 -      1.45785698818839i
如果您现在希望对一组较大的值phi和θ执行此操作,则一对循环现在是简单的解决方案。或者,您可以在一次计算中完成所有操作,尽管数组将变大。仍然不难。WTP

您确实意识到meshgrid和ndgrid都需要不止两个参数吗?因此,现在是学习如何使用bsxfun,然后挤压的时候了

[m,n,theta,phi] = ndgrid(1:4,1:32,linspace(-pi, pi, 50),linspace(0, 2*pi, 100));
res = bsxfun(@times,S,exp(sqrt(-1)*(m.*theta + n.*phi)));
res = squeeze(sum(sum(res,1),2));
或者这样做,速度会快一点。上一次计算花了我的机器0.07秒。最后一次计算花了0.05秒,所以大量使用bsxfun可以节省一些成本

m = (1:4)';
n = 1:32;
[theta,phi] = ndgrid(linspace(-pi, pi, 50),linspace(0, 2*pi, 100));
theta = reshape(theta,[1,1,size(theta)]);
phi = reshape(phi,size(theta));
res = bsxfun(@plus,bsxfun(@times,m,theta*sqrt(-1)),bsxfun(@times,n,phi*sqrt(-1)));
res = bsxfun(@times,S,exp(res));
res = squeeze(sum(sum(res,1),2));

如果您需要执行上述2000次,那么应该需要100秒。WTP?喝点咖啡放松一下。

首先保存每个变量的大小:

size_m = size(m);
size_n = size(n);
size_theta = size(theta);
size_phi = size(phi);
使用如下函数:

[theta, phi, m, n] = ngrid(theta, phi, m, n)
S_tpmn = repmat(S_mn, [size_theta size_phi size_m size_n]);
aux_sum = S_tpmn.*exp(1i*(m.*theta + n.*phi));
这将为您提供一个4维数组(每个变量一个:θ、φ、m、n)。现在您可以计算:

m.*theta + n.*phi
现在需要使S_mn有4个维度,大小为size_theta,size_phi,size_m,size_n,如下所示:

[theta, phi, m, n] = ngrid(theta, phi, m, n)
S_tpmn = repmat(S_mn, [size_theta size_phi size_m size_n]);
aux_sum = S_tpmn.*exp(1i*(m.*theta + n.*phi));
现在你可以这样计算你的总和:

[theta, phi, m, n] = ngrid(theta, phi, m, n)
S_tpmn = repmat(S_mn, [size_theta size_phi size_m size_n]);
aux_sum = S_tpmn.*exp(1i*(m.*theta + n.*phi));
最后,您可以沿最后两个维度(m和n)求和,以获得一个具有2个维度的数组,其大小为size_theta乘以size_phi:

final_sum = sum(sum(aux_sum, 4), 3);

注意:我现在没有访问Matlab的权限,所以我无法测试这是否有效。

有几种方法可以实现这一点

一种方法是创建一个函数(-handle),将总和作为θ和φ的函数返回,然后使用
arrayfun
进行总和计算。另一种方法是完全矢量化计算,尽管这将占用更多内存

arrayfun
版本:

[m, n] = meshgrid(m,n);

sumHandle = @(theta,phi)sum(reshape(...
    S_mn.*exp(1i(m*theta + n*phi)),...
    [],1)) 

[theta, phi] = meshgrid(theta,phi);

sumAsFunOfThetaPhi = arrayfun(sumHandle,theta,phi);
矢量化版本:

[m, n] = meshgrid(m,n);
m = permute(m(:),[2 4 1 3]); %# vector along dim 3
n = permute(n(:),[2 3 4 1]); %# vector along dim 4

S_mn = repmat( permute(S_mn,[3 4 1 2]), length(theta),length(phi));

theta = theta(:); %# vector along dim 1 (phi is along dim 2 b/c of linspace)

fullSum = S_mn.* exp( 1i*(...
    bsxfun(@plus,...
       bsxfun(@times, m, theta),...
       bsxfun(@times, n, phi),...
    )));

sumAsFunOfThetaPhi = sum(sum( fullSum, 3),4);

我将对整个范围[-pi,pi]x[0,2pi]内的
phi
theta
中的高分辨率进行此操作,用于2000个时间步。我需要比这更好的性能。也许如果你一开始就说了一些关于你的需求的话,将来可能会有所帮助?无论如何,仅仅希望计算机运行得更快是没有帮助的。这里有固定数量的倍数和加法,你的计算机只会以最快的速度处理它们。如果你需要更快的电脑,然后买一台。事实上,上面的计算是完全矢量化的,没有斜率。