org.chocosolver.solver.constraints.nary.circuit.PropCircuitSCC Maven / Gradle / Ivy
/*
* This file is part of choco-solver, http://choco-solver.org/
*
* Copyright (c) 2022, IMT Atlantique. All rights reserved.
*
* Licensed under the BSD 4-clause license.
*
* See LICENSE file in the project root for full license information.
*/
package org.chocosolver.solver.constraints.nary.circuit;
import org.chocosolver.solver.constraints.Propagator;
import org.chocosolver.solver.constraints.PropagatorPriority;
import org.chocosolver.solver.exception.ContradictionException;
import org.chocosolver.solver.variables.IntVar;
import org.chocosolver.solver.variables.events.PropagatorEventType;
import org.chocosolver.util.ESat;
import org.chocosolver.util.graphOperations.connectivity.StrongConnectivityFinder;
import org.chocosolver.util.objects.graphs.DirectedGraph;
import org.chocosolver.util.objects.setDataStructures.ISet;
import org.chocosolver.util.objects.setDataStructures.ISetIterator;
import org.chocosolver.util.objects.setDataStructures.SetFactory;
import org.chocosolver.util.objects.setDataStructures.SetType;
import java.util.Random;
/**
* Filters circuit based on strongly connected components
* (see the TechReport "Improving the Asymmetric TSP by considering graph structure", Fages & Lorca, 2012)
* @author Jean-Guillaume Fages
*/
public class PropCircuitSCC extends Propagator {
//***********************************************************************************
// VARIABLES
//***********************************************************************************
private final int n;
private final int n2;
private final DirectedGraph support;
private final StrongConnectivityFinder SCCfinder;
private final DirectedGraph G_R;
private int[] sccOf;
private final ISet[] mates;
// proba
private Random rd;
private final int offSet;
private final CircuitConf conf;
//***********************************************************************************
// CONSTRUCTORS
//***********************************************************************************
public PropCircuitSCC(IntVar[] succs, int offSet, CircuitConf conf) {
super(succs, PropagatorPriority.LINEAR, false);
this.offSet = offSet;
n = vars.length;
n2 = n+1;
support = new DirectedGraph(n2,SetType.BITSET,true);
G_R = new DirectedGraph(n2,SetType.LINKED_LIST,false);
SCCfinder = new StrongConnectivityFinder(support);
mates = new ISet[n2];
for(int i=0;i 1) {
arc = (i + 1) * n2 + to;
ISetIterator iter = mates[x].iterator();
while (iter.hasNext()) {
int a = iter.nextInt();
if (a != arc) {
int val = a%n2;
if(val==n){
val = source;
}
vars[a/n2-1].removeValue(val+offSet, this);
}
}
mates[x].clear();
mates[x].add(arc);
}
}
}
}
private void checkSCCLink(int sccFrom) throws ContradictionException {
int inDoor = -1;
int outDoor = -1;
ISetIterator iter = mates[sccFrom].iterator();
while (iter.hasNext()) {
int i = iter.nextInt();
if(inDoor==-1){
inDoor = i%n2;
}else if (inDoor!=i%n2){
inDoor = -2;
}
if(outDoor==-1){
outDoor = i/n2-1;
}else if (outDoor!=i/n2-1){
outDoor = -2;
}
}
if (inDoor>=0) {
forceInDoor(inDoor);
}
if (outDoor>=0) {
forceOutDoor(outDoor);
// If 1 in and 1 out and |scc| > 2 then forbid in->out
// Is only 1 in ?
if (G_R.getPredecessorsOf(sccFrom).iterator().hasNext()) {
int in = -1;
int p = G_R.getPredecessorsOf(sccFrom).iterator().next();
ISetIterator iterP = mates[p].iterator();
while (iterP.hasNext()) {
int i = iterP.nextInt();
if (in == -1) {
in = i % n2;
} else if (in != i % n2) {
return;
}
}
assert (in!=-1);
assert (sccOf[in] == sccFrom);
// Is in->out possible?
if(vars[in].contains(outDoor+offSet)){
// Is |scc| > 2 ?
int size = 0;
for(int i=SCCfinder.getSCCFirstNode(sccFrom); i>=0 && size<3;i=SCCfinder.getNextNode(i)){
size++;
}
if(size>2){
vars[in].removeValue(outDoor+offSet, this);
}
}
}
}
}
private void forceInDoor(int x) throws ContradictionException {
int sx = sccOf[x];
for(int i=0; i
© 2015 - 2024 Weber Informatics LLC | Privacy Policy