code: long next(int[][] graph, int v, long[] current, long[] unique, long[] included, Suppressed suppressed) {
  
          if (suppressed.contains(v)) return current[v];
  
          long invariant = distribute(current[v]);
          int nUnique = 0;
  
          for (int w : graph[v]) {
  
              // skip suppressed atom
              if (suppressed.contains(w)) continue;
  
              long adjInv = current[w];
  
              // find index of already included neighbor
              int i = 0;
              while (i < nUnique && unique[i] != adjInv) {
                  ++i;
              }
  
              // no match, then the value is unique, use adjInv
              // match, then rotate the previously included value
              included[i] = (i == nUnique) ? unique[nUnique++] = adjInv : rotate(included[i]);
  
              invariant ^= included[i];
          }
  
          return invariant;
      }
docs: Determine the next value of the atom at index <i>v</i>. The value is
  calculated by combining the current values of adjacent atoms. When a
  duplicate value is found it can not be directly included and is
  <i>rotated</i> the number of times it has previously been seen.
  
  @param graph      adjacency list representation of connected atoms
  @param v          the atom to calculate the next value for
  @param current    the current values
  @param unique     buffer for working out which adjacent values are unique
  @param included   buffer for storing the rotated <i>unique</i> value, this
  value is <i>rotated</i> each time the same value is
  found.
  @param suppressed bit set indicates which atoms are 'suppressed'
  @return the next value for <i>v</i>