2011-11-29 72 views
0

爲尷尬的標題道歉,這裏是一個更具體的問題描述。我有一個大的(例如10^6×10^6)稀疏對稱矩陣,它定義了節點之間的鍵。MATLAB - 使用其他(稀疏)矩陣中的信息填充矩陣的高效方法?

例如矩陣A = [0 1 0 0 0; 1 0 0 2 3; 0 0 0 4 0; 0 2 4 0 5; 0 3 0 5 0]將描述一個5節點系統,使得節點1和2被鍵數A(1,2) = 1,節點3和4通過鍵數A(3,4) = 4連接等

欲形成兩個新的矩陣連接。第一個B將列出連接到每個節點的節點(即,如果需要,B的每一行i具有由find(A(i,:))給出的元素並且在末尾用零填充),並且第二個C將列出連接到該節點的鍵(即C的每一行i有由nonzeros(A(i,:))給出的元素,如果需要再次填充)。

例如對於上面的矩陣A,我希望以形成B = [2 0 0; 1 4 5; 4 0 0; 2 3 5; 2 4 0]C = [1 0 0; 1 2 3; 4 0 0; 2 4 5; 3 5 0]

當前的代碼是:

B=zeros(length(A), max(sum(spones(A)))) 
C=zeros(length(A), max(sum(spones(A)))) 
for i=1:length(A) 
    B(i,1:length(find(A(i,:)))) = find(A(i,:)); 
    C(i,1:length(nonzeros(A(i,:)))) = nonzeros(A(i,:)); 
end 

其工作原理,但對於大的長度(A)慢。我嘗試了其他的配方,但它們都包含循環,並沒有太大的改進。

如何在不循環行的情況下執行此操作?

回答

0

嗯。不知道如何向量化(給出一個矩陣,這是不是你想要什麼,當find回報線性指數),但你嘗試過這樣的:

B=zeros(length(A), 0); 
C=zeros(length(A), 0); 
for i=1:length(A) 
    Bi = find(A(i,:)); 
    B(i,1:length(Bi)) = Bi; 
    Ci = nonzeros(A(i,:)); 
    C(i,1:length(Ci)) = Ci; 
end 

我做了兩個變化:

  • 除去調用spones(似乎沒有必要;需要的性能損失擴大的列#在B和C可能是最小的)
  • 查找()和非零(緩存的結果),所以他們不叫兩次
+0

sum(spones(A))之前在代碼中用於其他目的,所以重用它是有意義的。感謝您的緩存技巧。 – user1071878

0

我知道這很難閱讀,但這些代碼是你的代碼的向量化版本:

[ i j k ] = find(A); 
A2=(A~=0); 
j2=nonzeros(cumsum(A2,2).*A2); 
C2=accumarray([i,j2],k) 
k2=nonzeros(bsxfun(@times,1:size(A,2),A2)); 
B2=accumarray([i,j2],k2); 

試試吧,告訴我,如果你的作品。

+0

工程,可能會快很多,但是...'?錯誤使用==> cumsum 內存不足。爲您的選項鍵入HELP MEMORY。 ' – user1071878

+0

......所以也許你可以把小問題切成小塊......或者買一些內存,最近變得非常便宜:P – Oli