2013-12-10 6 views
5

bsxfunのような要素単位の操作を実行する方法はありますか?は疎行列の非ゼロ要素で動作しますか?特にspfunがbsxfunと出会う場所

、位置(i,j)におけるマトリックスAにおける各非ゼロ要素のI要素(i,j)を除いて、i行目の非零要素のすべての製品を検索します。例えば

i-th行はこのように見える場合:結果は次のようになります。

​​

0 12 20 0 0 15 0 0 

最も明白な解決策は、非の製品を取るように見えます各行に沿ってゼロ要素を計算し、各要素を列積から戻します。したがって、上記の例では、行の積は5 x 3 x 4 = 60であり、次にそれぞれの位置で534を除算します。疎行列A考える

が、これはこれまでのところ私の最高のソリューションです:

[M N] = size(A); 
[row col vals] = find(A); 
row_prod = accumarray(row,vals,[],@prod); 
B = bsxfun(@ldivide, A, row_prod); 
B = sparse(row,col,B(sub2ind([M N],row,col)),M,N); 

最初の3行は、私が欲しいものを達成:各行の非ゼロ要素の積を表す列ベクトルを。しかし、最後の2行にはかなりの問題があります。

  • bsxfunは、不必要にゼロ除算サイクルの多くを無駄になるだろうA
  • のサイズの非スパース行列を返すために起こっています。
  • 結果は、ほとんどがInfまたは-Infで構成されている行列です。ここで、実際にはゼロが欲しいです。
  • Matlabはゼロ時間無限大をNaNと定義しているので、Infをマスクすることはできません。
  • 弾丸を噛んで、for-loopを書くだけでいいですか?それともそれにアプローチする別の方法がありますか?

    答えて

    3

    私は上記の私の懸念のほとんどを解決する解決策を見つけたと思います。ときどき私が手に持っているハンマーがbsxfunになると、世界全体が釘のように見えるようになります。 bsxfunで行う単純な乗算のいくつかは、行列乗算を使用して簡単に(そしておそらくはより可読性良く)解くことができます。私はこの問題に対する私の解決策がそれ以上読めるとは思っていませんが、私の最後の解決策よりも効率的です。

    % 'This happens once, outside the loop, since the size' 
    % 'and sparsity structure of A dont change in the loop' 
    [M N] = size(A); 
    [row col] = find(A); 
    
    %% 'Inside iterative loop' 
    
        % 'Get the product of non-zero row elements' 
        row_prod = accumarray(row,nonzeros(A),[],@prod); 
    
        % 'Use row products to compute 'leave-one-out' row products' 
        B = spdiags(row_prod,0,M,M)*spfun(@(x) 1./x, A); 
    

    これが改善できる場合、私はまだ他の提案を聞くことに興味があります。

    関連する問題