org.chocosolver.graphsolver.cstrs.IGraphConstraintFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of choco-graph Show documentation
Show all versions of choco-graph Show documentation
A graph module for Choco Solver.
/*
* Copyright (c) 1999-2014, Ecole des Mines de Nantes
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Ecole des Mines de Nantes nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.chocosolver.graphsolver.cstrs;
import org.chocosolver.graphsolver.GraphModel;
import org.chocosolver.graphsolver.cstrs.basic.*;
import org.chocosolver.graphsolver.cstrs.channeling.edges.*;
import org.chocosolver.graphsolver.cstrs.channeling.nodes.PropNodeBoolChannel;
import org.chocosolver.graphsolver.cstrs.channeling.nodes.PropNodeBoolsChannel;
import org.chocosolver.graphsolver.cstrs.channeling.nodes.PropNodeSetChannel;
import org.chocosolver.graphsolver.cstrs.connectivity.PropConnected;
import org.chocosolver.graphsolver.cstrs.connectivity.PropNbCC;
import org.chocosolver.graphsolver.cstrs.connectivity.PropNbSCC;
import org.chocosolver.graphsolver.cstrs.cost.trees.PropMaxDegVarTree;
import org.chocosolver.graphsolver.cstrs.cost.trees.PropTreeCostSimple;
import org.chocosolver.graphsolver.cstrs.cost.trees.lagrangianRelaxation.PropLagr_DCMST_generic;
import org.chocosolver.graphsolver.cstrs.cost.tsp.PropCycleCostSimple;
import org.chocosolver.graphsolver.cstrs.cost.tsp.lagrangianRelaxation.PropLagr_OneTree;
import org.chocosolver.graphsolver.cstrs.cycles.*;
import org.chocosolver.graphsolver.cstrs.degree.*;
import org.chocosolver.graphsolver.cstrs.inclusion.PropInclusion;
import org.chocosolver.graphsolver.cstrs.symmbreaking.PropIncrementalAdjacencyMatrix;
import org.chocosolver.graphsolver.cstrs.symmbreaking.PropIncrementalAdjacencyUndirectedMatrix;
import org.chocosolver.graphsolver.cstrs.symmbreaking.PropSymmetryBreaking;
import org.chocosolver.graphsolver.cstrs.symmbreaking.PropSymmetryBreakingEx;
import org.chocosolver.graphsolver.cstrs.tree.PropArborescence;
import org.chocosolver.graphsolver.cstrs.tree.PropArborescences;
import org.chocosolver.graphsolver.cstrs.tree.PropReachability;
import org.chocosolver.graphsolver.variables.IDirectedGraphVar;
import org.chocosolver.graphsolver.variables.IGraphVar;
import org.chocosolver.graphsolver.variables.IUndirectedGraphVar;
import org.chocosolver.graphsolver.variables.IncidentSet;
import org.chocosolver.solver.Model;
import org.chocosolver.solver.constraints.Constraint;
import org.chocosolver.solver.constraints.Propagator;
import org.chocosolver.solver.variables.BoolVar;
import org.chocosolver.solver.variables.IntVar;
import org.chocosolver.solver.variables.SetVar;
import org.chocosolver.util.objects.graphs.Orientation;
import org.chocosolver.util.tools.ArrayUtils;
/**
* Some usual graph constraints
*
* @author Jean-Guillaume Fages
*/
public interface IGraphConstraintFactory {
GraphModel _me();
//***********************************************************************************
// BASIC CONSTRAINTS
//***********************************************************************************
// counting
/**
* Create a constraint to force the number of nodes in g to be equal to nb
* @param g a graph variable
* @param nb an integer variable indicating the expected number of nodes in g
* @return A constraint to force the number of nodes in g to be equal to nb
*/
default Constraint nbNodes(IGraphVar g, IntVar nb){
return new Constraint("nbNodes", new PropNbNodes(g,nb));
}
/**
* Create a constraint to force the number of arcs in g to be equal to nb
* @param g a directed graph variable
* @param nb an integer variable indicating the expected number of arcs in g
* @return A constraint to force the number of arcs in g to be equal to nb
*/
default Constraint nbArcs(IDirectedGraphVar g, IntVar nb){
return new Constraint("nbArcs", new PropNbArcs(g,nb));
}
/**
* Create a constraint to force the number of edges in g to be equal to nb
* @param g an undirected graph variable
* @param nb an integer variable indicating the expected number of edges in g
* @return A constraint to force the number of edges in g to be equal to nb
*/
default Constraint nbEdges(IUndirectedGraphVar g, IntVar nb){
return new Constraint("nbEdges", new PropNbArcs(g,nb));
}
// loops
/**
* Create a constraint which ensures that 'loops' denotes the set
* of vertices in g which have a loop, i.e. an arc of the form f(i,i)
* i.e. vertex i in g => arc (i,i) in g
* @param g a graph variable
* @return A constraint which makes sure every node has a loop
*/
default Constraint loopSet(IGraphVar g, SetVar loops){
return new Constraint("loopSet", new PropLoopSet(g,loops));
}
/**
* Create a constraint which ensures g has nb loops
* |(i,i) in g| = nb
* @param g a graph variable
* @param nb an integer variable counting the number of loops in g
* @return A constraint which ensures g has nb loops
*/
default Constraint nbLoops(IGraphVar g, IntVar nb){
return new Constraint("nbLoops", new PropNbLoops(g,nb));
}
//***********************************************************************************
// SIMPLE PROPERTY CONSTRAINTS
//***********************************************************************************
// symmetry
/**
* Creates a constraint which ensures that g is a symmetric directed graph
* This means (i,j) in g <=> (j,i) in g
* Note that it may be preferable to use an undirected graph variable instead!
* @param g a directed graph variable
* @return A constraint which ensures that g is a symmetric directed graph
*/
default Constraint symmetric(IDirectedGraphVar g){
return new Constraint("symmetric", new PropSymmetric(g));
}
/**
* Creates a constraint which ensures that g is an antisymmetric directed graph
* This means (i,j) in g => (j,i) notin g
* @param g a directed graph variable
* @return A constraint which ensures that g is an antisymmetric directed graph
*/
default Constraint antisymmetric(IDirectedGraphVar g){
return new Constraint("antisymmetric", new PropAntiSymmetric(g));
}
// Transitivity
/**
* Create a transitivity constraint
* (i,j) in g and (j,k) in g => (i,k) in g
* Does not consider loops
* Enables to make cliques
* @param g An undirected graph variable
* @return A transitivity constraint
*/
default Constraint transitivity(IUndirectedGraphVar g){
return new Constraint("transitivity",new PropTransitivity(g));
}
/**
* Create a transitivity constraint
* (i,j) in g and (j,k) in g => (i,k) in g
* Does not consider loops
* Enables to make cliques and transitive closures
* @param g A directed graph variable
* @return A transitivity constraint
*/
default Constraint transitivity(IDirectedGraphVar g){
return new Constraint("transitivity",new PropTransitivity(g));
}
//***********************************************************************************
// INCLUSION CONSTRAINTS
//***********************************************************************************
/**
* Create an inclusion constraint between g1 and g2 such that
* g1 is a subGraph of g2
* Note that node are labelled with their indexes :
* the vertex 0 in g1 corresponds to the vertex 0 in g2
* @param g1 An undirected graph variable
* @param g2 An undirected graph variable
* @return a constraint which ensures that g1 is a subGraph of g2
*/
default Constraint subGraph(IUndirectedGraphVar g1, IUndirectedGraphVar g2){
return new Constraint("subGraph",new PropInclusion(g1,g2));
}
/**
* Create an inclusion constraint between g1 and g2 such that
* g1 is a subGraph of g2
* Note that node are labelled with their indexes :
* the vertex 0 in g1 corresponds to the vertex 0 in g2
* @param g1 A directed graph variable
* @param g2 A directed graph variable
* @return a constraint which ensures that g1 is a subGraph of g2
*/
default Constraint subGraph(IDirectedGraphVar g1, IDirectedGraphVar g2){
return new Constraint("subGraph",new PropInclusion(g1,g2));
}
//***********************************************************************************
// CHANNELING CONSTRAINTS
//***********************************************************************************
// Vertices
/**
* Channeling constraint :
* int i in nodes <=> vertex i in g
* @param g
* @param nodes
*/
default Constraint nodesChanneling(IGraphVar g, SetVar nodes){
return new Constraint("nodesSetChanneling",
new PropNodeSetChannel(nodes,g));
}
/**
* Channeling constraint :
* nodes[i] = 1 <=> vertex i in g
* @param g
* @param nodes
*/
default Constraint nodesChanneling(IGraphVar g, BoolVar[] nodes){
return new Constraint("nodesBoolsChanneling",
new PropNodeBoolsChannel(nodes,g));
}
/**
* Channeling constraint :
* isIn = 1 <=> vertex 'vertex' in g
* @param g
* @param isIn
* @param vertex
*/
default Constraint nodeChanneling(IGraphVar g, BoolVar isIn, int vertex){
return new Constraint("nodesBoolChanneling",
new PropNodeBoolChannel(isIn,vertex,g));
}
// Arc
/**
* Channeling constraint :
* isArc = 1 <=> arc (from,to) in g
* @param g
* @param isArc
* @param from
* @param to
*/
default Constraint arcChanneling(IDirectedGraphVar g, BoolVar isArc, int from, int to){
return new Constraint("arcChanneling",
new PropArcBoolChannel(isArc,from,to,g));
}
// Edge
/**
* Channeling constraint:
* isEdge = 1 <=> edge (i,j) in g
* @param g
* @param isEdge
* @param i
* @param j
*/
default Constraint edgeChanneling(IUndirectedGraphVar g, BoolVar isEdge, int i, int j){
return new Constraint("arcChanneling",
new PropArcBoolChannel(isEdge,i,j,g));
}
// Neighbors
/**
* Channeling constraint:
* successors[i] = j OR successors[j] = i <=> edge (i,j) in g
* @param g
* @param successors
*/
default Constraint neighborsChanneling(IUndirectedGraphVar g, IntVar[] successors){
return new Constraint("neighIntsChanneling",
new PropNeighIntsChannel1(successors,g),new PropNeighIntsChannel2(successors,g));
}
/**
* Channeling constraint:
* int j in neighbors[i] <=> edge (i,j) in g
* @param g
* @param neighbors
*/
default Constraint neighborsChanneling(IUndirectedGraphVar g, SetVar[] neighbors){
return new Constraint("neighSetsChanneling",
new PropNeighSetsChannel1(neighbors,g),new PropNeighSetsChannel2(neighbors,g));
}
/**
* Channeling constraint:
* neighbors[i][j] = 1 <=> edge (i,j) in g
* @param g
* @param neighbors
*/
default Constraint neighborsChanneling(IUndirectedGraphVar g, BoolVar[][] neighbors){
return new Constraint("neighBoolsChanneling",
new PropNeighBoolsChannel1(neighbors,g),new PropNeighBoolsChannel2(neighbors,g));
}
/**
* Channeling constraint:
* int j in neighborsOf <=> edge (node,j) in g
* @param g
* @param neighborsOf
* @param node
*/
default Constraint neighborsChanneling(IUndirectedGraphVar g, SetVar neighborsOf, int node){
return new Constraint("neighSetChanneling",
new PropNeighSetChannel(neighborsOf,node,g,new IncidentSet.SuccOrNeighSet()));
}
/**
* Channeling constraint:
* neighborsOf[j] = 1 <=> edge (node,j) in g
* @param g
* @param neighborsOf
* @param node
*/
default Constraint neighborsChanneling(IUndirectedGraphVar g, BoolVar[] neighborsOf, int node){
return new Constraint("neighBoolChanneling",
new PropNeighBoolChannel(neighborsOf,node,g,new IncidentSet.SuccOrNeighSet()));
}
// Successors
/**
* Channeling constraint:
* successors[i] = j <=> arc (i,j) in g
* @param g
* @param successors
*/
default Constraint successorsChanneling(IDirectedGraphVar g, IntVar[] successors){
return new Constraint("succIntsChanneling",
new PropSuccIntsChannel1(successors,g),new PropNeighIntsChannel2(successors,g));
}
/**
* Channeling constraint:
* int j in successors[i] <=> arc (i,j) in g
* @param g
* @param successors
*/
default Constraint successorsChanneling(IDirectedGraphVar g, SetVar[] successors){
return new Constraint("succSetsChanneling",
new PropNeighSetsChannel1(successors,g),new PropNeighSetsChannel2(successors,g));
}
/**
* Channeling constraint:
* successors[i][j] <=> arc (i,j) in g
* @param g
* @param successors
*/
default Constraint successorsChanneling(IDirectedGraphVar g, BoolVar[][] successors){
return new Constraint("succBoolsChanneling",
new PropNeighBoolsChannel1(successors,g),new PropNeighBoolsChannel2(successors,g));
}
/**
* Channeling constraint:
* int j in successorsOf <=> arc (node,j) in g
* @param g
* @param successorsOf
* @param node
*/
default Constraint successorsChanneling(IDirectedGraphVar g, SetVar successorsOf, int node){
return new Constraint("succSetChanneling",
new PropNeighSetChannel(successorsOf,node,g,new IncidentSet.SuccOrNeighSet()));
}
/**
* Channeling constraint:
* successorsOf[j] = 1 <=> arc (node,j) in g
* @param g
* @param successorsOf
* @param node
*/
default Constraint successorsChanneling(IDirectedGraphVar g, BoolVar[] successorsOf, int node){
return new Constraint("succBoolChanneling",
new PropNeighBoolChannel(successorsOf,node,g,new IncidentSet.SuccOrNeighSet()));
}
// Predecessors
/**
* Channeling constraint:
* int j in predecessorsOf <=> arc (j,node) in g
* @param g
* @param predecessorsOf
* @param node
*/
default Constraint predecessorsChanneling(IDirectedGraphVar g, SetVar predecessorsOf, int node){
return new Constraint("predSetChanneling",
new PropNeighSetChannel(predecessorsOf,node,g,new IncidentSet.PredOrNeighSet()));
}
/**
* Channeling constraint:
* predecessorsOf[j] = 1 <=> arc (j,node) in g
* @param g
* @param predecessorsOf
* @param node
*/
default Constraint predecessorsChanneling(IDirectedGraphVar g, BoolVar[] predecessorsOf, int node){
return new Constraint("predBoolChanneling",
new PropNeighBoolChannel(predecessorsOf,node,g,new IncidentSet.PredOrNeighSet()));
}
//***********************************************************************************
// DEGREE CONSTRAINTS
//***********************************************************************************
// degrees
/**
* Minimum degree constraint
* for any vertex i in g, |(i,j)| >= minDegree
* This constraint only holds on vertices that are mandatory
* @param g undirected graph var
* @param minDegree integer minimum degree of every node
* @return a minimum degree constraint
*/
default Constraint minDegrees(IUndirectedGraphVar g, int minDegree){
return new Constraint("minDegrees",new PropNodeDegree_AtLeast_Incr(g, minDegree));
}
/**
* Minimum degree constraint
* for any vertex i in g, |(i,j)| >= minDegree[i]
* This constraint only holds on vertices that are mandatory
* @param g undirected graph var
* @param minDegrees integer array giving the minimum degree of each node
* @return a minimum degree constraint
*/
default Constraint minDegrees(IUndirectedGraphVar g, int[] minDegrees){
return new Constraint("minDegrees",new PropNodeDegree_AtLeast_Incr(g, minDegrees));
}
/**
* Maximum degree constraint
* for any vertex i in g, |(i,j)| <= maxDegree
* This constraint only holds on vertices that are mandatory
* @param g undirected graph var
* @param maxDegree integer maximum degree
* @return a maximum degree constraint
*/
default Constraint maxDegrees(IUndirectedGraphVar g, int maxDegree){
return new Constraint("maxDegrees",new PropNodeDegree_AtMost_Coarse(g, maxDegree));
}
/**
* Maximum degree constraint
* for any vertex i in g, |(i,j)| <= maxDegrees[i]
* This constraint only holds on vertices that are mandatory
* @param g undirected graph var
* @param maxDegrees integer array giving the maximum degree of each node
* @return a maximum degree constraint
*/
default Constraint maxDegrees(IUndirectedGraphVar g, int[] maxDegrees){
return new Constraint("maxDegrees",new PropNodeDegree_AtMost_Coarse(g, maxDegrees));
}
/**
* Degree constraint
* for any vertex i in g, |(i,j)| = degrees[i]
* A vertex which has been removed has a degree equal to 0
* ENSURES EVERY VERTEX i FOR WHICH DEGREE[i]>0 IS MANDATORY
* @param g undirected graph var
* @param degrees integer array giving the degree of each node
* @return a degree constraint
*/
default Constraint degrees(IUndirectedGraphVar g, IntVar[] degrees){
return new Constraint("degrees",new PropNodeDegree_Var(g, degrees));
}
// inDegrees
/**
* Minimum inner degree constraint
* for any vertex i in g, |(j,i)| >= minDegree
* This constraint only holds on vertices that are mandatory
* @param g directed graph var
* @param minDegree integer minimum degree of every node
* @return a minimum inner degree constraint
*/
default Constraint minInDegrees(IDirectedGraphVar g, int minDegree){
return new Constraint("minInDegrees",new PropNodeDegree_AtLeast_Incr(g, Orientation.PREDECESSORS, minDegree));
}
/**
* Minimum inner degree constraint
* for any vertex i in g, |(j,i)| >= minDegree[i]
* This constraint only holds on vertices that are mandatory
* @param g directed graph var
* @param minDegrees integer array giving the minimum degree of each node
* @return a minimum inner degree constraint
*/
default Constraint minInDegrees(IDirectedGraphVar g, int[] minDegrees){
return new Constraint("minInDegrees",new PropNodeDegree_AtLeast_Incr(g, Orientation.PREDECESSORS, minDegrees));
}
/**
* Maximum inner degree constraint
* for any vertex i in g, |(j,i)| <= maxDegree
* This constraint only holds on vertices that are mandatory
* @param g directed graph var
* @param maxDegree integer maximum degree
* @return a maximum inner degree constraint
*/
default Constraint maxInDegrees(IDirectedGraphVar g, int maxDegree){
return new Constraint("maxInDegrees",new PropNodeDegree_AtMost_Coarse(g, Orientation.PREDECESSORS, maxDegree));
}
/**
* Maximum inner degree constraint
* for any vertex i in g, |(j,i)| <= maxDegrees[i]
* This constraint only holds on vertices that are mandatory
* @param g directed graph var
* @param maxDegrees integer array giving the maximum degree of each node
* @return a maximum inner degree constraint
*/
default Constraint maxInDegrees(IDirectedGraphVar g, int[] maxDegrees){
return new Constraint("maxInDegrees",new PropNodeDegree_AtMost_Coarse(g, Orientation.PREDECESSORS, maxDegrees));
}
/**
* Degree inner constraint
* for any vertex i in g, |(j,i)| = degrees[i]
* A vertex which has been removed has a degree equal to 0
* ENSURES EVERY VERTEX i FOR WHICH DEGREE[i]>0 IS MANDATORY
* @param g directed graph var
* @param degrees integer array giving the degree of each node
* @return a degree inner constraint
*/
default Constraint inDegrees(IDirectedGraphVar g, IntVar[] degrees){
return new Constraint("inDegrees",new PropNodeDegree_Var(g, Orientation.PREDECESSORS, degrees));
}
// out-degrees
/**
* Minimum outer degree constraint
* for any vertex i in g, |(i,j)| >= minDegree
* This constraint only holds on vertices that are mandatory
* @param g directed graph var
* @param minDegree integer minimum degree of every node
* @return a minimum outer degree constraint
*/
default Constraint minOutDegrees(IDirectedGraphVar g, int minDegree){
return new Constraint("minOutDegrees",new PropNodeDegree_AtLeast_Incr(g, Orientation.SUCCESSORS, minDegree));
}
/**
* Minimum outer degree constraint
* for any vertex i in g, |(i,j)| >= minDegree[i]
* This constraint only holds on vertices that are mandatory
* @param g directed graph var
* @param minDegrees integer array giving the minimum degree of each node
* @return a minimum outer degree constraint
*/
default Constraint minOutDegrees(IDirectedGraphVar g, int[] minDegrees){
return new Constraint("minOutDegrees",new PropNodeDegree_AtLeast_Incr(g, Orientation.SUCCESSORS, minDegrees));
}
/**
* Maximum outer degree constraint
* for any vertex i in g, |(i,j)| <= maxDegree
* This constraint only holds on vertices that are mandatory
* @param g directed graph var
* @param maxDegree integer maximum degree
* @return a maximum outer degree constraint
*/
default Constraint maxOutDegrees(IDirectedGraphVar g, int maxDegree){
return new Constraint("maxOutDegrees",new PropNodeDegree_AtMost_Coarse(g, Orientation.SUCCESSORS, maxDegree));
}
/**
* Maximum outer degree constraint
* for any vertex i in g, |(i,j)| <= maxDegrees[i]
* This constraint only holds on vertices that are mandatory
* @param g directed graph var
* @param maxDegrees integer array giving the maximum outer degree of each node
* @return a outer maximum degree constraint
*/
default Constraint maxOutDegrees(IDirectedGraphVar g, int[] maxDegrees){
return new Constraint("maxOutDegrees",new PropNodeDegree_AtMost_Coarse(g, Orientation.SUCCESSORS, maxDegrees));
}
/**
* Outer degree constraint
* for any vertex i in g, |(i,j)| = degrees[i]
* A vertex which has been removed has a degree equal to 0
* ENSURES EVERY VERTEX i FOR WHICH DEGREE[i]>0 IS MANDATORY
* @param g directed graph var
* @param degrees integer array giving the degree of each node
* @return an outer degree constraint
*/
default Constraint outDegrees(IDirectedGraphVar g, IntVar[] degrees){
return new Constraint("outDegrees",new PropNodeDegree_Var(g, Orientation.SUCCESSORS, degrees));
}
//***********************************************************************************
// CYCLE CONSTRAINTS
//***********************************************************************************
/**
* g must form a Hamiltonian cycle
* Implies that every vertex in [0,g.getNbMaxNodes()-1] is mandatory
*
* @param g an undirected graph variable
* @return a hamiltonian cycle constraint
*/
default Constraint hamiltonianCycle(IUndirectedGraphVar g) {
int m = 0;
int n = g.getNbMaxNodes();
for(int i=0;i 0) {
PropLagr_OneTree hk = new PropLagr_OneTree(GRAPHVAR, COSTVAR, EDGE_COSTS);
hk.waitFirstSolution(LAGR_MODE == 2);
props = ArrayUtils.append(props,new Propagator[]{hk});
}
return new Constraint("TSP",props);
}
/**
* Creates a degree-constrained minimum spanning tree constraint :
* GRAPH is a spanning tree of cost COSTVAR and each vertex degree is constrained
*
* BEWARE : assumes the channeling between GRAPH and DEGREES is already done
*
* @param GRAPH an undirected graph variable
* @param DEGREES the degree of every vertex
* @param COSTVAR variable representing the cost of the mst
* @param EDGE_COSTS cost matrix (should be symmetric)
* @param LAGR_MODE use the Lagrangian relaxation of the dcmst
* {0:no Lagrangian relaxation,
* 1:Lagrangian relaxation (since root node),
* 2:Lagrangian relaxation but wait a first solution before running it}
* @return a degree-constrained minimum spanning tree constraint
*/
default Constraint dcmst(IUndirectedGraphVar GRAPH, IntVar[] DEGREES,
IntVar COSTVAR, int[][] EDGE_COSTS,
int LAGR_MODE){
Propagator[] props = ArrayUtils.append(
tree(GRAPH).getPropagators()
,new Propagator[]{
new PropTreeCostSimple(GRAPH, COSTVAR, EDGE_COSTS)
,new PropMaxDegVarTree(GRAPH, DEGREES)
}
);
if (LAGR_MODE > 0) {
PropLagr_DCMST_generic hk = new PropLagr_DCMST_generic(GRAPH, COSTVAR, DEGREES, EDGE_COSTS, LAGR_MODE == 2);
props = ArrayUtils.append(props,new Propagator[]{hk});
}
return new Constraint("dcmst",props);
}
//***********************************************************************************
// SYMMETRY BREAKING CONSTRAINTS
//***********************************************************************************
/**
* Post a symmetry breaking constraint. This constraint is a symmetry breaking for
* class of directed graphs which contain a directed tree with root in node 0.
* (All nodes must be reachable from node 0)
* Note, that this method post this constraint directly, so it cannot be reified.
*
* This symmetry breaking method based on paper:
* Ulyantsev V., Zakirzyanov I., Shalyto A.
* BFS-Based Symmetry Breaking Predicates for DFA Identification
* //Language and Automata Theory and Applications. – Springer International Publishing, 2015. – С. 611-622.
*
*
* @param graph graph to be constrainted
*/
default void postSymmetryBreaking(IDirectedGraphVar graph) {
Model m = _me();
// ---------------------- variables ------------------------
int n = graph.getNbMaxNodes();
// t[i, j]
BoolVar[] t = m.boolVarArray("T[]", n * n);
// p[i]
IntVar[] p = new IntVar[n];
p[0] = m.intVar("P[0]", 0);
for (int i = 1; i < n; i++) {
p[i] = m.intVar("P[" + i + "]", 0, i - 1);
}
// ---------------------- constraints -----------------------
// t[i, j] <-> G
new Constraint("AdjacencyMatrix", new PropIncrementalAdjacencyMatrix(graph, t)).post();
// (p[j] == i) ⇔ t[i, j] and AND(!t[k, j], 0 ≤ k < j)
for (int i = 0; i < n - 1; i++) {
IntVar I = m.intVar(i);
for (int j = 1; j < n; j++) {
BoolVar[] clause = new BoolVar[i + 1];
clause[i] = t[i + j * n];
for (int k = 0; k < i; k++) {
clause[k] = t[k + j * n].not();
}
Constraint c = m.and(clause);
Constraint pij = m.arithm(p[j], "=", I);
m.ifThen(pij, c);
m.ifThen(c, pij);
}
}
// p[i] ≤ p[i + 1]
for (int i = 1; i < n - 1; i++) {
m.arithm(p[i], "<=", p[i + 1]).post();
}
}
/**
* Post a symmetry breaking constraint. This constraint is a symmetry breaking for
* class of undirected connected graphs.
* Note, that this method post this constraint directly, so it cannot be reified.
*
* This symmetry breaking method based on paper:
* Ulyantsev V., Zakirzyanov I., Shalyto A.
* BFS-Based Symmetry Breaking Predicates for DFA Identification
* //Language and Automata Theory and Applications. – Springer International Publishing, 2015. – С. 611-622.
*
* @param graph graph to be constrainted
*/
default void postSymmetryBreaking(IUndirectedGraphVar graph) {
Model m = _me();
// ---------------------- variables ------------------------
int n = graph.getNbMaxNodes();
// t[i, j]
BoolVar[] t = m.boolVarArray("T[]", n * n);
// p[i]
IntVar[] p = new IntVar[n];
p[0] = m.intVar("P[0]", 0);
for (int i = 1; i < n; i++) {
p[i] = m.intVar("P[" + i + "]", 0, i - 1);
}
// ---------------------- constraints -----------------------
// t[i, j] <-> G
new Constraint("AdjacencyMatrix", new PropIncrementalAdjacencyUndirectedMatrix(graph, t)).post();
// (p[j] == i) ⇔ t[i, j] and AND(!t[k, j], 0 ≤ k < j)
for (int i = 0; i < n - 1; i++) {
IntVar I = m.intVar(i);
for (int j = 1; j < n; j++) {
BoolVar[] clause = new BoolVar[i + 1];
clause[i] = t[i + j * n];
for (int k = 0; k < i; k++) {
clause[k] = t[k + j * n].not();
}
Constraint c = m.and(clause);
Constraint pij = m.arithm(p[j], "=", I);
m.ifThen(pij, c);
m.ifThen(c, pij);
}
}
// p[i] ≤ p[i + 1]
for (int i = 1; i < n - 1; i++) {
m.arithm(p[i], "<=", p[i + 1]).post();
}
}
/**
* Creates a symmetry breaking constraint. This constraint is a symmetry breaking for
* class of undirected connected graphs.
*
* This symmetry breaking method based on paper:
* Codish M. et al.
* Breaking Symmetries in Graph Representation
* //IJCAI. – 2013. – С. 3-9.
*
* @param graph graph to be constrainted
*/
default Constraint symmetryBreaking2(IUndirectedGraphVar graph) {
int n = graph.getNbMaxNodes();
BoolVar[] t = _me().boolVarArray("T[]", n * n);
return new Constraint("symmBreak",
new PropIncrementalAdjacencyUndirectedMatrix(graph, t),
new PropSymmetryBreaking(t)
);
}
/**
* Creates a symmetry breaking constraint. This constraint is a symmetry breaking for
* class of undirected connected graphs.
*
* This symmetry breaking method based on paper:
* Codish M. et al.
* Breaking Symmetries in Graph Representation
* //IJCAI. – 2013. – С. 3-9.
*
* @param graph graph to be constrainted
*/
default Constraint symmetryBreaking3(IUndirectedGraphVar graph) {
int n = graph.getNbMaxNodes();
BoolVar[] t = _me().boolVarArray("T[]", n * n);
return new Constraint("symmBreakEx",
new PropIncrementalAdjacencyUndirectedMatrix(graph, t),
new PropSymmetryBreakingEx(t)
);
}
}