【问题标题】:vectorizing 4 nested for-loops in Matlab在 Matlab 中向量化 4 个嵌套的 for 循环
【发布时间】:2011-09-16 13:44:57
【问题描述】:

我正在为学校编写一个程序,我有嵌套的 for 循环创建一个 4 维数组(坐标为 (x,y) 和 (x',y') 的两点之间的距离),如下所示:

pos_x=1:20;
pos_y=1:20;
Lx = length(pos_x);             
Ly = length(pos_y);
Lx2 = Lx/2;
Ly2 = Ly/2;

%Distance function, periodic boundary conditions
d_x=abs(repmat(1:Lx,Lx,1)-repmat((1:Lx)',1,Lx));
d_x(d_x>Lx2)=Lx-d_x(d_x>Lx2);
d_y=abs(repmat(1:Ly,Ly,1)-repmat((1:Ly)',1,Ly)); 
d_y(d_y>Ly2)=Ly-d_y(d_y>Ly2);

for l=1:Ly
    for k=1:Lx
        for j=1:Ly
            for i=1:Lx
            distance(l,k,j,i)=sqrt(d_x(k,i).^2+d_y(l,j).^2);
            end
        end
    end
end

d_x 和 d_y 只是 20x20 矩阵,Lx=Ly 用于试验目的。它非常缓慢,显然不是一种非常优雅的方式。我尝试对嵌套循环进行矢量化,并成功摆脱了两个内部循环:

dx2=zeros(Ly,Lx,Ly,Lx);
dy2=zeros(Ly,Lx,Ly,Lx);
distance=zeros(Ly,Lx,Ly,Lx);

for l=1:Ly
    for k=1:Lx
        dy2(l,k,:,:)=repmat(d_y(l,:),Ly,1);
        dx2(l,k,:,:)=repmat(d_x(k,:)',1,Lx);
    end
end
distance=sqrt(dx2.^2+dy2.^2);

它基本上取代了上面的 4 个 for 循环。我现在已经尝试了 2 天,但我找不到一种方法来矢量化所有循环。我想问:

  1. 是否有可能真正摆脱这两个循环
  2. 如果是这样,我将不胜感激任何提示和技巧。 到目前为止,我已经尝试在 4 维中再次使用 repmat,但是您不能转置 4 维矩阵,所以我尝试在许多不同的组合中一起使用 permute 和 repmat,但无济于事。

任何建议将不胜感激。


感谢您的回复。抱歉措辞不好,我基本上想要的是在 x-y 平面上统一放置一组振荡器。我想模拟它们的耦合,耦合函数是每个振荡器之间距离的函数。每个振荡器都有一个 x 和 ay 坐标,所以我需要找到 osci(1,1)osci(1,1),..osci(1,N),osci(2,1),..osci(N,N)... 之间的距离,然后对于 osci(1,2)osci(1,1)...osci(N,N) 等等。(所以基本上是所有振荡器之间的距离和所有其他振荡器加上自耦合)如果有比使用 4-D 阵列更简单的方法,我也肯定想知道它..

【问题讨论】:

  • 你说要两组坐标之间的距离。那不应该给你一个二维数组,其中元素(i,j)[x1i,y1i][x2i,y2i] 之间的距离吗?
  • 我赞同乔纳斯的评论。你能解释计算 [x1i,y2j] 和 [x1k,y2l] 之间距离的基本原理吗?如果您提供原因,则可能有一条捷径可以在不填充 4D 矩阵的情况下获得该答案。
  • 感谢您的回复。抱歉措辞不好,我基本上想要的是在 x-y 平面上统一放置一组振荡器。我想模拟它们的耦合,耦合函数是每个振荡器之间距离的函数。每个振荡器都有一个 x 和 ay 坐标,所以我需要找到 osci(1,1) 和 osci(1,1),..osci(1,N),osci(2,1),.. 之间的距离osci(N,N).. 然后 osci(1,2) 和 osci(1,1)...osci(N,N) 等等.. (所以基本上所有振荡器和所有振荡器之间的距离其他振荡器加上自耦合)如果有 ea
  • 我没有读过你的代码,但我有预感它类似于this question。您可能想尝试查看那里的答案,看看是否有帮助。

标签: matlab nested-loops


【解决方案1】:

如果我理解正确的话,你到处都有振荡器,就像这样:

然后你想计算振荡器 1 和振荡器 1 到 100 之间的距离,然后是振荡器 2 和振荡器 1 到 100 之间的距离等。我相信这可以用二维距离矩阵表示,如果第一个维度来自1 到 100,第二维从 1 到 100。

例如

%# create 100 evenly spaced oscillators
[xOscillator,yOscillator] = ndgrid(1:10,1:10); 
oscillatorXY = [xOscillator(:),yOscillator(:)];

%# calculate the euclidean distance between the oscillators
xDistance = abs(bsxfun(@minus,oscillatorXY(:,1),oscillatorXY(:,1)')); %'# abs distance x
xDistance(xDistance>5) = 10-xDistance; %# add periodic boundary conditions
yDistance = abs(bsxfun(@minus,oscillatorXY(:,2),oscillatorXY(:,2)')); %'# abs distance y
yDistance(yDistance>5) = 10-yDistance; %# add periodic boundary conditions

%# and we get the Euclidean distance
euclideanDistance = sqrt(xDistance.^2 + yDistance.^2);

【讨论】:

    【解决方案2】:

    我发现虚数有时可以帮助很好地传达耦合信息,同时减少混乱。我的方法将使必要的计算次数增加一倍(即我找到距离 X 和 Y 然后是 Y 和 X),我仍然需要一个 for 循环

    x = 1:20;
    y = 1:20;
    [X,Y] = meshgrid(x,y);
    Z =X + Y*i;
    z = Z(:);
    leng = length(z);
    store = zeros(leng);
    for looper = 1:(leng-1) 
        dummyz = circshift(z,looper);
        store(:,looper+1) = z - dummyz;
    end
    final = abs(store);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-03
      相关资源
      最近更新 更多