/*
* Kodkod -- Copyright (c) 2005-present, Emina Torlak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package kodkod.examples.csp;
import java.util.ArrayList;
import java.util.List;
import kodkod.ast.Expression;
import kodkod.ast.Formula;
import kodkod.ast.Relation;
import kodkod.ast.Variable;
import kodkod.engine.Solution;
import kodkod.engine.Solver;
import kodkod.engine.config.ConsoleReporter;
import kodkod.engine.satlab.SATFactory;
import kodkod.instance.Bounds;
import kodkod.instance.TupleFactory;
import kodkod.instance.TupleSet;
import kodkod.instance.Universe;
/**
* A decision version of the graph coloring problem. Given a graph G and a number of colors k,
* this class determines if G is k-colorable.
* See <a href="http://www.cs.hbg.psu.edu/txn131/graphcoloring.html">Graph Coloring Benchmark Instances</a>
* for example graph coloring problems instances.
* @author Emina Torlak
*/
public final class GraphColoring {
private final Relation vertex, color, edges, v2c;
private final Bounds bounds;
/**
* Constructs an instance of the graph coloring problem for the given graph and the number of colors.
* @requires colors > 0
*/
public GraphColoring(String file, Graph.Format format, int colors) {
assert colors > 0;
vertex = Relation.unary("Vertex");
color = Relation.unary("Color");
edges = Relation.binary("edges");
v2c = Relation.binary("color");
final Graph<?> g = format.parse(file);
final int vertices = g.nodes().size();
final List<Object> atoms = new ArrayList<Object>(vertices+colors);
atoms.addAll(g.nodes());
for(int i = 0 ; i < colors; i++) { atoms.add(new Color(i)); }
final Universe u = new Universe(atoms);
final TupleFactory f = u.factory();
bounds = new Bounds(u);
bounds.boundExactly(vertex, f.range(f.tuple(atoms.get(0)), f.tuple(atoms.get(vertices-1))));
bounds.boundExactly(color, f.range(f.tuple(atoms.get(vertices)), f.tuple(atoms.get(atoms.size()-1))));
bounds.bound(v2c, bounds.upperBound(vertex).product(bounds.upperBound(color)));
final TupleSet edgeBound = f.noneOf(2);
for(Object from : g.nodes()) {
for (Object to : g.edges(from))
edgeBound.add(f.tuple(from, to));
}
// for(Object from : g.nodes()) {
// System.out.println(from + ": " + g.edges(from).size());
// }
bounds.boundExactly(edges, edgeBound);
System.out.println("vertices: " + vertices + ", edges: " + edgeBound.size());
}
private static final class Color {
final int value;
Color(int value) { this.value = value; }
public String toString() { return "color"+value; }
}
/**
* Returns a formula stating that all vertices
* have one color, and that no two adjacent
* vertices have intersecting colors.
* @return a formula stating that all vertices
* have one color, and that no two adjacent
* vertices have intersecting colors.
*/
public Formula coloring() {
final Variable v = Variable.unary("v");
final Expression vcolor = v.join(v2c);
final Formula f0 = vcolor.one();
final Formula f1 = vcolor.intersection(v.join(edges).join(v2c)).no();
return f0.and(f1).forAll(v.oneOf(vertex));
}
/**
* Returns the bounds for this coloring problem.
* @return bounds for this coloring problem
*/
public Bounds bounds() {
return bounds.unmodifiableView();
}
private static void usage() {
System.out.println("Usage: java examples.classicnp.GraphColoring <filename> <DIMACS | ASP | ASP_EDGES> <# of colors>");
System.exit(1);
}
/**
* Usage: java examples.classicnp.GraphColoring <filename> <DIMACS | ASP | ASP_EDGES> <# of colors>
*/
public static void main(String[] args) {
if (args.length!=3) usage();
try {
final GraphColoring model = new GraphColoring(args[0], Enum.valueOf(Graph.Format.class, args[1].toUpperCase()), Integer.parseInt(args[2]));
final Solver solver = new Solver();
solver.options().setSolver(SATFactory.MiniSat);
solver.options().setSymmetryBreaking(0);
solver.options().setReporter(new ConsoleReporter());
final Formula f = model.coloring();
final Bounds b = model.bounds();
final Solution sol = solver.solve(f, b);
System.out.println(sol.outcome());
System.out.println(sol.stats());
//if (sol.instance()!=null)
// System.out.println("coloring: "+sol.instance().tuples(model.v2c));
} catch (NumberFormatException e) { usage(); }
}
}