EDIT: To clarify, the bottleneck right now is available RAM, so any answer should keep that in mind (I cannot store all T!
lists of length T
and filter out those that satisfy the condition a posteriori.)
I want to find all permutations of the elements of Range[0,T-1]
that satisfy a condition, but where T
may be too large for Permutations
to be useable: first generating and storing all permutations simply consumes too much RAM. The condition is always such that cond = {c[1],c[2],...,c[T]}
means that the first element of the permutation must be larger than or equal to c[1]
, the second element must be larger than or equal to c[2]
etc. The condition is sorted in increasing order, and we can assume that the condition is not so strict that no permutations survive.
I have managed to implement what I want, but in a very procedural way using a recursive function (the details here are not that important):
recuPerm[level_] :=
If[level == 0,
res[[1]] = Total[avail];
Sow[res],
((res[[level + 1]] = #; avail[[First[#] + 1]] = 0;
recuPerm[level - 1];
avail[[
First[#] + 1]] = #) & /@ ({(allow[[level + 1]].avail)} /.
Plus -> Sequence));
]
and I call it from the wrapper function:
listPerm[T_, cond_] :=
Block[
{a, avail, allow, res = ConstantArray[1, T], rip},
avail = a /@ Range[0, T - 1];
allow =
Table[PadLeft[ConstantArray[1, T - cond[[i]]], T], {i,
T}];
rip = Reap[recuPerm[T - 1]][[2]];
If[rip == {}, {}, rip[[1]]]
]
(The dummy head a
is simply there so I can use Total
and Dot
in order to pick out allowed elements.)
Do you know of an approach that is more functional in nature and/or can better take advantage of the strengths of Mathematica? If it's more memory efficient (or faster) than my (unelegant) attempt then that's of course a bonus!
T
? $\endgroup$Total
has the same order of magnitude as T. Take for instanceT = 8
andcond = {0,1,2,2,3,3,4,5}
. Contrast this to no constraints,cond = ConstantArray[0,T]
, then anyperm
hasTotal[perm - cond] = T(T-1)/2
. $\endgroup$