@Override
 public void propagate(int evtmask) throws ContradictionException {
   ISet nei;
   IntVar v;
   for (int i = 0; i < n; i++) {
     nei = g.getEnvelopGraph().getSuccessorsOf(i);
     for (int j = nei.getFirstElement(); j >= 0; j = nei.getNextElement()) {
       if (!intVars[i].contains(j)) {
         g.removeArc(i, j, aCause);
       }
     }
     v = intVars[i];
     int ub = v.getUB();
     for (int j = v.getLB(); j <= ub; j = v.nextValue(j)) {
       if (j < n && !g.getEnvelopGraph().arcExists(i, j)) {
         v.removeValue(j, aCause);
       }
     }
     if (!v.hasEnumeratedDomain()) {
       ub = v.getUB();
       while (ub >= 0 && ub < n && !g.getEnvelopGraph().arcExists(i, ub)) {
         v.removeValue(ub, aCause);
         ub--;
       }
     }
   }
   gdm.unfreeze();
   for (int i = 0; i < idms.length; i++) {
     idms[i].unfreeze();
   }
 }
 /**
  * Links intVars and the graph arc (x,y)=var[x]=y values outside range [0,n-1] are not considered
  *
  * @param intVars
  * @param graph
  */
 public PropIntVarChanneling(IntVar[] intVars, DirectedGraphVar graph) {
   super(ArrayUtils.append(intVars, new Variable[] {graph}), PropagatorPriority.LINEAR, true);
   g = graph;
   gdm = (GraphDeltaMonitor) g.monitorDelta(this);
   this.intVars = intVars;
   this.idms = new IIntDeltaMonitor[intVars.length];
   for (int i = 0; i < intVars.length; i++) {
     idms[i] = intVars[i].monitorDelta(this);
   }
   this.n = g.getEnvelopGraph().getNbNodes();
   valRemoved = new ValRem();
   arcEnforced = new EnfArc();
   if (intVars[0].hasEnumeratedDomain()) {
     arcRemoved = new RemArcAC();
   } else {
     arcRemoved = new RemArcBC();
   }
 }
 @Override
 public ESat isEntailed() {
   for (int i = 0; i < vars.length; i++) {
     if (!vars[i].instantiated()) {
       return ESat.UNDEFINED;
     }
   }
   int val;
   for (int i = 0; i < n; i++) {
     val = intVars[i].getValue();
     if (val < n && !g.getEnvelopGraph().arcExists(i, val)) {
       return ESat.FALSE;
     }
     if (g.getEnvelopGraph().getSuccessorsOf(i).getSize() > 1) {
       return ESat.FALSE;
     }
   }
   return ESat.TRUE;
 }
 @Override
 public void propagate(int idxVarInProp, int mask) throws ContradictionException {
   if ((vars[idxVarInProp].getTypeAndKind() & Variable.GRAPH) != 0) {
     gdm.freeze();
     if ((mask & EventType.ENFORCEARC.mask) != 0) {
       gdm.forEachArc(arcEnforced, EventType.ENFORCEARC);
     }
     if ((mask & EventType.REMOVEARC.mask) != 0) {
       gdm.forEachArc(arcRemoved, EventType.REMOVEARC);
     }
     gdm.unfreeze();
   } else {
     varIdx = idxVarInProp;
     int val = intVars[varIdx].getLB();
     if ((mask & EventType.INSTANTIATE.mask) != 0 && val < n) {
       g.enforceArc(varIdx, val, aCause);
     }
     idms[varIdx].freeze();
     idms[idxVarInProp].forEach(valRemoved, EventType.REMOVE);
     idms[varIdx].unfreeze();
   }
 }