@Override public void propagate(int evtmask) throws ContradictionException { if (PropagatorEventType.isFullPropagation(evtmask)) { if (n2 < n + vars[n].getLB()) { fails(); // TODO: could be more precise, for explanation purpose } buildDigraph(); } digraph.removeNode(n2); digraph.removeNode(n2 + 1); free.clear(); for (int i = 0; i < n; i++) { if (digraph.getPredOf(i).size() == 0) { free.set(i); } } for (int i = n; i < n2; i++) { if (digraph.getSuccOf(i).size() == 0) { free.set(i); } } int card = repairMatching(); vars[n].updateUpperBound(card, this); if (vars[n].getLB() == card) { filter(); } for (int i = 0; i < idms.length; i++) { idms[i].unfreeze(); } }
private int repairMatching() throws ContradictionException { for (int i = free.nextSetBit(0); i >= 0 && i < n; i = free.nextSetBit(i + 1)) { tryToMatch(i); } int card = 0; for (int i = 0; i < n; i++) { if (digraph.getPredOf(i).size() > 0) { card++; } } return card; }
private void buildDigraph() { for (int i = 0; i < n2; i++) { digraph.getSuccOf(i).clear(); digraph.getPredOf(i).clear(); } free.set(0, n2); int j, k, ub; IntVar v; for (int i = 0; i < n2 + 2; i++) { digraph.removeNode(i); } for (int i = 0; i < n; i++) { v = vars[i]; ub = v.getUB(); for (k = v.getLB(); k <= ub; k = v.nextValue(k)) { j = map.get(k); digraph.addArc(i, j); } } }
private void filter() throws ContradictionException { buildSCC(); int j, ub; IntVar v; for (int i = 0; i < n; i++) { v = vars[i]; ub = v.getUB(); for (int k = v.getLB(); k <= ub; k = v.nextValue(k)) { j = map.get(k); if (nodeSCC[i] != nodeSCC[j]) { if (digraph.getPredOf(i).contains(j)) { v.instantiateTo(k, this); } else { v.removeValue(k, this); digraph.removeArc(i, j); } } } if (!v.hasEnumeratedDomain()) { ub = v.getUB(); for (int k = v.getLB(); k <= ub; k = v.nextValue(k)) { j = map.get(k); if (digraph.arcExists(i, j) || digraph.arcExists(j, i)) { break; } else { v.removeValue(k, this); } } int lb = v.getLB(); for (int k = ub; k >= lb; k = v.previousValue(k)) { j = map.get(k); if (digraph.arcExists(i, j) || digraph.arcExists(j, i)) { break; } else { v.removeValue(k, this); } } } } }