/* * 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.engine; import kodkod.instance.Instance; /** * Represents the full solution to a formula: an * instance if the formula is satisfiable or a * proof of unsatisfiability if not. * * @specfield formula: Formula // the formula being solved * @specfield bounds: Bounds // the bounds on the formula * @author Emina Torlak */ public final class Solution { private final Outcome outcome; private final Statistics stats; private final Instance instance; private final Proof proof; /** * Constructs a Solution from the given values. * @requires outcome != null && stats != null * @requires outcome = SATISFIABLE || TRIVIALLY_SATISFIABLE => instance != null */ private Solution(Outcome outcome, Statistics stats, Instance instance, Proof proof) { assert outcome != null && stats != null; this.outcome = outcome; this.stats = stats; this.instance = instance; this.proof = proof; } /** * Returns a new Solution with a SATISFIABLE outcome, given stats and instance. * @return {s: Solution | s.outcome() = SATISFIABLE && s.stats() = stats && s.instance() = instance } */ static Solution satisfiable(Statistics stats, Instance instance) { return new Solution(Outcome.SATISFIABLE, stats, instance, null); } /** * Returns a new Solution with a TRIVIALLY_SATISFIABLE outcome, given stats and instance. * @return {s: Solution | s.outcome() = TRIVIALLY_SATISFIABLE && s.stats() = stats && s.instance() = instance } */ static Solution triviallySatisfiable(Statistics stats, Instance instance) { return new Solution(Outcome.TRIVIALLY_SATISFIABLE, stats, instance, null); } /** * Returns a new Solution with a UNSATISFIABLE outcome, given stats and proof. * @return {s: Solution | s.outcome() = UNSATISFIABLE && s.stats() = stats && s.proof() = proof } */ static Solution unsatisfiable(Statistics stats, Proof proof) { return new Solution(Outcome.UNSATISFIABLE, stats, null, proof); } /** * Returns a new Solution with a TRIVIALLY_UNSATISFIABLE outcome, given stats and proof. * @return {s: Solution | s.outcome() = TRIVIALLY_UNSATISFIABLE && s.stats() = stats && s.proof() = proof } */ static Solution triviallyUnsatisfiable(Statistics stats, Proof proof) { return new Solution(Outcome.TRIVIALLY_UNSATISFIABLE, stats, null, proof); } /** * Returns the outcome of the attempt to find * a model for this.formula. If the outcome is * SATISFIABLE or TRIVIALLY_SATISFIABLE, a satisfying * instance can be obtained by calling {@link #instance()}. * If the formula is UNSATISFIABLE, a proof of unsatisfiability * can be obtained by calling {@link #proof()} provided that * translation logging was enabled and the unsatisfiability was * determined using a core extracting * {@link kodkod.engine.satlab.SATSolver sat solver}. * Lastly, if the returned Outcome is * or TRIVIALLY_UNSATISFIABLE, a proof of unsatisfiability can * be obtained by calling {@link #proof()} provided that * translation logging was enabled. * @return an Outcome instance designating the * satisfiability of this.formula with respect to this.bounds */ public Outcome outcome() { return outcome; } /** * Returns true iff this solution has a (trivially) satisfiable outcome. * @return this.outcome = Outcome.SATISFIABLE || this.outcome = Outcome.TRIVIALLY_SATISFIABLE */ public final boolean sat() { return outcome==Outcome.SATISFIABLE || outcome==Outcome.TRIVIALLY_SATISFIABLE; } /** * Returns true iff this solution has a (trivially) unsatisfiable outcome. * @return this.outcome = Outcome.UNSATISFIABLE || this.outcome = Outcome.TRIVIALLY_UNSATISFIABLE */ public final boolean unsat() { return outcome==Outcome.UNSATISFIABLE || outcome==Outcome.TRIVIALLY_UNSATISFIABLE; } /** * Returns a satisfiying instance for this.formula, if the * value returned by {@link #outcome() this.outcome()} is either * SATISFIABLE or TRIVIALLY_SATISFIABLE. Otherwise returns null. * @return a satisfying instance for this.formula, if one exists. */ public Instance instance() { return instance; } /** * Returns a proof of this.formula's unsatisfiability if the value * returned by {@link #outcome() this.outcome()} is UNSATISFIABLE or * TRIVIALLY_UNSATISFIABLE, translation logging was enabled during solving, * and a core extracting {@link kodkod.engine.satlab.SATProver sat solver} (if any) * was used to determine unsatisfiability. * Otherwise, null is returned. * @return a proof of this.formula's unsatisfiability, if one is available. */ public Proof proof() { return proof; } /** * Returns the statistics gathered while solving * this.formula. * @return the statistics gathered while solving * this.formula. */ public Statistics stats() { return stats; } /** * Returns a string representation of this Solution. * @return a string representation of this Solution. */ public String toString() { final StringBuilder b = new StringBuilder(); b.append("---OUTCOME---\n"); b.append(outcome); b.append("\n"); if (instance!=null) { b.append("\n---INSTANCE---\n"); b.append(instance); b.append("\n"); } if (proof!=null) { b.append("\n---PROOF---\n"); b.append(proof); b.append("\n"); } b.append("\n---STATS---\n"); b.append(stats); b.append("\n"); return b.toString(); } /** * Enumerates the possible outcomes of an attempt * to find a model for a FOL formula. */ public static enum Outcome { /** The formula is satisfiable with respect to the specified bounds. */ SATISFIABLE, /** The formula is unsatisfiable with respect to the specified bounds. */ UNSATISFIABLE, /** * The formula is trivially satisfiable with respect to the specified bounds: * a series of simple transformations reduces the formula to the constant TRUE. **/ TRIVIALLY_SATISFIABLE, /** * The formula is trivially unsatisfiable with respect to the specified bounds: * a series of simple transformations reduces the formula to the constant FALSE. */ TRIVIALLY_UNSATISFIABLE; } }