private int visit(int node, int last) throws ContradictionException { if (node == -1) { contradiction(G, "G_R disconnected"); } if (node == last) { return 1; } int next = -1; INeighbors succs = G_R.getSuccessorsOf(node); for (int x = succs.getFirstElement(); x >= 0; x = succs.getNextElement()) { if (G_R.getPredecessorsOf(x).neighborhoodSize() == 1) { if (next != -1) { return 0; } next = x; } else { G_R.removeArc(node, x); } } succs = mates[node]; int from, to; for (int e = succs.getFirstElement(); e >= 0; e = succs.getNextElement()) { to = e % n; if (sccOf[to].get() != next) { from = e / n - 1; G.removeArc(from, to, this); mates[node].remove(e); } } return visit(next, last) + 1; }
@Override public ESat isEntailed() { if (G.instantiated()) { int nr = 0; for (int i = 0; i < n_R.get(); i++) { nr += G_R.getSuccessorsOf(i).neighborhoodSize(); } if (nr == n_R.get() - 1) { return ESat.TRUE; } return ESat.FALSE; } return ESat.UNDEFINED; }
/** * Maintain incrementally the reduced graph and strongly connected components of a directed graph * variable Ensures that the reduced graph is a Hamiltonian path BEWARE REQUIRES A UNIQUE SOURCE * AND A UNIQUE SINK * * @param graph * @param constraint * @param solver */ public PropReducedGraphHamPath(V graph, Constraint<V, Propagator<V>> constraint, Solver solver) { super((V[]) new DirectedGraphVar[] {graph}, solver, constraint, PropagatorPriority.LINEAR); G = graph; n = G.getEnvelopGraph().getNbNodes(); n_R = environment.makeInt(0); G_R = new StoredDirectedGraph(environment, n, GraphType.DOUBLE_LINKED_LIST); sccOf = new IStateInt[n]; sccFirst = new IStateInt[n]; sccNext = new IStateInt[n]; mates = new INeighbors[n]; for (int i = 0; i < n; i++) { sccOf[i] = environment.makeInt(0); sccFirst[i] = environment.makeInt(-1); sccNext[i] = environment.makeInt(-1); G_R.getActiveNodes().desactivate(i); mates[i] = new StoredDoubleIntLinkedList(environment); } arcRemoved = new RemArc(this); sccComputed = new BitSet(n); }
@Override public void propagate(int evtmask) throws ContradictionException { for (int i = 0; i < n; i++) { sccFirst[i].set(-1); sccNext[i].set(-1); mates[i].clear(); G_R.getActiveNodes().desactivate(i); } ArrayList<TIntArrayList> allSCC = StrongConnectivityFinder.findAllSCCOf(G.getEnvelopGraph()); int s = allSCC.size(); n_R.set(s); int elem; TIntArrayList list; for (int i = 0; i < s; i++) { list = allSCC.get(i); G_R.getActiveNodes().activate(i); for (int j = list.size() - 1; j >= 0; j--) { elem = list.get(j); sccOf[elem].set(i); addNode(i, elem); } } INeighbors succs; int x; for (int i = 0; i < n; i++) { x = sccOf[i].get(); succs = G.getEnvelopGraph().getSuccessorsOf(i); for (int j = succs.getFirstElement(); j >= 0; j = succs.getNextElement()) { if (x != sccOf[j].get()) { G_R.addArc(x, sccOf[j].get()); mates[x].add((i + 1) * n + j); } } } int first = -1; int last = -1; for (int i = 0; i < s; i++) { if (G_R.getPredecessorsOf(i).isEmpty()) { first = i; } if (G_R.getSuccessorsOf(i).isEmpty()) { last = i; } } if (first == -1 || last == -1 || first == last) { contradiction(G, ""); } if (visit(first, last) != n_R.get()) { contradiction(G, ""); } int to, arc; for (int i = 0; i < n; i++) { to = G.getKernelGraph().getSuccessorsOf(i).getFirstElement(); x = sccOf[i].get(); if (to != -1 && sccOf[to].get() != x && mates[x].neighborhoodSize() > 1) { arc = (i + 1) * n + to; for (int a = mates[x].getFirstElement(); a >= 0; a = mates[x].getNextElement()) { if (a != arc) { G.removeArc(a / n - 1, a % n, this); } } mates[x].clear(); mates[x].add(arc); } } }