/* * 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 kodkod.ast.Formula; import kodkod.ast.Relation; import kodkod.engine.Evaluator; 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.Instance; import kodkod.instance.TupleFactory; import kodkod.instance.TupleSet; import kodkod.instance.Universe; /** * Reads a graph from a file, formatted using the DIMACS or the ASP (http://asparagus.cs.uni-potsdam.de/?action=instances&id=30) graph format, * and finds a Hamiltonian cycle in it if one exists. * * @author Emina Torlak */ public final class HamiltonianCycle { private final Relation vertex, start, edges, cycle; /** * Constructs an instance of the encoding. */ public HamiltonianCycle() { this.vertex = Relation.unary("Vertex"); this.start = Relation.unary("start"); this.edges = Relation.binary("edges"); this.cycle = Relation.binary("cycle"); } /** * Returns a formula that defines a Hamiltonian cycle. * @return a formula that defines a Hamiltonian cycle */ public Formula cycleDefinition() { final Formula f0 = cycle.function(edges.join(vertex), vertex.join(edges)); final Formula f1 = vertex.in(start.join(cycle.closure())); return f0.and(f1); } /** * Returns Bounds extracted from the graph * definition in the given file. * @requires file is in the specified format * @return Bounds extracted from the graph * definition in the given file. */ public Bounds bounds(String file, Graph.Format format) { final Graph<?> graph = format.parse(file); final Universe u = new Universe(graph.nodes()); final TupleFactory f = u.factory(); final Bounds b = new Bounds(u); b.boundExactly(vertex, f.allOf(1)); b.boundExactly(start, f.setOf(graph.start()==null ? u.atom(0) : graph.start())); final TupleSet edgeBound = f.noneOf(2); for(Object from : graph.nodes()) { for (Object to : graph.edges(from)) edgeBound.add(f.tuple(from, to)); } b.boundExactly(edges, edgeBound); b.bound(cycle, edgeBound); return b; } private static void usage() { System.out.println("Usage: examples.classicnp.HamiltonianCycle <graph file> <file format>"); System.exit(1); } private final boolean verify(Instance instance) { final Evaluator eval = new Evaluator(instance); System.out.println(eval.evaluate(cycle)); return eval.evaluate(cycleDefinition()); } /** * Usage: examples.classicnp.HamiltonianCycle <graph file> <DIMACS | ASP> */ public static void main(String[] args) { if (args.length!=2) usage(); final HamiltonianCycle model = new HamiltonianCycle(); final Formula f = model.cycleDefinition(); final Bounds b = model.bounds(args[0], Enum.valueOf(Graph.Format.class, args[1].toUpperCase())); System.out.println(f); System.out.println(b); final Solver solver = new Solver(); solver.options().setSolver(SATFactory.MiniSat); solver.options().setReporter(new ConsoleReporter()); // solver.options().setFlatten(false); final Solution s = solver.solve(f,b); System.out.println(s); if (s.instance()!=null) { System.out.print("verifying solution ... "); System.out.println(model.verify(s.instance()) ? "correct." : "incorrect!"); } } }