/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang * * 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 edu.mit.csail.sdg.alloy4compiler.translator; import java.io.Serializable; import java.util.prefs.Preferences; import edu.mit.csail.sdg.alloy4.ErrorAPI; import edu.mit.csail.sdg.alloy4.SafeList; import edu.mit.csail.sdg.alloy4.Util; /** Mutable; this class encapsulates the customizable options of the Alloy-to-Kodkod translator. */ public final class A4Options implements Serializable { /** This enum defines the set of possible SAT solvers. */ public static final class SatSolver implements Serializable { /** This ensures the class can be serialized reliably. */ private static final long serialVersionUID = 0; /** List of all existing SatSolver values. */ private static final SafeList<SatSolver> values = new SafeList<SatSolver>(); /** This is a unique String for this value; it should be kept consistent in future versions. */ private final String id; /** This is the label that the toString() method will return. */ private final String toString; /** If not null, this is the external command-line solver to use. */ private final String external; /** If not null, this is the set of options to use with the command-line solver. */ private final String[] options; /** Constructs a new SatSolver value. */ private SatSolver(String id, String toString, String external, String[] options, boolean add) { this.id=id; this.toString=toString; this.external=external; this.options=new String[options!=null ? options.length : 0]; for(int i=0; i<this.options.length; i++) this.options[i] = options[i]; if (add) { synchronized(SatSolver.class) { values.add(this); } } } /** Constructs a new SatSolver value that uses a command-line solver; throws ErrorAPI if the ID is already in use. */ public static SatSolver make(String id, String toString, String external, String[] options) throws ErrorAPI { if (id==null || toString==null || external==null) throw new ErrorAPI("NullPointerException in SatSolver.make()"); SatSolver ans = new SatSolver(id, toString, external, options, false); synchronized(SatSolver.class) { for(SatSolver x: values) if (x.id.equals(id)) throw new ErrorAPI("The SatSolver id \""+id+"\" is already in use."); values.add(ans); } return ans; } /** Constructs a new SatSolver value that uses a command-line solver; throws ErrorAPI if the ID is already in use. */ public static SatSolver make(String id, String toString, String external) throws ErrorAPI { return make(id, toString, external, null); } /** Returns the executable for the external command-line solver to use (or null if this solver does not use an external commandline solver) */ public String external() { return external; } /** Returns the options for the external command-line solver to use (or empty array if this solver does not use an external commandline solver) */ public String[] options() { if (external==null || options.length==0) return new String[0]; String[] ans = new String[options.length]; for(int i=0; i<ans.length; i++) ans[i] = options[i]; return ans; } /** Returns the unique String for this value; it will be kept consistent in future versions. */ public String id() { return id; } /** Returns the list of SatSolver values. */ public static SafeList<SatSolver> values() { SafeList<SatSolver> ans; synchronized(SatSolver.class) { ans=values.dup(); } return ans; } /** Returns the human-readable label for this enum value. */ @Override public String toString() { return toString; } /** Ensures we can use == to do comparison. */ private Object readResolve() { synchronized(SatSolver.class) { for(SatSolver x:values) if (x.id.equals(id)) return x; values.add(this); } return this; } /** Given an id, return the enum value corresponding to it (if there's no match, then return SAT4J). */ public static SatSolver parse(String id) { synchronized(SatSolver.class) { for(SatSolver x:values) if (x.id.equals(id)) return x; } return SAT4J; } /** Saves this value into the Java preference object. */ public void set() { Preferences.userNodeForPackage(Util.class).put("SatSolver2",id); } /** Reads the current value of the Java preference object (if it's not set, then return SAT4J). */ public static SatSolver get() { return parse(Preferences.userNodeForPackage(Util.class).get("SatSolver2","")); } /** BerkMin via pipe */ public static final SatSolver BerkMinPIPE = new SatSolver("berkmin", "BerkMin", "berkmin", null, true); /** Spear via pipe */ public static final SatSolver SpearPIPE = new SatSolver("spear", "Spear", "spear", new String[]{"--model", "--dimacs"}, true); /** MiniSat1 via JNI */ public static final SatSolver MiniSatJNI = new SatSolver("minisat(jni)", "MiniSat", null, null, true); /** MiniSatProver1 via JNI */ public static final SatSolver MiniSatProverJNI = new SatSolver("minisatprover(jni)", "MiniSat with Unsat Core", null, null, true); /** ZChaff via JNI */ public static final SatSolver ZChaffJNI = new SatSolver("zchaff(jni)", "ZChaff", null, null, true); /** SAT4J using native Java */ public static final SatSolver SAT4J = new SatSolver("sat4j", "SAT4J", null, null, true); /** Outputs the raw CNF file only */ public static final SatSolver CNF = new SatSolver("cnf", "Output CNF to file", null, null, true); /** Outputs the raw Kodkod file only */ public static final SatSolver KK = new SatSolver("kodkod", "Output Kodkod to file", null, null, true); } /** This ensures the class can be serialized reliably. */ private static final long serialVersionUID = 0; /** Constructs an A4Options object with default values for everything. */ public A4Options() { } /** This option specifies the amount of symmetry breaking to do (when symmetry breaking isn't explicitly disabled). * * <p> If a formula is unsatisfiable, then in general, the higher this value, * the faster you finish the solving. But if this value is too high, it will instead slow down the solving. * * <p> If a formula is satisfiable, then in general, the lower this value, the faster you finish the solving. * Setting this value to 0 usually gives the fastest solve. * * <p> Default value is 20. */ public int symmetry = 20; /** This option specifies the maximum skolem-function depth. * <p> Default value is 0, which means it will only generate skolem constants, and will not generate skolem functions. */ public int skolemDepth = 0; /** This option specifies the unsat core minimization strategy (0=GuaranteedLocalMinimum 1=FasterButLessAccurate 2=EvenFaster...) * <p> Default value is set to the fastest current strategy. */ public int coreMinimization = 2; /** Unsat core granularity, default is 0 (only top-level conjuncts are considered), 3 expands all quantifiers */ public int coreGranularity = 0; /** This option specifies the SAT solver to use (SAT4J, MiniSatJNI, MiniSatProverJNI, ZChaffJNI...) * <p> Default value is SAT4J. */ public SatSolver solver = SatSolver.SAT4J; /** When this.solver is external, and the solver filename is a relative filename, then this option specifies * the directory that the solver filename is relative to. */ public String solverDirectory = ""; /** This specifies the directory where we may write temporary files to. */ public String tempDirectory = System.getProperty("java.io.tmpdir"); /** This option tells the compiler the "original filename" that these AST nodes came from; * it is only used for generating comments and other diagnostic messages. * <p> Default value is "". */ public String originalFilename = ""; /** This option specifies whether the compiler should record * the original Kodkod formula being generated and the resulting Kodkod instances. * <p> Default value is false. */ public boolean recordKodkod = false; /** This option specifies whether the solver should report only solutions * that don't cause any overflows. */ public boolean noOverflow = false; /** This option constrols how deep we unroll loops and unroll recursive predicate/function/macros (negative means it's disallowed) */ public int unrolls = (-1); /** This method makes a copy of this Options object. */ public A4Options dup() { A4Options x = new A4Options(); x.unrolls = unrolls; x.symmetry = symmetry; x.skolemDepth = skolemDepth; x.coreMinimization = coreMinimization; x.solver = solver; x.solverDirectory = solverDirectory; x.tempDirectory = tempDirectory; x.originalFilename = originalFilename; x.recordKodkod = recordKodkod; x.noOverflow = noOverflow; x.coreGranularity = coreGranularity; return x; } }