search_impl_base.h

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file search.h
00004  * \brief Abstract API to the proof search engine
00005  * 
00006  * Author: Clark Barrett, Vijay Ganesh (Clausal Normal Form Converter)
00007  * 
00008  * Created: Fri Jan 17 13:35:03 2003
00009  *
00010  * <hr>
00011  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00012  * Junior University and by New York University. 
00013  *
00014  * License to use, copy, modify, sell and/or distribute this software
00015  * and its documentation for any purpose is hereby granted without
00016  * royalty, subject to the terms and conditions defined in the \ref
00017  * LICENSE file provided with this distribution.  In particular:
00018  *
00019  * - The above copyright notice and this permission notice must appear
00020  * in all copies of the software and related documentation.
00021  *
00022  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00023  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00024  * 
00025  * <hr>
00026  * 
00027  */
00028 /*****************************************************************************/
00029 
00030 #ifndef _cvcl__include__search_impl_base_h_
00031 #define _cvcl__include__search_impl_base_h_
00032 
00033 #include "search.h"
00034 #include "assumptions_value.h"
00035 #include "theory_core.h"
00036 #include "variable.h"
00037 
00038 namespace CVCL {
00039 
00040 class SearchEngineRules;
00041 class VariableManager;
00042 
00043   /*! \defgroup SE Search Engine 
00044    * \ingroup VC
00045    * Implementation of a search engine, a.k.a. the SAT Solver.  It
00046    * consists of a generic abstract API (class SearchEngine) and its
00047    * subclasses implementing concrete instances of search engines.
00048    */
00049 
00050   //! API to to a generic proof search engine (a.k.a. SAT solver) 
00051   /*! \ingroup SE */
00052 class SearchImplBase :public SearchEngine {
00053   friend class DecisionEngine;
00054 protected:
00055   /*! \addtogroup SE 
00056    * @{
00057    */
00058   //! Variable manager for classes Variable and Literal
00059   VariableManager* d_vm;
00060 
00061   /*! @brief The bottom-most scope for the current call to checkSAT (where conflict
00062     clauses are still valid).
00063   */
00064   CDO<int> d_bottomScope;
00065 
00066   TheoryCore::CoreSatAPI* d_coreSatAPI_implBase;
00067 
00068   //! Representation of a DP-suggested splitter
00069   class Splitter {
00070     Literal d_lit;
00071   public:
00072     // int priority;
00073     //! Constructor
00074     Splitter(const Literal& lit);
00075     //! Copy constructor
00076     Splitter(const Splitter& s);
00077     //! Assignment
00078     Splitter& operator=(const Splitter& s);
00079     //! Descructor
00080     ~Splitter();
00081     operator Literal() { return d_lit; }
00082     //! The order is descending by priority ("reversed", highest first)
00083 //     friend bool operator<(const Splitter& s1, const Splitter& s2) {
00084 //       return (s1.priority > s2.priority
00085 //            || (s1.priority == s2.priority && s1.expr > s2.expr));
00086 //     }
00087   };
00088   //! Backtracking ordered set of DP-suggested splitters
00089   CDList<Splitter> d_dpSplitters;
00090 
00091   /*! @brief Theorem from the last successful checkValid call.  It is
00092     used by getProof and getAssumptions. */
00093   Theorem d_lastValid;
00094   /*! @brief Assumptions from the last unsuccessful checkValid call.
00095     These are used by getCounterExample. */
00096   ExprHashMap<bool> d_lastCounterExample;
00097   /*! @brief Maintain the list of current assumptions (user asserts and
00098    splitters) for getAssumptions(). */
00099   CDMap<Expr,Theorem> d_assumptions;
00100 
00101   //! Backtracking cache for the CNF generator
00102   CDMap<Expr, Theorem> d_cnfCache;
00103   //! Backtracking set of new variables generated by CNF translator
00104   /*! Specific search engines do not have to split on these variables */
00105   CDMap<Expr, bool> d_cnfVars;
00106   //! Command line flag whether to convert to CNF
00107   const bool* d_cnfOption;
00108   //! Flag: whether to convert term ITEs into CNF
00109   const bool* d_ifLiftOption;
00110   //! Flag: ignore auxiliary CNF variables when searching for a splitter
00111   const bool* d_ignoreCnfVarsOption;
00112   //! Flag: Preserve the original formula with +cnf (for splitter heuristics)
00113   const bool* d_origFormulaOption;
00114 
00115   /*!
00116    * \name CNF Caches 
00117    *
00118    * These caches are for subexpressions of the translated formula
00119    * phi, to avoid expanding phi into a tree.  We cannot use
00120    * d_cnfCache for that, since it is effectively non-backtracking,
00121    * and we do not know if a subexpression of phi was translated at
00122    * the current level, or at some other (inactive) branch of the
00123    * decision tree.
00124    * @{
00125    */
00126   //! Cache for enqueueCNF()
00127   CDMap<Expr,bool> d_enqueueCNFCache;
00128   //! Cache for applyCNFRules()
00129   CDMap<Expr,bool> d_applyCNFRulesCache;
00130   //! Cache for replaceITE()
00131   CDMap<Expr,Theorem> d_replaceITECache;
00132   /*@}*/ // End of CNF Caches
00133 
00134   //! Construct a Literal out of an Expr or return an existing one
00135   Literal newLiteral(const Expr& e) { return Literal(d_vm, e); }
00136 
00137   /*! @brief Our version of simplifier: take Theorem(e), apply
00138     simplifier to get Theorem(e==e'), return Theorem(e') */
00139   Theorem simplify(const Theorem& e)
00140     { return d_core->iffMP(e, d_core->simplify(e.getExpr(), false)); }
00141 
00142   //! Notify the search engine about a new literal fact.
00143   /*! It should be called by SearchEngine::addFact() only.
00144    *  Must be implemented by the subclasses of SearchEngine.
00145    *
00146    * IMPORTANT: do not call addFact() from this function; use
00147    * enqueueFact() or setInconsistent() instead.
00148    */
00149   virtual void addLiteralFact(const Theorem& thm) = 0;
00150   //! Notify the search engine about a new non-literal fact.
00151   /*! It should be called by SearchEngine::addFact() only.
00152    *  Must be implemented by the subclasses of SearchEngine.
00153    *
00154    * IMPORTANT: do not call addFact() from this function; use
00155    * enqueueFact() or setInconsistent() instead.
00156    */
00157   virtual void addNonLiteralFact(const Theorem& thm) = 0;
00158   //! Add a new fact to the search engine bypassing CNF converter
00159   /*! Calls either addLiteralFact() or addNonLiteralFact()
00160    * appropriately, and converts to CNF when d_cnfOption is set.  If
00161    * fromCore==true, this fact already comes from the core, and
00162    * doesn't need to be reported back to the core.
00163    */
00164   void addCNFFact(const Theorem& thm, bool fromCore=false);
00165 
00166  public:
00167 
00168   int getBottomScope() { return d_bottomScope; }
00169 
00170   //! Check if e is a clause (a literal, or a disjunction of literals)
00171   bool isClause(const Expr& e);
00172 
00173   //! Check if e is a propositional clause
00174   /*! \sa isPropAtom() */
00175   bool isPropClause(const Expr& e);
00176   //! Check whether e is a fresh variable introduced by the CNF converter
00177   /*! Search engines do not need to split on those variables in order
00178    * to be complete
00179    */
00180   bool isCNFVar(const Expr& e) { return (d_cnfVars.count(e) > 0); }
00181   //! Check if a splitter is required for completeness
00182   /*! Currently, it checks that 'e' is not an auxiliary CNF variable */
00183   bool isGoodSplitter(const Expr& e);
00184 
00185  private:
00186 
00187   //! Translate theta to CNF and enqueue the new clauses
00188   void enqueueCNF(const Theorem& theta);
00189   //! Recursive version of enqueueCNF()
00190   void enqueueCNFrec(const Theorem& theta);
00191   //! FIXME: write a comment
00192   void applyCNFRules(const Theorem& e);
00193   
00194   //! Cache a theorem phi <=> v by phi, where v is a literal.
00195   void addToCNFCache(const Theorem& thm);
00196 
00197   //! Find a theorem phi <=> v by phi, where v is a literal.
00198   /*! \return Null Theorem if not found. */
00199   Theorem findInCNFCache(const Expr& e);
00200 
00201   //! Replaces ITE subexpressions in e with variables
00202   Theorem replaceITE(const Expr& e);
00203   
00204 protected:
00205 
00206   //! Return the current scope level (for convenience)
00207   int scopeLevel() { return d_core->getCM()->scopeLevel(); }
00208 
00209 public:
00210   //! Constructor
00211   SearchImplBase(TheoryCore* core);
00212   //! Destructor
00213   virtual ~SearchImplBase();
00214 
00215   virtual void registerAtom(const Expr& e) { d_core->registerAtom(e); }
00216   virtual Theorem getImpliedLiteral() { return d_core->getImpliedLiteral(); }
00217 
00218   ///////////////////////////////////////////////////////////////////////////
00219   // checkValid() is the method that subclasses must implement.
00220   ///////////////////////////////////////////////////////////////////////////
00221 
00222   //! Checks the validity of a formula in the current context
00223   /*! The method that actually calls the SAT solver (implemented in a
00224     subclass).  It should maintain d_assumptions (add all asserted
00225     splitters to it), and set d_lastValid and d_lastCounterExample
00226     appropriately before exiting. */
00227   virtual bool checkValidInternal(const Expr& e) = 0;
00228   //! Similar to checkValid(), only returns Theorem(e) or Null
00229   virtual Theorem checkValid(const Expr& e);
00230   //! Reruns last check with e as an additional assumption
00231   virtual bool restartInternal(const Expr& e) = 0;
00232   //! Reruns last check with e as an additional assumption
00233   virtual Theorem restart(const Expr& e);
00234   void returnFromCheck() { restart(d_core->falseExpr()); }
00235   virtual Theorem lastThm() { return d_lastValid; }
00236 
00237   ///////////////////////////////////////////////////////////////////////////
00238   // The following methods are provided by the base class, and in most
00239   // cases should be sufficient.  However, they are virtual so that
00240   // subclasses can add functionality to them if needed.
00241   ///////////////////////////////////////////////////////////////////////////
00242 
00243   /*! @brief Generate and add a new assertion to the set of assertions
00244     in the current context.  This should only be used by class VCL in
00245     assertFormula(). */
00246   Theorem newUserAssumption(const Expr& e, int scope = -1);
00247   //! Add a new internal asserion
00248   virtual Theorem newIntAssumption(const Expr& e);
00249   //! Helper for above function
00250   void newIntAssumption(const Theorem& thm);
00251   //! Get all assertions made in this and all previous contexts.
00252   /*! \param assertions should be an empty vector which will be filled \
00253     with the assertions */
00254   void getUserAssumptions(std::vector<Expr>& assumptions);
00255   void getInternalAssumptions(std::vector<Expr>& assumptions);
00256   virtual void getAssumptions(std::vector<Expr>& assumptions);
00257   //! Check if the formula has been assumed
00258   virtual bool isAssumption(const Expr& e);
00259 
00260   //! Add a new fact to the search engine from the core
00261   /*! It should be called by TheoryCore::assertFactCore(). */
00262   void addFact(const Theorem& thm);
00263 
00264   //! Suggest a splitter to the SearchEngine
00265   /*! The higher is the priority, the sooner the SAT solver will split
00266    * on it.  It can be positive or negative (default is 0).
00267    *
00268    * The set of suggested splitters is backtracking; that is, a
00269    * splitter is "forgotten" once the scope is backtracked.
00270    *
00271    * This method can be used either to change the priority
00272    * of existing splitters, or to introduce new splitters that DPs
00273    * consider relevant, even though they do not appear in existing
00274    * formulas.
00275    */
00276   virtual void addSplitter(const Expr& e, int priority);
00277   
00278   virtual void getCounterExample(std::vector<Expr>& assertions, bool inOrder = true);
00279 
00280   // The following two methods should be called only after a checkValid
00281   // which returns true.  In any other case, they return Null values.
00282 
00283   //! Returns the proof term for the last proven query
00284   /*! It should be called only after a checkValid which returns true.
00285     In any other case, it returns Null. */
00286   virtual Proof getProof();
00287   /*! @brief Returns the set of assumptions used in the proof.  It
00288     should be a subset of getAssumptions(). */
00289   /*! It should be called only after a checkValid which returns true.
00290     In any other case, it returns Null. */
00291   virtual const Assumptions getAssumptionsUsed();
00292 
00293   //! Process result of checkValid
00294   bool processResult(const Theorem& res, const Expr& e);
00295 
00296   /* @} */ // end of group SE
00297 
00298 };
00299 
00300 
00301 }
00302 
00303 #endif

Generated on Thu Apr 13 16:57:33 2006 for CVC Lite by  doxygen 1.4.4