2011-03-08 91 views
2

我一直在尝试对我的早期question进行Ghaul's answer关于导入上三角矩阵的一般导入。在MATLAB中对上三角矩阵进行一般导入

初始化数据:

1.0 3.32 -7.23 
1.00 0.60 
1.00 

A = importdata('A.txt') 

A = 

    1.0000 3.3200 -7.2300 
    1.0000 0.6000  NaN 
    1.0000  NaN  NaN 

所以,你将不得不在最后两行转移,像这样的:他们的对称同行

A(2,:) = circshift(A(2,:),[0 1]) 
A(3,:) = circshift(A(3,:),[0 2]) 

A = 

    1.0000 3.3200 -7.2300 
    NaN  1.0000 0.6000 
    NaN  NaN  1.0000 

然后更换的NaN:

A(isnan(A)) = A(isnan(A)') 

A = 

    1.0000 3.3200 -7.2300 
    3.3200 1.0000 0.6000 
    -7.2300 0.6000 1.0000 

我有这个,所以我们得到的完整矩阵的任何尺寸:

A = importdata('A.txt') 
for i = (1:size(A)-1) 
    A(i+1,:) = circshift(A(i+1,:),[0 i]); 
end 
A(isnan(A)) = A(isnan(A)'); 

是这种方法最好?必须有更好的东西。我记得有人告诉我尽量不要在MATLAB中使用for循环。

UPDATE
所以这就是结果。没有任何方法可以让它在没有循环的情况下变得更快?

A = importdata('A.txt') 
for i = (1:size(A)-1) 
    A(i+1,:) = circshift(A(i+1,:),[0 i]) 
end 
A(isnan(A)) = 0; 
A = A + triu(A, 1)'; 
+0

看到我更新的答案,我认为这应该工作。 – Ghaul 2011-03-08 15:55:45

回答

3

这是另一个适用于任何大小上三角矩阵的通用解决方案。它使用功能ROT90SPDIAGS,并TRIU

>> A = [1 3.32 -7.23; 1 0.6 nan; 1 nan nan]; %# Sample matrix 
>> A = spdiags(rot90(A),1-size(A,2):0);  %# Shift the rows 
>> A = A+triu(A,1).'       %'# Mirror around the main diagonal 

A = 

    1.0000 3.3200 -7.2300 
    3.3200 1.0000 0.6000 
    -7.2300 0.6000 1.0000 
2

这是一种没有循环的方法。如果你有一个更新的Matlab版本,你可能想要检查哪个解决方案真的更快,因为循环不像以前那么糟糕。

A = A'; %'# transpose so that linear indices get the right order 
out = tril(ones(size(A))); %# create an array of indices 
out(out>0) = A(~isnan(A)); %# overwrite the indices with the right number 
out = out + triu(out',1); %'# fix the upper half of the array 
+0

我有MATLAB 7.11.0(R2010b),所以你的解决方案更快,对吗?在MATLAB的低版本? – cMinor 2011-03-08 16:18:08

+2

@darkcminor:在MATLAB的旧版本中(我认为<2007年,但我可能会误),做循环代价非常高(因为MATLAB基本上一直在解释循环中的所有内容)。在更新的版本中,这不再是这种情况,因此新版本中性能增益可能更小或不存在(循环仍然导致大量函数调用,效率低下)。所以在大多数情况下矢量化代码仍然是有意义的。 – Egon 2011-03-08 16:28:21

+0

@darkcminor:我认为即使使用更新版本的Matlab,我的解决方案可能会更快(请参阅@ Egon的评论以获得很好的解释),但由于您不能简单地覆盖'A',因此需要更多内存。 – Jonas 2011-03-08 16:40:05