00001 /*****************************************************************************/ 00002 /*! 00003 *\file dpllt.h 00004 *\brief Generic DPLL(T) module 00005 * 00006 * Author: Clark Barrett 00007 * 00008 * Created: Mon Dec 12 16:28:08 2005 00009 */ 00010 /*****************************************************************************/ 00011 00012 #ifndef _cvcl__include__dpllt_h_ 00013 #define _cvcl__include__dpllt_h_ 00014 00015 #include "cnf.h" 00016 00017 namespace SAT { 00018 00019 class DPLLT { 00020 public: 00021 00022 enum Result {UNSAT, SATISFIABLE, ABORT }; 00023 enum ConsistentResult {INCONSISTENT, MAYBE_CONSISTENT, CONSISTENT }; 00024 00025 class TheoryAPI { 00026 public: 00027 TheoryAPI() {} 00028 virtual ~TheoryAPI() {} 00029 00030 //! Set a checkpoint for backtracking 00031 virtual void push() = 0; 00032 //! Restore most recent checkpoint 00033 virtual void pop() = 0; 00034 00035 //! Notify theory when a literal is set to true 00036 virtual void assertLit(Lit l) = 0; 00037 00038 //! Check consistency of the current assignment. 00039 /*! The result is either INCONSISTENT, MAYBE_CONSISTENT, or CONSISTENT 00040 * Most of the time, fullEffort should be false, and the result will most 00041 * likely be either INCONSISTENT or MAYBE_CONSISTENT. To force a full 00042 * check, set fullEffort to true. When fullEffort is set to true, the 00043 * only way the result can be MAYBE_CONSISTENT is if there are new clauses 00044 * to get (via getNewClauses). 00045 * \param c should be empty initially. If INCONSISTENT is returned, 00046 * then c will contain a conflict clause when it returns. Otherwise, c is 00047 * unchanged. 00048 */ 00049 virtual ConsistentResult checkConsistent(Clause& c, bool fullEffort) = 0; 00050 00051 //! Get a literal that is implied by the current assignment. 00052 /*! This is theory propagation. It can be called repeatedly and returns a 00053 * Null literal when there are no more literals to propagate. It should 00054 * only be called when the assignment is not known to be inconsistent. 00055 */ 00056 virtual Lit getImplication() = 0; 00057 00058 //! Get an explanation for a literal that was implied 00059 /*! Given a literal l that is true in the current assignment as a result of 00060 * an earlier call to getImplication(), this method returns a clause which 00061 * justifies the propagation of that literal. The clause will contain the 00062 * literal l as well as other literals that are in the current assignment. 00063 * The clause is such that it would have caused a unit propagation at the 00064 * time getImplication() was called. 00065 * \param c should be empty initially. */ 00066 virtual void getExplanation(Lit l, Clause& c) = 0; 00067 00068 //! Get new clauses from the theory. 00069 /*! This is extended theory learning. Returns false if there are no new 00070 * clauses to get. Otherwise, returns true and new clauses are added to 00071 * cnf. Note that the new clauses (if any) are theory lemmas, i.e. clauses 00072 * that are valid in the theory and not dependent on the current 00073 * assignment. The clauses may contain new literals as well as literals 00074 * that are true in the current assignment. 00075 * \param cnf should be empty initially. */ 00076 virtual bool getNewClauses(CNF_Formula& cnf) = 0; 00077 00078 }; 00079 00080 class Decider { 00081 public: 00082 Decider() {} 00083 virtual ~Decider() {} 00084 00085 //! Make a decision. 00086 /* Returns a NULL Lit if there are no more decisions to make */ 00087 virtual Lit makeDecision() = 0; 00088 00089 }; 00090 00091 protected: 00092 TheoryAPI* d_theoryAPI; 00093 Decider* d_decider; 00094 00095 public: 00096 //! Constructor 00097 /*! The client constructing DPLLT must provide an implementation of 00098 * TheoryAPI. It may also optionally provide an implementation of Decider. 00099 * If decider is NULL, then the DPLLT class must make its own decisions. 00100 */ 00101 DPLLT(TheoryAPI* theoryAPI, Decider* decider) 00102 : d_theoryAPI(theoryAPI), d_decider(decider) {} 00103 virtual ~DPLLT() {} 00104 00105 TheoryAPI* theoryAPI() { return d_theoryAPI; } 00106 Decider* decider() { return d_decider; } 00107 00108 //! Check the satisfiability of a set of clauses in the current context 00109 /*! If the result is SATISFIABLE, the DPLLT engine should remain in the state 00110 * containing the satisfiable assignment until returnFromSat() is called. If 00111 * the result is UNSAT or ABORT, the DPLLT engine should return to the state 00112 * it was in when called. Note that it should be possible to call checkSat 00113 * multiple times, even if the result is true (each additional call should 00114 * use the context left by the previous call). 00115 */ 00116 virtual Result checkSat(const CNF_Formula& cnf) = 0; 00117 00118 //! Continue checking the last check with additional constraints 00119 /*! Should only be called after a previous call to checkSat (or 00120 * continueCheck) that returned SATISFIABLE. It should add the clauses in 00121 * cnf to the existing clause database and search for a satisfying 00122 * assignment. As with checkSat, if the result is SATISFIABLE, the DPLLT 00123 * engine should remain in the state containing the satisfiable assignment 00124 * until returnFromSat() is called. Note that returnFromSat should return to 00125 * the state just before the last call to checkSat, NOT the last call to 00126 * continueCheck. Similarly, if the result is UNSAT or ABORT, the DPLLT 00127 * engine should return to the state it was in when checkSat was last called. 00128 */ 00129 virtual Result continueCheck(const CNF_Formula& cnf) = 0; 00130 00131 //! Get value of variable: unassigned, false, or true 00132 virtual Var::Val getValue(Var v) = 0; 00133 00134 //! Return to the state just before the last satisfiable call to checkSat 00135 /*! Each time a call to checkSat returns SATISFIABLE, the resulting 00136 * assignment is retained. Multiple calls to checkSat can be used to refine 00137 * assignments, adding additional constraints each time. returnFromSat() 00138 * returns to the state just before the last call to checkSat which returned 00139 * SATISFIABLE. */ 00140 virtual void returnFromSat() = 0; 00141 00142 }; 00143 00144 } 00145 00146 #endif