2012-04-01 8 views
0

ためにネストする代わりに、現在の私の.mファイルは、私が50 すなわち{1、...、1,2,3から4つの要素のセットを生成しようとしています。このMatlabの、ループ

for a = 1 : 47 
    for b = a+1 : 48 
    for c = b+1 : 49 
    for d = c+1 : 50 
    fprintf('%d %d %d %d \n',a,b,c,d); 
    end 
    end 
    end 

のように見えます2,3,4}、{1,2,3,5}、... {1,2,3,50}、{1,2,4,5}、.. {47,48,49,50 }。したがって、合計でC(50,4)セットが存在する。これら4つのネストされたループよりも速い選択肢があるかどうかを知りたいですか? 1つのセット内の順序は必ずしも増加する順序ではない。すなわち、コードが{1,2,3,4}ではなく{4,1,2,3}を生成していればOKである。

+1

MATLABは、並列ループを有しています。 – Griffin

+0

私はN = 4:50の置換をparfor N = 4:50に置き換えようとしましたが、それはより遅くなることが判明しました。 – endeavour90

+2

'parfor'は' matlabpool'が設定されている場合にのみ並列化され、並列計算ツールボックスが必要です。実際の 'parfor'コマンドは、開発者がそのツールボックスなしで作業し、後で追加のツールボックスを使ってセッションに折り畳むことができるように、Matlabの一部です。 – Pursuit

答えて

0

コードの目的は、以下の条件を満たしているすべての可能な入力とSomeFunctionを呼び出すように記載することができるように見えます:

  1. < B < C < D
  2. D < = 50
  3. (Implied、A、B、C、Dは整数)

この場合、一番外側のループを削除することでもっと速くなります。つまり、for N = 1:50N = 50に置き換えます。そうであるように、あなたは同じ組み合わせを何度も呼びます。例えば、N = 4:6で最初の行を交換し、次の結果を返します(「*」EDラインが重複している):

A  B  C  D 
N=4 
1  2  3  4 

N=5 
1  2  3  4 * 
1  2  3  5 
1  2  4  5 
1  3  4  5 
2  3  4  5 

N=6 
1  2  3  4 * 
1  2  3  5 * 
1  2  3  6 
1  2  4  5 * 
1  2  4  6 
1  2  5  6 
1  3  4  5 * 
1  3  4  6 
1  3  5  6 
1  4  5  6 
2  3  4  5 * 
2  3  4  6 
2  3  5  6 
2  4  5  6 
3  4  5  6 
+0

それは私が思ったものです。外側ループを取り外し、N = 50に置き換えます。 – Pursuit

+0

Ok、N = 50としましょう。 私は、1,2,3、...から50までの4タプルの組み合わせを得る代わりに、forループを使用せずに (1 2 3 4)、(1 2 3 5)、...、(1 2 3 50)、(1 2 4 5)、...(47 48 49 50) – endeavour90

+1

私は清潔で美しい方法があると思う。 /私が1つを描く(または他の誰かが投稿するかもしれない)とき、この答えを更新します。私はより速い方法があるとは思わない。 – Pursuit

1

楽しい問題が!

すべての可能な組み合わせを列挙することは十分に検討されており、多くの解決策があります。例えばthis SO questionを参照してください。ここでNの合理的な選択のための簡単で効率的な解決策は、2つの便利なMATLAB関数、nchoosekとarrayfunを使用して、Kである:

% test function for benchmarking 
foo = @(a, b, c, d) (a + b + c + d); 

% see detailed timings at https://gist.github.com/2295957 
tic; 
C = nchoosek([1:50], 4);  % all 230,300 4-tuple combinations 
result = arrayfun(@(k) foo(C(k,1),C(k,2),C(k,3),C(k,4)), 1:length(C)); 
toc; 
+0

+1、エレガントな答え。私はあなたのタイミングに疑問を呈します。私はあなたのコードを6.4秒で実行し、元のコード(結果を230300X1のマトリックスに収めるように修正)を5.0秒で実行することができます。 (R2011a) – Pursuit

+0

@ Pursuitあなたのコミットメントに動機付けされた、より正確なベンチマークのためのテストストラップ(https://gist.github.com/2295957)を書きました。それは簡単ですが、私の最初の時間がオフであったことを確認します。新しいタイミングでは、ネストされたループが(適切に数えられる)ことが、最速の解決策であることが示唆されています(0.1232秒とR2011aセットアップの実行時間中央値2.62秒)。これは私には驚くべきことです。 –

+0

私は本当のテストデータが大好きです。ありがとう!私はあなたが桁違いに能力を発揮できたことに驚いていますが、ループが速いことは驚きではありません。Matlabは単純なループで非常に効率的です。単純なループは最小メモリ実装です。 arrayfunの呼び出しは特に高速ではなく、 'C 'の値を追跡するために多くのメモリを割り当てる必要があります。私がマイクロ最適化に入るとき、私はしばしばより単純なループとより少ないレベルの美しい呼び出しで終わる。しかし、あなたの答えは最初の質問に対処すると思います。うまくいけば、@ endeavour90はそれを受け入れるだろう。 – Pursuit