2014-10-02 171 views
6

我最近學會了如何向量化先前的question中的「簡單」嵌套循環。不過,現在我想也向量化下面的循環向量化一個嵌套循環,其中一個循環變量依賴於另一個循環變量

A=rand(80,80,10,6,8,8); 

I=rand(size(A1,3),1); 
C=rand(size(A1,4),1); 
B=rand(size(A1,5),1); 

for i=1:numel(I) 
    for v=1:numel(C) 
     for j=1:numel(B) 
      for k=1:j 
       A(:,:,i,v,j,k)= A(:,:,i,v,j,k)*I(i)*C(v)*B(j)*((k-1>0)+1);    
      end 
     end 
    end 
end 

所以現在k取決於在j ...什麼都我想到目前爲止: 的jk條款(即B(j)*((k-1>0)+1)的結合使三角矩陣我管理的獨立矢量化:

B2=tril([ones(8,1)*B']'); 
    B2(2:end,2:end)=2*B2(2:end,2:end); 

但是,這給我的(J,K)矩陣正確,而不是一種方法,用它來向量化剩餘的循環也許我在錯誤的道路了。 ..那麼我怎樣才能矢量化這種類型的循環?

回答

11

one of your comments到上一個問題的可接受的解決方案,你提到基於代碼的連續的bsxfun(@times,..,permute..)更快。如果是這種情況,你也可以在這裏使用類似的方法。這裏是使用這種模式的代碼tril -

B1 = tril(bsxfun(@times,B,[1 ones(1,numel(B)-1).*2])); 
v1 = bsxfun(@times,B1, permute(C,[3 2 1])); 
v2 = bsxfun(@times,v1, permute(I,[4 3 2 1])); 
A = bsxfun(@times,A, permute(v2,[5 6 4 3 1 2])); 
+0

太棒了!它更優雅,運行速度比@ natan的解決方案快25%。 – Max 2014-10-06 17:24:35

+0

@Max太棒了!很高興知道這一點! – Divakar 2014-10-06 17:30:45

+6

這個解決方案讓我想起[Ramanujan](https://en.wikipedia.org/wiki/Srinivasa_Ramanujan)。我完全不知道你是怎麼想出這個答案的。 – rayryeng 2015-11-25 22:22:06

2

你很近。你提出的矢量化確實遵循(j,k)邏輯,但是在循環未進入的地方做tril增加了零。針對您之前的問題(@ david's)使用解決方案並不完整,因爲它將所有元素相乘,包括循環未進入的這些零值元素。我對此的解決辦法,就是找到這些零個元素,並用1(很簡單)替換它們:

與您的代碼開始:

B2=tril([ones(8,1)*B']'); 
B2(2:end,2:end)=2*B2(2:end,2:end); 

,並按照上一題所示的矢量:

s=size(A); 
[b,c,d]=ndgrid(I,C,B2); 
F=b.*c.*d; 
F(F==0)=1; % this is the step that is important for your case. 
A=reshape(A,s(1),s(2),[]); 
A=bsxfun(@times,A,permute(F(:),[3 2 1])); 
A=reshape(A,s); 

對於A的問題所使用的尺寸這減少的運行時間,不差約50%......