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