Dana Vrajitoru
B424 Parallel and Distributed Programming

Combinatorial Object Generation

Generating Subsets

Example
Rank     Binary     Subset
0 0 0 0 {}
1 0 0 1 {3}
2 0 1 0 {2}
3 0 1 1 {2, 3}
4 1 0 0 {1}
5 1 0 1 {1, 3}
6 1 1 0 {1, 2}
7 1 1 1 {1, 2, 3}

Sequential Algorithm

Initial_set() {
  for (i=0; i<n; i++)
    a[i] = 0;
}
Next_set() {
  i=0; 
  while (a[i] == 1) {
    a[i] = 0;
    i++;
  }
  if (i < n)
    a[i] = 1;
}

Parallel Version

Binary Conversion

Binary(r) {
  for (i=0; i<n; i++) {
    if (r % 2 == 0)
      a[i] = 0;
    else
      a[i] = 1;
    r = r/2;
  }
}

Permutations

Next Permutation

Sequential Algorithm

Next_permutation(a, n) {
  for (k=n-2; k>=0; k--) 
    if (a[k] < a[k+1]) 
      break;
  if (k < 0) 
    return false; // last permutation
  for (m=n-1; a[m]<a[k]; m--);
  swap(a[k], a[m]);
  for(i=k+1, j=n-1; i<j; i++, j--)
    swap(a[i], a[j]);
  return true;
}

Parallel Algorithm

Initial Permutation

// Assumes that the elements are in order initially
First_permutation(a, n, id) {
  temp = a[id];
  for (i=id-1; i>=0; i--)
    a[i+1] = a[i];
  a[0] = temp;
}

Several Levels

Next Subset of Size m

Next_subset(a, n, s, m) {
  for (k = m-1; k >= 0; k--) // find k
    if (s[k] != a[n-m+k])
      break;
  if (k < 0)
    return false; // last subset
  for (j=n-m+k-1; a[j] != s[k]; j--); // find j
  s[k] = a[j+1]; 
  for (i=k+1; i < m; i++) 
    s[i] = a[j+1+i-k];
  return true;
}

Lexicographic Order

Extract Element

// Extracts the element from position last and places it in position
// first. Shifts the intermediate elements forward by 1.

Extract(a, first, last) {
  temp = a[last];
  for (i=last-1; i >= first; i--)
    a[i+1] = a[i];
  a[first] = temp;
}

Initial Permutation

// Assuming that np = n!/(n-m)!
Initial_permutation(a, n, m, id, np) {
  rank = id;
  subset_size = np/n;
  for (first=0; first < m; first++) {
    last = first + rank/subset_size;
    Extract(a, first, last);
    rank = rank % subset_size;
    subset_size = subset_size / (n-first-1);
  }
}