2017-07-13 7 views
0

私はMatlabのforループをベクトル化しようとしてきました。プログラム全体にボトルネックがあるからですが、ループの中の単一の行列の異なる行や列を反復処理するときはどうすればよいか分かりません。ここでは、コードがあります:同じ行列/配列の異なるインデックス上で操作するためにネストされたforループをベクトル化する方法はありますか?

// X is an n*k matrix, W is n*n 
// W(i,j) stores the norm of the vector resulting from subtracting 
// the j-th line of X from its i-th line. 
for i = 1:n 
    for j = 1:n 
     W(i,j) = norm(X(i,:) - X(j,:)) 
    end 
end 

編集:

それは私と私のアルゴリズムの背後にある数学的な考え方に近いです1のための最も便利だったと私はルイス・Mendoの答えを選んだ、まだすべての3つの答えが正しかったとMATLAB Toolboxやコード作成の方法によって、最も便利なものを使用することをお勧めします。

また、インデックスを格納する配列を使用したり、現在の配列を再構成したり、もう1つの次元を使用して、すべての回答の共通点が異なる形式を使用していたことに気付きました... あなたが似たような問題を抱えている場合、探検するのに適切なこと。

+0

あなたはすでに内部をvectoriseしようとしたことがありループのみ? – m7913d

答えて

0
  • あなたはStatistics Toolboxのを持っている場合は、pdistを使用しない:

    W = squareform(pdist(X)); 
    
  • ませツールボックス:古き良きbsxfun

    W = sqrt(sum(bsxfun(@minus, permute(X, [1 3 2]), permute(X, [3 1 2])).^2, 3)); 
    
2

使用コンビナトリー:ここ

% sample data 
X = randi(9,5,4); 
n = size(X,1); 

% row index combinations 
combIdx = combvec(1:n,1:n); 
% difference between row combinations 
D = X(combIdx(1,:),:)-X(combIdx(2,:),:); 
% norm of each row 
W = diag(sqrt(D*D')); 
% reshape 
W = reshape(W,n,[]); 
1

は大きな行列に対して、より効率的かもしれ別のソリューションです。あなたができる簡単な使用

W = sqrt(sum(abs(reshape(X,n,1,k) - reshape(X,1,n,k)).^2,3)) 

(あなたの配列が実数値である場合にも腹筋をスキップすることができます)のMatlab> = R2016については

。 Matlabの以前のバージョンのあなたには、いくつかのrepmatの魔法を追加する必要があり、すなわちの場合:

W = sqrt(sum(abs(repmat(reshape(X,n,1,k),[1,n,1]) - repmat(reshape(X,1,n,k),[n,1,1])).^2,3)); 

P.S:R2017bは、それがさらに便利になるかもしれない、少なくともrelease notes多少醜いsqrt(sum(abs(.).^2)))ものを置き換えることができvecnormと呼ばれる機能を言及。しかし、ドキュメンテーションはまだ上手くいかないので、私は正確に何ができるのか分からない。 「

関連する問題