Browse Source

Combinatorics: add a method for lexicographic generation of all possible subsets of a set.

pull/607/head
Daniel Sword 8 years ago
parent
commit
e1f1eda470
  1. 72
      src/Numerics/Combinatorics.cs

72
src/Numerics/Combinatorics.cs

@ -197,6 +197,78 @@ namespace MathNet.Numerics
}
}
/// <summary>
/// Lazily generates all combinations lexicographically.
/// Note that the same array is yielded on each iteration,
/// so care is needed when converting to a collection.
/// </summary>
/// <param name="n">Number of items in the set.</param>
/// <param name="k">Number of items to choose, without replacement.</param>
/// <returns>A lazy enumeration of all unique subsets of size k.</returns>
public static IEnumerable<int[]> GenerateAllCombinations(int n, int k)
{
// This method follows Algorithm T found in
// Knuth, "Combinatorial Algorithms," The Art of Computer Science vol. 4A, 7.2.1.3
if (n < 0) throw new ArgumentOutOfRangeException(nameof(n), Resources.ArgumentNotNegative);
if (k < 0) throw new ArgumentOutOfRangeException(nameof(k), Resources.ArgumentNotNegative);
// We'll repeatedly yield the following array as we generate the permutations.
// The first entry is just the items in lexicographical order.
var a = new int[k];
var c = Enumerable.Range(0, k + 2).ToArray();
c[k] = n;
c[k + 1] = 0;
int x;
int j = k;
if (k <= n) // Returns empty enumerable if k > n;
{
if (k == n)
yield return c.Take(k).ToArray();
else
while (true)
{
for (int i = 0; i < k; i++)
a[i] = c[i];
yield return a;
if (j > 0)
{
x = j;
}
else
{
// Easy case?
if (c[0] + 1 < c[1])
{
c[0] = c[0] + 1;
continue;
}
// We differ slightly here from Knuth.
// Instead of j=2, we set to 1.
// But we put j++ at the beginning of the do loop that immediately follows.
j = 1;
do
{
j++;
c[j - 2] = j - 2;
x = c[j - 1] + 1;
} while (x == c[j]);
if (j > k) break;
}
c[j - 1] = x;
j--;
}
}
}
/// <summary>
/// Select a random permutation, without repetition, from a data array by reordering the provided array in-place.
/// Implemented using Fisher-Yates Shuffling. The provided data array will be modified.

Loading…
Cancel
Save