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 _cvc3__include__dpllt_h_ 00013 #define _cvc3__include__dpllt_h_ 00014 00015 #include "queryresult.h" 00016 #include "cnf.h" 00017 #include "cnf_manager.h" 00018 #include "proof.h" 00019 #include "theory_core.h" 00020 00021 namespace SAT { 00022 00023 class DPLLT { 00024 public: 00025 00026 enum ConsistentResult {INCONSISTENT, MAYBE_CONSISTENT, CONSISTENT }; 00027 00028 class TheoryAPI { 00029 public: 00030 TheoryAPI() {} 00031 virtual ~TheoryAPI() {} 00032 00033 //! Set a checkpoint for backtracking 00034 virtual void push() = 0; 00035 //! Restore most recent checkpoint 00036 virtual void pop() = 0; 00037 00038 //! Notify theory when a literal is set to true 00039 virtual void assertLit(Lit l) = 0; 00040 00041 //! Check consistency of the current assignment. 00042 /*! The result is either INCONSISTENT, MAYBE_CONSISTENT, or CONSISTENT 00043 * Most of the time, fullEffort should be false, and the result will most 00044 * likely be either INCONSISTENT or MAYBE_CONSISTENT. To force a full 00045 * check, set fullEffort to true. When fullEffort is set to true, the 00046 * only way the result can be MAYBE_CONSISTENT is if there are new clauses 00047 * to get (via getNewClauses). 00048 * \param cnf should be empty initially. If INCONSISTENT is returned, 00049 * then cnf will contain one or more clauses ruling out the current 00050 * assignment when it returns. Otherwise, cnf is unchanged. 00051 * \param fullEffort true for a full check, false for a fast check 00052 */ 00053 virtual ConsistentResult checkConsistent(CNF_Formula& cnf, bool fullEffort) = 0; 00054 00055 00056 //! Check if the work budget has been exceeded 00057 /*! If true, it means that the engine should quit and return ABORT. 00058 * Otherwise, it should proceed normally. This should be checked regularly. 00059 */ 00060 virtual bool outOfResources() = 0; 00061 00062 //! Get a literal that is implied by the current assignment. 00063 /*! This is theory propagation. It can be called repeatedly and returns a 00064 * Null literal when there are no more literals to propagate. It should 00065 * only be called when the assignment is not known to be inconsistent. 00066 */ 00067 virtual Lit getImplication() = 0; 00068 00069 //! Get an explanation for a literal that was implied 00070 /*! Given a literal l that is true in the current assignment as a result of 00071 * an earlier call to getImplication(), this method returns a set of clauses which 00072 * justifies the propagation of that literal. The clauses will contain the 00073 * literal l as well as other literals that are in the current assignment. 00074 * The clauses are such that they would have propagated l via unit 00075 * propagation at the time getImplication() was called. 00076 * \param l the literal 00077 * \param c should be empty initially. */ 00078 virtual void getExplanation(Lit l, CNF_Formula& c) = 0; 00079 00080 //! Get new clauses from the theory. 00081 /*! This is extended theory learning. Returns false if there are no new 00082 * clauses to get. Otherwise, returns true and new clauses are added to 00083 * cnf. Note that the new clauses (if any) are theory lemmas, i.e. clauses 00084 * that are valid in the theory and not dependent on the current 00085 * assignment. The clauses may contain new literals as well as literals 00086 * that are true in the current assignment. 00087 * \param cnf should be empty initially. */ 00088 virtual bool getNewClauses(CNF_Formula& cnf) = 0; 00089 00090 }; 00091 00092 class Decider { 00093 public: 00094 Decider() {} 00095 virtual ~Decider() {} 00096 00097 //! Make a decision. 00098 /* Returns a NULL Lit if there are no more decisions to make */ 00099 virtual Lit makeDecision() = 0; 00100 00101 }; 00102 00103 protected: 00104 TheoryAPI* d_theoryAPI; 00105 Decider* d_decider; 00106 00107 public: 00108 //! Constructor 00109 /*! The client constructing DPLLT must provide an implementation of 00110 * TheoryAPI. It may also optionally provide an implementation of Decider. 00111 * If decider is NULL, then the DPLLT class must make its own decisions. 00112 */ 00113 DPLLT(TheoryAPI* theoryAPI, Decider* decider) 00114 : d_theoryAPI(theoryAPI), d_decider(decider) {} 00115 virtual ~DPLLT() {} 00116 00117 TheoryAPI* theoryAPI() { return d_theoryAPI; } 00118 Decider* decider() { return d_decider; } 00119 00120 void setDecider(Decider* decider) { d_decider = decider; } 00121 00122 //! Set a checkpoint for backtracking 00123 /*! This should effectively save the current state of the solver. Note that 00124 * it should also result in a call to TheoryAPI::push. 00125 */ 00126 virtual void push() = 0; 00127 00128 //! Restore checkpoint 00129 /*! This should return the state to what it was immediately before the last 00130 * call to push. In particular, if one or more calls to checkSat, 00131 * continueCheck, or addAssertion have been made since the last push, these 00132 * should be undone. Note also that in this case, a single call to 00133 * DPLLT::pop may result in multiple calls to TheoryAPI::pop. 00134 */ 00135 virtual void pop() = 0; 00136 00137 //! Add new clauses to the SAT solver 00138 /*! This is used to add clauses that form a "context" for the next call to 00139 * checkSat 00140 */ 00141 virtual void addAssertion(const CNF_Formula& cnf) = 0; 00142 00143 virtual std::vector<SAT::Lit> getCurAssignments() =0 ; 00144 virtual std::vector<std::vector<SAT::Lit> > getCurClauses() =0 ; 00145 00146 //! Check the satisfiability of a set of clauses in the current context 00147 /*! If the result is SATISFIABLE, UNKNOWN, or ABORT, the DPLLT engine should 00148 * remain in the state it is in until pop() is called. If the result is 00149 * UNSATISFIABLE, the DPLLT engine should return to the state it was in when 00150 * called. Note that it should be possible to call checkSat multiple times, 00151 * even if the result is true (each additional call should use the context 00152 * left by the previous call). 00153 */ 00154 virtual CVC3::QueryResult checkSat(const CNF_Formula& cnf) = 0; 00155 00156 //! Continue checking the last check with additional constraints 00157 /*! Should only be called after a previous call to checkSat (or 00158 * continueCheck) that returned SATISFIABLE. It should add the clauses in 00159 * cnf to the existing clause database and search for a satisfying 00160 * assignment. As with checkSat, if the result is not UNSATISFIABLE, the 00161 * DPLLT engine should remain in the state containing the satisfiable 00162 * assignment until pop() is called. Similarly, if the result is 00163 * UNSATISFIABLE, the DPLLT engine should return to the state it was in when 00164 * checkSat was last called. 00165 */ 00166 virtual CVC3::QueryResult continueCheck(const CNF_Formula& cnf) = 0; 00167 00168 //! Get value of variable: unassigned, false, or true 00169 virtual Var::Val getValue(Var v) = 0; 00170 00171 //! Get the proof from SAT engine. 00172 virtual CVC3::Proof getSatProof(CNF_Manager*, CVC3::TheoryCore*) = 0 ; 00173 00174 }; 00175 00176 } 00177 00178 #endif