2014-08-28 109 views
1

我正在寻找一种有效的方法来计算大小坐标矩阵(nodeCount x 2)中所有点之间使用MATLAB的成对距离。我不希望两次计算配对距离(例如,在节点1-2和节点2-1之间)。我构建了一个外部'for'循环,该循环通过每个节点增加一个内部循环,该循环仅评估更高索引号的节点。结果是由节点分隔距离填充的上三角矩阵。我想对这些计算进行向量化,或者至少提高此操作的效率。任何帮助,将不胜感激。向量化依赖嵌套循环

gap = 10; 

for s = 1:(nodeCount); 
    for ss = s+1:(nodeCount); 
    if abs(nodeCoord(s,1)-nodeCoord(ss,1)) < gap; 
     sep(s,ss) = sqrt((nodeCoord(s,1)-nodeCoord(ss,1))^2+(nodeCoord(s,2)-nodeCoord(ss,2))^2); 
    end 
    end 
end 
+0

很想看看这里发布的解决方案如何在效率方面为您服务! – Divakar 2014-08-28 14:36:48

+0

大家好,非常感谢您的评论!我修改了我的原始代码来显示一个技巧,我正在使用它来加快计算速度,为我的应用程序。我最感兴趣的是计算由变量“间隙”定义的彼此之间的一定距离内的节点对之间的距离。我在代码中添加了一个额外的屏幕,它可以过滤掉比'x'方向上的间隙更远的节点坐标,所以我进一步减少了计算时间和内存需求。我正在处理数以千计的节点,这个代码是瓶颈。 – 2014-08-28 14:48:48

+0

你是否预先分配'sep'为零?我在问,因为如果条件 - 如果abs(nodeCoord(s,1)-nodeCoord(ss,1)) Divakar 2014-08-28 16:08:26

回答

1

该循环不是真正依赖的持久性。我想你想找到的所有其他坐标的距离试试这个:

xCoord = [1;2;3;4;5]; 
yCoord = [1;2;3;4;5]: 
xSquare = bsxfun(@(x,y) power((x-y),2),xCoord,xCoord.'); 
ySquare = bsxfun(@(x,y) power((x-y),2),yCoord,yCoord.'); 
dist = sqrt(xSquare+ySquare); 
+0

感谢您的答复。这段代码似乎比我构建的代码慢,而且内存不足(我正在笔记本上运行,并且有大约50,000个节点对)。 – 2014-08-28 14:40:00

1

而不是试图用事实不需要的下三角元素,因为它们是在输出零,我觉得你是最好使用基于这个very smart solution中讨论的快速矩阵乘法的技术来获得欧几里德距离的完整矩阵。为了得到上三角矩阵的所需输出,可以用triu来包装输出。

接下来的代码是稍微修改后的代码,我们正在计算nodeCoord同一对坐标之间的距离。

代码

numA = size(nodeCoord,1); 
helpA = ones(numA,6); 
helpB = ones(numA,6); 
for idx = 1:2 
    sqA_idx = nodeCoord(:,idx).^2; 
    helpA(:,3*idx-1:3*idx) = [-2*nodeCoord(:,idx), sqA_idx ]; 
    helpB(:,3*idx-2:3*idx-1) = [sqA_idx , nodeCoord(:,idx)]; 
end 
sep = triu(sqrt(helpA(:,1:3) * helpB(:,1:3)')<gap).* sqrt(helpA * helpB'); 
1
xCoord = [1;2;3;4;5]; 
yCoord = [1;2;3;4;5]; 

dist = sqrt(pdist2(xCoord,yCoord,'euclidean')); 

可以使用函数pdist2

+0

谢谢! pdist2实际上比我的代码慢,大概是因为每对之间的距离计算两次。 – 2014-08-28 14:36:59

0

pdist(nodeCoord)做它在一个快速的方式,但在矢量返回数据。将它映射回矩阵的时间与计算距离大致相同:

sep3=zeros(nodeCount,nodeCount); 
sep3(tril(true(nodeCount),-1))=pdist(nodeCoord); 
sep3=sep3+sep3.'; 

如果您对下三角矩阵感到满意,则可以省略最后一行。