I have managed to construct code for randomly generating a set partition of size n with k parts. Note that the total number of such objects is counted by a Stirling number of the second kind.
The code is very simple; there are two cases for the largest entry n
. Either it is in its own block, or not. It is easy to compute the probability for the first case,
and then one uses recursion.
RandomSetPartition[0, k_Integer] := Which[k == 0, {{}}, {}];
RandomSetPartition[1, k_Integer] := Which[k == 1, {{1}}, {}];
RandomSetPartition[n_Integer, 1] := {Range@n};
RandomSetPartition[n_Integer, n_Integer] := List /@ (Range@n);
RandomSetPartition[n_Integer, k_Integer] := If[
RandomReal[] <= StirlingS2[n - 1, k - 1]/StirlingS2[n, k],
Append[RandomSetPartition[n - 1, k - 1], {n}],
MapAt[Append[#, n] &, RandomSetPartition[n - 1, k],
RandomInteger[{1, k}]]
];
The issue is, the code is rather slow for large arguments, say RandomSetPartition[1000,30]
takes about 2 seconds on my machine.
I am not sure what the issue with my code is; the complexity should be O(n),
but some tests indicate the complexity is higher for my code.
What can I change to make it more efficient?
Which
do not work, but you do not need them. $\endgroup$