Como he indicado anteriormente, el uso de Compile
dará un código más rápido. Usando un algoritmo de fxtbook, el siguiente código genera una partición siguiente en orden lexicográfico:
PermutationIterator[f_, n_Integer?Positive, nextFunc_] :=
Module[{this = Range[n]},
While[this =!= {-1}, f[this]; this = nextFunc[n, this]];]
El código siguiente se supone que ejecutan la versión 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
];
Entonces
In[75]:= Reap[PermutationIterator[Sow, 4, cfNextPartition["C"]]][[2,
1]] === Permutations[Range[4]]
Out[75]= True
Este es claramente mejor en rendimiento que la función original 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}
El uso de la máquina virtual de Mathematica no es mucho más lento:
In[85]:= PermutationIterator[dummy, 9,
cfNextPartition["MVM"]] // Timing
Out[85]= {1.154, Null}
Por supuesto, esto no es en absoluto la aplicación del código C, sin embargo, proporciona una considerable aceleración sobre el código de nivel superior pura.
FWIW, la forma de hacer iteradores/generadores de Python es bastante inusual. Siempre que tenga algún tipo de abstracción sobre el estado (cierres, clases), puede implementarlos en cualquier lengua. – jrockway
Ah, lindo. Tal vez agregue eso como una respuesta a su propia pregunta (se considera bastante kosher hacer eso). ¿O todavía hay una pregunta sin respuesta aquí? – dreeves
Bueno, necesita pasar explícitamente sus funciones, mientras que el rendimiento de Python se lo imagina y lo hace encajar en el marco. Entonces, no es completamente perfecto. Pero lo suficientemente bueno, de hecho, lo uso ahora. – nes1983