private void buildDigraph() throws ContradictionException {
   digraph.desactivateNode(n2);
   for (int i = 0; i < n2; i++) {
     flow[i] = 0;
     digraph.getSuccessorsOf(i).clear();
     digraph.getPredecessorsOf(i).clear();
   }
   int j, k, ub;
   IntVar v;
   for (int i = 0; i < n; i++) {
     v = vars[i];
     ub = v.getUB();
     if (v.instantiated()) {
       j = map.get(v.getValue());
       if (flow[j] < this.ub[j]) {
         digraph.addArc(j, i);
         flow[i]++;
         flow[j]++;
       } else {
         contradiction(v, "");
       }
     } else {
       for (k = v.getLB(); k <= ub; k = v.nextValue(k)) {
         j = map.get(k);
         digraph.addArc(i, j);
       }
     }
   }
 }
 private void buildSCC() {
   digraph.desactivateNode(n2);
   digraph.activateNode(n2);
   for (int i = n; i < n2; i++) {
     if (flow[i] < ub[i]) {
       digraph.addArc(i, n2);
     }
     if (flow[i] > lb[i]) {
       digraph.addArc(n2, i);
     }
   }
   SCCfinder.findAllSCC();
   nodeSCC = SCCfinder.getNodesSCC();
   digraph.desactivateNode(n2);
 }
 private void useValue(int i) throws ContradictionException {
   int mate = swapValue_BFS(i);
   if (mate != -1) {
     flow[mate]--;
     flow[i]++;
     int tmp = mate;
     while (tmp != i) {
       digraph.removeArc(tmp, father[tmp]);
       digraph.addArc(father[tmp], tmp);
       tmp = father[tmp];
     }
   } else {
     contradiction(null, "no match");
   }
 }
 private void assignVariable(int i) throws ContradictionException {
   int mate = augmentPath_BFS(i);
   if (mate != -1) {
     flow[mate]++;
     flow[i]++;
     int tmp = mate;
     while (tmp != i) {
       digraph.removeArc(father[tmp], tmp);
       digraph.addArc(tmp, father[tmp]);
       tmp = father[tmp];
     }
   } else {
     contradiction(vars[i], "no match");
   }
 }
 private boolean canUnuseValue(int i) {
   int mate = augmentPath_BFS(i);
   if (mate != -1) {
     flow[mate]++;
     flow[i]--;
     int tmp = mate;
     while (tmp != i) {
       digraph.removeArc(father[tmp], tmp);
       digraph.addArc(tmp, father[tmp]);
       tmp = father[tmp];
     }
     return true;
   } else {
     return false;
   }
 }
 private int augmentPath_BFS(int root) {
   in.clear();
   int indexFirst = 0, indexLast = 0;
   fifo[indexLast++] = root;
   in.set(root); // TODO CORRECTION JG 15/11/12 to test on minizinc instance
   int x, y;
   ISet succs;
   while (indexFirst != indexLast) {
     x = fifo[indexFirst++];
     succs = digraph.getSuccessorsOf(x);
     for (y = succs.getFirstElement(); y >= 0; y = succs.getNextElement()) {
       if (!in.get(y)) {
         father[y] = x;
         fifo[indexLast++] = y;
         in.set(y);
         if (flow[y] < this.ub[y]) {
           if (y < n) {
             throw new UnsupportedOperationException();
           }
           return y;
         }
       }
     }
   }
   return -1;
 }
 private int swapValue_BFS(int root) {
   in.clear();
   int indexFirst = 0, indexLast = 0;
   fifo[indexLast++] = root;
   in.set(root); // TODO CORRECTION JG 15/11/12 to test on minizinc instance
   int x, y;
   ISet succs;
   while (indexFirst != indexLast) {
     x = fifo[indexFirst++];
     succs = digraph.getPredecessorsOf(x);
     //			succs = digraph.getSuccessorsOf(x);
     for (y = succs.getFirstElement(); y >= 0; y = succs.getNextElement()) {
       if (!in.get(y)) {
         father[y] = x;
         fifo[indexLast++] = y;
         in.set(y);
         if (flow[y] > this.lb[y]) {
           return y;
         }
       }
     }
   }
   return -1;
 }
 private void filter() throws ContradictionException {
   buildSCC();
   int j, ub;
   IntVar v;
   for (int i = 0; i < n; i++) {
     v = vars[i];
     ub = v.getUB();
     if (v.getLB() != ub) { // i.e. v is not instantiated
       for (int k = v.getLB(); k <= ub; k = v.nextValue(k)) {
         j = map.get(k);
         if (nodeSCC[i] != nodeSCC[j]) {
           if (digraph.arcExists(j, i)) {
             v.instantiateTo(k, aCause);
             ISet nei = digraph.getSuccessorsOf(i);
             for (int s = nei.getFirstElement(); s >= 0; s = nei.getNextElement()) {
               digraph.removeArc(i, s);
             }
           } else {
             v.removeValue(k, aCause);
             digraph.removeArc(i, j);
           }
         }
       }
     }
   }
   int nb = boundedVariables.size();
   for (int i = 0; i < nb; i++) {
     v = vars[boundedVariables.get(i)];
     ub = v.getUB();
     for (int k = v.getLB(); k <= ub; k++) {
       j = map.get(k);
       if (!(digraph.arcExists(i, j) || digraph.arcExists(j, i))) {
         v.removeValue(k, aCause);
       }
     }
     int lb = v.getLB();
     for (int k = v.getUB(); k >= lb; k--) {
       j = map.get(k);
       if (!(digraph.arcExists(i, j) || digraph.arcExists(j, i))) {
         v.removeValue(k, aCause);
       }
     }
   }
   // filter cardinality variables
   int idx;
   ISet nei;
   for (int i = 0; i < values.length; i++) {
     idx = map.get(values[i]);
     nei = digraph.getSuccessorsOf(idx);
     ub = nei.getSize() + digraph.getPredecessorsOf(idx).getSize();
     cards[i].updateUpperBound(ub, aCause);
   }
   for (int i = 0; i < values.length; i++) {
     idx = map.get(values[i]);
     int size = digraph.getSuccessorsOf(idx).getSize();
     ub = cards[i].getUB();
     while (size < ub && canUseValue(idx)) {
       size++;
     }
     cards[i].updateUpperBound(size, aCause);
   }
   for (int i = 0; i < values.length; i++) {
     idx = map.get(values[i]);
     while (canUnuseValue(idx)) {}
     cards[i].updateLowerBound(digraph.getSuccessorsOf(idx).getSize(), aCause);
   }
 }