前述したように、Compile
を使用すると、より高速なコードが与えられます。 fxtbookからアルゴリズムを使用して、次のコードは、辞書式順序で次のパーティションを生成します。
PermutationIterator[f_, n_Integer?Positive, nextFunc_] :=
Module[{this = Range[n]},
While[this =!= {-1}, f[this]; this = nextFunc[n, this]];]
次のコードは、我々はバージョン8を実行する前提としています
ClearAll[cfNextPartition];
cfNextPartition[target : "MVM" | "C"] :=
cfNextPartition[target] =
Compile[{{n, _Integer}, {this, _Integer, 1}},
Module[{i = n, j = n, ni, next = this, r, s},
While[Part[next, --i] > Part[next, i + 1],
If[i == 1, i = 0; Break[]]];
If[i == 0, {-1}, ni = Part[next, i];
While[ni > Part[next, j], --j];
next[[i]] = Part[next, j]; next[[j]] = ni;
r = n; s = i + 1;
While[r > s, ni = Part[next, r]; next[[r]] = Part[next, s];
next[[s]] = ni; --r; ++s];
next
]], RuntimeOptions -> "Speed", CompilationTarget -> target
];
その後
In[75]:= Reap[PermutationIterator[Sow, 4, cfNextPartition["C"]]][[2,
1]] === Permutations[Range[4]]
Out[75]= True
を は
これはさ明らかに元のgen
機能よりもパフォーマンスが優れています。
In[83]:= gen[dummy, 9] // Timing
Out[83]= {26.067, Null}
In[84]:= PermutationIterator[dummy, 9, cfNextPartition["C"]] // Timing
Out[84]= {1.03, Null}
Mathematicaの仮想マシンを使用すると、はるかに遅いではありません。もちろん
In[85]:= PermutationIterator[dummy, 9,
cfNextPartition["MVM"]] // Timing
Out[85]= {1.154, Null}
これはCコードの実装の近くにどこにもない、まだ純粋なトップレベルのコードに比べて大幅スピードアップを提供します。
FWIW、Pythonのイテレータ/ジェネレータのやり方は、まれです。あなたが状態(クロージャ、クラス)を超えて何らかの抽象化を持っている限り、それらを任意の言語で実装することができます。 – jrockway
あ、いいね。たぶんあなた自身の質問への答えとしてそれを追加してください(それを行うにはかなり正直な考えです)。それともまだここに答えられていない質問がありますか? – dreeves
さて、あなたは関数を明示的に渡す必要がありますが、Pythonの収穫物はあなたのためにそれを理解し、フレームワークに適合させます。だから、それは完全ではありません。しかし、十分に良い、確かに、私は今それを使用します。 – nes1983