2011-03-08 97 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