package kodkod.examples.csp;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import kodkod.ast.Formula;
import kodkod.ast.Relation;
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.TupleSet;
import kodkod.instance.Universe;
public class GraphColoring2 {
private final Relation[] vcolors;
private final int[][] graph;
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 GraphColoring2(String file, Graph.Format format, int colors) {
assert colors > 0;
final Graph<?> g = format.parse(file);
final int vertices = g.nodes().size();
vcolors = new Relation[vertices];
for(int i = 0; i < vertices; i++) {
vcolors[i] = Relation.unary("v"+i+"color");
}
final List<Object> atoms = new ArrayList<Object>(colors);
for(int i = 0 ; i < colors; i++) { atoms.add(new Color(i)); }
final Universe u = new Universe(atoms);
bounds = new Bounds(u);
final TupleSet all = u.factory().allOf(1);
for(Relation r : vcolors) {
bounds.bound(r, all);
}
graph = new int[vertices][];
final Map<Object,Integer> ids = new LinkedHashMap<Object, Integer>();
int i = 0;
for(Object n : g.nodes()) {
ids.put(n, i++);
}
i = 0;
for(Object n : g.nodes()) {
final Set<?> neighbors = g.edges(n);
graph[i] = new int[neighbors.size()];
int j = 0;
for(Object neighbor : neighbors) {
graph[i][j++] = ids.get(neighbor);
}
i++;
}
}
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 List<Formula> formulas = new ArrayList<Formula>(vcolors.length);
for(Relation r : vcolors) {
formulas.add( r.one() );
}
for(int i = 0; i < vcolors.length; i++) {
final int[] neighbors = graph[i];
final int max = neighbors.length;
final Relation vcolor = vcolors[i];
for(int j = 0; j < max; j++) {
formulas.add( vcolor.intersection(vcolors[neighbors[j]]).no() );
}
}
return Formula.and(formulas);
}
/**
* 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 GraphColoring2 model = new GraphColoring2(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(); }
}
}