All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.chocosolver.solver.constraints.nary.circuit.PropCircuitSCC Maven / Gradle / Ivy

The newest version!
/*
 * This file is part of choco-solver, http://choco-solver.org/
 *
 * Copyright (c) 2024, 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