dpllt.h

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

Generated on Tue Jul 3 14:33:36 2007 for CVC3 by  doxygen 1.5.1