Introduction
I would like to enumerate the 1-factors, or (near-)perfect matchings, of the complete graph Kn. The adjacency list representation for Kn is basically { (x, y) | 1 ≤ x < y ≤ n }.
For example, in the case of K3 = {{1, 2}, {1, 3}, {2, 3}}
, the near-perfect matchings would be
{{{1, 2}}, {{1, 3}}, {{2, 3}}}
. For K4 = {{1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}}
, the perfect matchings would be
{{{1, 2}, {3, 4}}, {{1, 3}, {2, 4}}, {{1, 4}, {2, 3}}}
.
Here's a nifty little illustration of this inspired by an example from the documentation:
The number of 1-factors of Kn is given by the odd double factorial: n!! if n is odd, and (n – 1)!! if n is even. See how this function grows (as the even double factorial) compared to n! below:
n 1 2 3 4 5 6 7 8 9 10
n!! 1 1 3 3 15 15 105 105 945 945
n! 1 2 6 24 120 720 5040 40320 362880 3628800
n!/n!! 1 2 2 8 8 48 48 384 384 3840
(For the sake of brevity, I am ignoring parity when using the n!! notation in the row headers.)
Attempt
My current solution generates the n! permutations, partitions each into pairs, and filters them.
p[n_] := Partition[#, 2] & /@ Permutations[Range[n]];
one[p_] := Select[p, OrderedQ @ # && And @@ OrderedQ /@ # &];
two[p_] := Select[p, # === Intersection@(Intersection /@ #) &];
Solution one
filters the permutations by requiring each element and each of its contents be sorted.
Solution two
does the same thing by exploiting the fact that order is ignored in sets.
The first solution can be a magnitude faster than the second solution:
With[{n = 9}, TableForm[Table[
With[{ptemp = p[i]},
tone = one@ptemp // Timing // First;
ttwo = two@ptemp // Timing // First;
{tone, ttwo, ttwo/tone}]
, {i, n}],
TableHeadings -> {Range[n], {"one", "two", "one faster by"}}]]
one two one faster by
1 0.000017 0.000011 0.6
2 0.000013 0.000019 1.
3 0.000025 0.000037 1.5
4 0.000066 0.000186 2.8
5 0.000520 0.001044 2.01
6 0.001274 0.007714 6.05
7 0.010958 0.047812 4.363
8 0.065019 0.446901 6.873
9 0.572954 3.941633 6.8795
Question
How can achieve this without doing n!! times as much work generating all the permutations?
Permutations[n]
toPermutations[Range[n]]
, which I believe does not requireCombinatorica`
. $\endgroup$