private void buildSCC() { digraph.removeNode(n2); digraph.removeNode(n2 + 1); digraph.addNode(n2); digraph.addNode(n2 + 1); // TODO CHECK THIS PART for (int i = 0; i < n; i++) { if (free.get(i)) { digraph.addArc(n2, i); } else { digraph.addArc(i, n2); } } for (int i = n; i < n2; i++) { if (free.get(i)) { digraph.addArc(i, n2 + 1); } else { digraph.addArc(n2 + 1, i); } } SCCfinder.findAllSCC(); nodeSCC = SCCfinder.getNodesSCC(); digraph.removeNode(n2); digraph.removeNode(n2 + 1); }
@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 void tryToMatch(int i) throws ContradictionException { int mate = augmentPath_BFS(i); if (mate != -1) { free.clear(mate); free.clear(i); int tmp = mate; while (tmp != i) { digraph.removeArc(father[tmp], tmp); digraph.addArc(tmp, father[tmp]); tmp = father[tmp]; } } }
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 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 int augmentPath_BFS(int root) { in.clear(); int indexFirst = 0, indexLast = 0; fifo[indexLast++] = root; int x; ISetIterator succs; while (indexFirst != indexLast) { x = fifo[indexFirst++]; succs = digraph.getSuccOf(x).iterator(); while (succs.hasNext()) { int y = succs.nextInt(); if (!in.get(y)) { father[y] = x; fifo[indexLast++] = y; in.set(y); if (free.get(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(); 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); } } } } }