3

I'm trying to get a simple method (a script or a c++ snippet, perhaps) that generates a hypercube links data, i.e., given an n-dimensional hypercube with vertices numbered as 1, ..., 2n, it produces the output:

1 3
1 5
2 3
...

Where each row represents a connection between two vertices. (related question)

But in a somehow different context. I hope someone has already done this. The input should be the hypercube dimensionality. To remind you, links exist between two nodes if and only if their node i.d.'s differ in exactly one bit position. My intention was to use XOR operator, and when the result can be expressed as 2k for some k, then the bit representations differ in a single position, and I write a link. However, I'm not sure how to get this implemented (C++ or script).

Community
  • 1
  • 1
user506901
  • 699
  • 4
  • 9
  • 18

2 Answers2

2

Brute force approach O(2^(2k)) in C++:

int n = 32 // or any other power of 2
for(int i = 0; i < n; i++){
   // we check with which vertices is it connected
   for(int j = 0; j < i; j++){
     // we stop when j >= i, because we want to output each unordered pair once
     int u = i ^ j;

     // we check if U is a power of 2, by rounding it up to next power of two and
     // checking if it changed
     int k = u - 1;
     k |= k >> 1;
     k |= k >> 2;
     k |= k >> 4;
     k |= k >> 8;
     k |= k >> 16;

     if(k + 1 == u)
       cout << i << " " << j << endl;
   } 
}

If you need a faster solution, I'll recommend trying recursion, because the structure of hypercube is itself recursive: n - dimensional hypercube is made from two n-1 dimensional hypercubes, which differ on only one coordinate. Take a square for example - it consists of two segments (1 dimensional) that differ on exactly one coordinate.

Algorithm for recursive solution will be more or less like this (python):

# outputs pair (list of vertices, list of connections beetween them), for n
# dimensional hypercube with vertices starting at x
def hypercube(n, i):
  if n == 1:
    return (i, [])
  v1, e1 = hypercube(n-1, i)
  v2, e2 = hypercube(n-1, i + len(v1))
  return(v1 + v2, zip(v1, v2) + e1 + e2)
KCH
  • 2,794
  • 2
  • 23
  • 22
2

Here's a short, self-contained C++ version that prints the connected vertices for an n-dimensional hypercube:

int n = 3;
// examine all vertices from 0...2^n-1
unsigned long long max = 1ULL << n;  
for (unsigned long long vertex = 0; vertex < max; ++vertex) {
  std::cout << vertex << ':';
  // print all vertices that differ from vertex by one bit
  unsigned long long mask = 1;
  for (int shift_amt = 0; shift_amt < n; ++shift_amt) {
    std::cout << ' ' << (vertex ^ (mask << shift_amt));
  }
  std::cout << '\n';
}

Example output when n is 3 (assuming you're okay with vertices that start at 0, not 1):

0: 1 2 4
1: 0 3 5
2: 3 0 6
3: 2 1 7
4: 5 6 0
5: 4 7 1
6: 7 4 2
7: 6 5 3
Nate Kohl
  • 35,264
  • 10
  • 43
  • 55