00001 /*****************************************************************************/ 00002 /*! 00003 * \file theory_core.h 00004 * 00005 * Author: Clark Barrett 00006 * 00007 * Created: Thu Jan 30 16:58:05 2003 00008 * 00009 * <hr> 00010 * 00011 * License to use, copy, modify, sell and/or distribute this software 00012 * and its documentation for any purpose is hereby granted without 00013 * royalty, subject to the terms and conditions defined in the \ref 00014 * LICENSE file provided with this distribution. 00015 * 00016 * <hr> 00017 * 00018 */ 00019 /*****************************************************************************/ 00020 00021 #ifndef _cvc3__include__theory_core_h_ 00022 #define _cvc3__include__theory_core_h_ 00023 00024 #include <queue> 00025 #include "theory.h" 00026 #include "cdmap.h" 00027 00028 namespace CVC3 { 00029 00030 class ExprTransform; 00031 class Statistics; 00032 class CoreProofRules; 00033 class Translator; 00034 00035 /*****************************************************************************/ 00036 /*! 00037 *\class TheoryCore 00038 *\ingroup Theories 00039 *\brief This theory handles the built-in logical connectives plus equality. 00040 * It also handles the registration and cooperation among all other theories. 00041 * 00042 * Author: Clark Barrett 00043 * 00044 * Created: Sat Feb 8 14:54:05 2003 00045 */ 00046 /*****************************************************************************/ 00047 class TheoryCore :public Theory { 00048 friend class Theory; 00049 00050 //! Context manager 00051 ContextManager* d_cm; 00052 00053 //! Theorem manager 00054 TheoremManager* d_tm; 00055 00056 //! Core proof rules 00057 CoreProofRules* d_rules; 00058 00059 //! Reference to command line flags 00060 const CLFlags& d_flags; 00061 00062 //! Reference to statistics 00063 Statistics& d_statistics; 00064 00065 //! PrettyPrinter (we own it) 00066 PrettyPrinter* d_printer; 00067 00068 //! Type Computer 00069 ExprManager::TypeComputer* d_typeComputer; 00070 00071 //! Expr Transformer 00072 ExprTransform* d_exprTrans; 00073 00074 //! Translator 00075 Translator* d_translator; 00076 00077 //! Assertion queue 00078 std::queue<Theorem> d_queue; 00079 //! Queue of facts to be sent to the SearchEngine 00080 std::vector<Theorem> d_queueSE; 00081 00082 //! Inconsistent flag 00083 CDO<bool> d_inconsistent; 00084 //! The set of reasons for incompleteness (empty when we are complete) 00085 CDMap<std::string, bool> d_incomplete; 00086 00087 //! Proof of inconsistent 00088 CDO<Theorem> d_incThm; 00089 //! List of all active terms in the system (for quantifier instantiation) 00090 CDList<Expr> d_terms; 00091 //! Map from active terms to theorems that introduced those terms 00092 std::hash_map<Expr, Theorem> d_termTheorems; 00093 00094 //! List of all active non-equality atomic formulas in the system (for quantifier instantiation) 00095 CDList<Expr> d_predicates; 00096 //! List of variables that were created up to this point 00097 CDList<Expr> d_vars; 00098 //! Database of declared identifiers 00099 std::map<std::string, Expr> d_globals; 00100 //! Bound variable stack: a vector of pairs <name, var> 00101 std::vector<std::pair<std::string, Expr> > d_boundVarStack; 00102 //! Map for bound vars 00103 std::hash_map<std::string, Expr> d_boundVarMap; 00104 //! Cache for parser 00105 ExprMap<Expr> d_parseCache; 00106 //! Cache for tcc's 00107 ExprMap<Expr> d_tccCache; 00108 00109 //! Array of registered theories 00110 std::vector<Theory*> d_theories; 00111 00112 //! Array mapping kinds to theories 00113 std::hash_map<int, Theory*> d_theoryMap; 00114 00115 //! The theory which has the solver (if any) 00116 Theory* d_solver; 00117 00118 //! Mapping of compound type variables to simpler types (model generation) 00119 ExprHashMap<std::vector<Expr> > d_varModelMap; 00120 //! Mapping of intermediate variables to their valies 00121 ExprHashMap<Theorem> d_varAssignments; 00122 //! List of basic variables (temporary storage for model generation) 00123 std::vector<Expr> d_basicModelVars; 00124 //! Mapping of basic variables to simplified expressions (temp. storage) 00125 /*! There may be some vars which simplify to something else; we save 00126 * those separately, and keep only those which simplify to 00127 * themselves. Once the latter vars are assigned, we'll re-simplify 00128 * the former variables and use the results as concrete values. 00129 */ 00130 ExprHashMap<Theorem> d_simplifiedModelVars; 00131 00132 //! Command line flag whether to simplify in place 00133 const bool* d_simplifyInPlace; 00134 //! Which recursive simplifier to use 00135 Theorem (TheoryCore::*d_currentRecursiveSimplifier)(const Expr&); 00136 00137 //! Resource limit (0==unlimited, 1==no more resources, >=2 - available). 00138 /*! Currently, it is the number of enqueued facts. Once the 00139 * resource is exhausted, the remaining facts will be dropped, and 00140 * an incomplete flag is set. 00141 */ 00142 unsigned d_resourceLimit; 00143 00144 IF_DEBUG(bool d_inCheckSATCore); 00145 IF_DEBUG(bool d_inAddFact); 00146 IF_DEBUG(bool d_inRegisterAtom); 00147 IF_DEBUG(ExprMap<bool> d_simpStack); 00148 00149 00150 //! So we get notified every time there's a pop 00151 friend class CoreNotifyObj; 00152 class CoreNotifyObj :public ContextNotifyObj { 00153 TheoryCore* d_theoryCore; 00154 public: 00155 CoreNotifyObj(TheoryCore* tc, Context* context) 00156 : ContextNotifyObj(context), d_theoryCore(tc) {} 00157 void notify() { d_theoryCore->getEM()->invalidateSimpCache(); } 00158 }; 00159 CoreNotifyObj d_notifyObj; 00160 00161 //! List of implied literals, based on registered atomic formulas of interest 00162 CDList<Theorem> d_impliedLiterals; 00163 00164 //! Next index in d_impliedLiterals that has not yet been fetched 00165 CDO<unsigned> d_impliedLiteralsIdx; 00166 00167 //! List of theorems from calls to update() 00168 // These are stored here until the equality lists are finished and then 00169 // processed by processUpdates() 00170 std::vector<Theorem> d_update_thms; 00171 00172 //! List of data accompanying above theorems from calls to update() 00173 std::vector<Expr> d_update_data; 00174 00175 public: 00176 /***************************************************************************/ 00177 /*! 00178 *\class CoreSatAPI 00179 *\brief Interface class for callbacks to SAT from Core 00180 * 00181 * Author: Clark Barrett 00182 * 00183 * Created: Mon Dec 5 18:42:15 2005 00184 */ 00185 /***************************************************************************/ 00186 class CoreSatAPI { 00187 public: 00188 CoreSatAPI() {} 00189 virtual ~CoreSatAPI() {} 00190 //! Add a new lemma derived by theory core 00191 virtual void addLemma(const Theorem& thm) = 0; 00192 //! Add an assumption to the set of assumptions in the current context 00193 /*! Assumptions have the form e |- e */ 00194 virtual Theorem addAssumption(const Expr& assump) = 0; 00195 //! Suggest a splitter to the Sat engine 00196 /*! \param e is a literal. 00197 * \param priority is between -10 and 10. A priority above 0 indicates 00198 * that the splitter should be favored. A priority below 0 indicates that 00199 * the splitter should be delayed. 00200 */ 00201 virtual void addSplitter(const Expr& e, int priority) = 0; 00202 //! Check the validity of e in the current context 00203 virtual bool check(const Expr& e) = 0; 00204 }; 00205 private: 00206 CoreSatAPI* d_coreSatAPI; 00207 00208 private: 00209 //! Private method to get a new theorem producer. 00210 /*! This method is used ONLY by the TheoryCore constructor. The 00211 only reason to have this method is to separate the trusted part of 00212 the constructor into a separate .cpp file (Alternative is to make 00213 the entire constructer trusted, which is not very safe). 00214 Method is implemented in core_theorem_producer.cpp */ 00215 CoreProofRules* createProofRules(TheoremManager* tm); 00216 00217 // Helper functions 00218 00219 //! Check if the vector<Expr> is sorted w.r.t. operator< 00220 IF_DEBUG(bool isSorted(const std::vector<Expr>& v)); 00221 00222 //! Intersection of sorted vectors of Exprs: res := \f$a \cap b\f$ 00223 //! Check if the vector<Expr> is sorted w.r.t. operator< 00224 /*! ASSUMPTION: a and b are sorted in ascending order w.r.t. operator< 00225 */ 00226 void intersect(const std::vector<Expr>& a, 00227 const std::vector<Expr>& b, 00228 std::vector<Expr>& res); 00229 00230 //! Set difference of sorted vectors of Exprs: res := a - b 00231 /*! ASSUMPTION: a and b are sorted in ascending order w.r.t. operator< 00232 */ 00233 void difference(const std::vector<Expr>& a, 00234 const std::vector<Expr>& b, 00235 std::vector<Expr>& res); 00236 00237 //! Effort level for processFactQueue 00238 /*! LOW means just process facts, don't call theory checkSat methods 00239 NORMAL means call theory checkSat methods without full effort 00240 FULL means call theory checkSat methods with full effort 00241 */ 00242 typedef enum { 00243 LOW, 00244 NORMAL, 00245 FULL 00246 } EffortLevel; 00247 00248 //! A helper function for addFact() 00249 /*! Returns true if lemmas were added to search engine, false otherwise */ 00250 bool processFactQueue(EffortLevel effort = NORMAL); 00251 //! Process a notify list triggered as a result of new theorem e 00252 void processNotify(const Theorem& e, NotifyList* L); 00253 //! Transitive composition of other rewrites with the above 00254 Theorem rewriteCore(const Theorem& e); 00255 //! Helper for registerAtom 00256 void setupSubFormulas(const Expr& s, const Expr& e, const Theorem& thm); 00257 //! Process updates recorded by calls to update() 00258 void processUpdates(); 00259 /*! @brief The assumptions for e must be in H or phi. "Core" added 00260 * to avoid conflict with theory interface function name 00261 */ 00262 void assertFactCore(const Theorem& e); 00263 //! Process a newly derived formula 00264 void assertFormula(const Theorem& e); 00265 //! Check that lhs and rhs of thm have same base type 00266 IF_DEBUG(void checkRewriteType(const Theorem& thm);) 00267 /*! @brief Returns phi |= e = rewriteCore(e). "Core" added to avoid 00268 conflict with theory interface function name */ 00269 Theorem rewriteCore(const Expr& e); 00270 00271 //! Set the find pointer of an atomic formula and notify SearchEngine 00272 /*! \param thm is a Theorem(phi) or Theorem(NOT phi), where phi is 00273 * an atomic formula to get a find pointer to TRUE or FALSE, 00274 * respectively. 00275 */ 00276 void setFindLiteral(const Theorem& thm); 00277 //! Derived rule for rewriting ITE 00278 Theorem rewriteIte(const Expr& e); 00279 //! Core rewrites for literals (NOT and EQ) 00280 Theorem rewriteLitCore(const Expr& e); 00281 //! Rewrite n levels deep. WARNING: no caching here, be careful. 00282 Theorem rewriteN(const Expr& e, int n); 00283 /*! @brief An auxiliary function for assertEqualities(); return true 00284 * if inconsistency is derived. 00285 */ 00286 bool processEquality(const Theorem& thm, ExprMap<Theorem>& q); 00287 //! Enqueue a fact to be sent to the SearchEngine 00288 void enqueueSE(const Theorem& thm); 00289 //! Fetch the concrete assignment to the variable during model generation 00290 Theorem getModelValue(const Expr& e); 00291 00292 //! An auxiliary recursive function to process COND expressions into ITE 00293 Expr processCond(const Expr& e, int i); 00294 00295 //! Request a unit of resource 00296 /*! It will be subtracted from the resource limit. 00297 * 00298 * \return true if resource unit is granted, false if no more 00299 * resources available. 00300 */ 00301 void getResource() { if (d_resourceLimit > 1) d_resourceLimit--; } 00302 //! Return true if no special parsing is required for this kind 00303 bool isBasicKind(int kind); 00304 00305 public: 00306 //! Constructor 00307 TheoryCore(ContextManager* cm, ExprManager* em, 00308 TheoremManager* tm, Translator* tr, 00309 const CLFlags& flags, 00310 Statistics& statistics); 00311 //! Destructor 00312 ~TheoryCore(); 00313 00314 //! Register a SatAPI for TheoryCore 00315 void registerCoreSatAPI(CoreSatAPI* coreSatAPI) { d_coreSatAPI = coreSatAPI; } 00316 00317 ContextManager* getCM() const { return d_cm; } 00318 TheoremManager* getTM() const { return d_tm; } 00319 const CLFlags& getFlags() const { return d_flags; } 00320 Statistics& getStatistics() const { return d_statistics; } 00321 ExprTransform* getExprTrans() const { return d_exprTrans; } 00322 CoreProofRules* getCoreRules() const { return d_rules; } 00323 Translator* getTranslator() const { return d_translator; } 00324 00325 //! Get list of terms 00326 const CDList<Expr>& getTerms() { return d_terms; } 00327 //! Get theorem which was responsible for introducing this term 00328 Theorem getTheoremForTerm(const Expr& e); 00329 //! Get quantification level at which this term was introduced 00330 unsigned getQuantLevelForTerm(const Expr& e); 00331 //! Get list of predicates 00332 const CDList<Expr>& getPredicates() { return d_predicates; } 00333 00334 // Implementation of Theory API 00335 /*! Variables of uninterpreted types may be sent here, and they 00336 should be ignored. */ 00337 void addSharedTerm(const Expr& e) { } 00338 void assertFact(const Theorem& e); 00339 void checkSat(bool fullEffort) { } 00340 Theorem rewrite(const Expr& e); 00341 /*! Only Boolean constants (TRUE and FALSE) and variables of 00342 uninterpreted types should appear here (they come from records and 00343 tuples). Just ignore them. */ 00344 void setup(const Expr& e) { } 00345 void update(const Theorem& e, const Expr& d); 00346 Theorem solve(const Theorem& e); 00347 00348 Theorem simplifyOp(const Expr& e); 00349 void checkType(const Expr& e); 00350 void computeType(const Expr& e); 00351 Type computeBaseType(const Type& t); 00352 Expr computeTCC(const Expr& e); 00353 Expr computeTypePred(const Type& t,const Expr& e); 00354 Expr parseExprOp(const Expr& e); 00355 ExprStream& print(ExprStream& os, const Expr& e); 00356 //! Calls for other theories to add facts to refine a coutnerexample. 00357 void refineCounterExample(); 00358 void computeModelBasic(const std::vector<Expr>& v); 00359 00360 // User-level API methods 00361 00362 /*! @brief Add a new assertion to the core from the user or a SAT 00363 solver. Do NOT use it in a decision procedure; use 00364 enqueueFact(). */ 00365 /*! \sa enqueueFact */ 00366 void addFact(const Theorem& e); 00367 00368 //! Top-level simplifier 00369 Theorem simplify(const Expr& e); 00370 00371 //! Check if the current context is inconsistent 00372 bool inconsistent() { return d_inconsistent ; } 00373 //! Get the proof of inconsistency for the current context 00374 /*! \return Theorem(FALSE) */ 00375 Theorem inconsistentThm() { return d_incThm; } 00376 /*! @brief To be called by SearchEngine when it believes the context 00377 * is satisfiable. 00378 * 00379 * \return true if definitely consistent or inconsistent and false if 00380 * consistency is unknown. 00381 */ 00382 bool checkSATCore(); 00383 00384 //! Check if the current decision branch is marked as incomplete 00385 bool incomplete() { return d_incomplete.size() > 0 ; } 00386 //! Check if the branch is incomplete, and return the reasons (strings) 00387 bool incomplete(std::vector<std::string>& reasons); 00388 00389 //! Register an atomic formula of interest. 00390 /*! If e or its negation is later deduced, we will add the implied 00391 literal to d_impliedLiterals */ 00392 void registerAtom(const Expr& e, const Theorem& thm); 00393 00394 //! Return the next implied literal (NULL Theorem if none) 00395 Theorem getImpliedLiteral(void); 00396 00397 //! Return total number of implied literals 00398 unsigned numImpliedLiterals() { return d_impliedLiterals.size(); } 00399 00400 //! Return an implied literal by index 00401 Theorem getImpliedLiteralByIndex(unsigned index); 00402 00403 //! Parse the generic expression. 00404 /*! This method should be used in parseExprOp() for recursive calls 00405 * to subexpressions, and is the method called by the command 00406 * processor. 00407 */ 00408 Expr parseExpr(const Expr& e); 00409 //! Top-level call to parseExpr, clears the bound variable stack. 00410 /*! Use it in VCL instead of parseExpr(). */ 00411 Expr parseExprTop(const Expr& e) { 00412 d_boundVarStack.clear(); 00413 d_parseCache.clear(); 00414 return parseExpr(e); 00415 } 00416 00417 //! Assign t a concrete value val. Used in model generation. 00418 void assignValue(const Expr& t, const Expr& val); 00419 //! Record a derived assignment to a variable (LHS). 00420 void assignValue(const Theorem& thm); 00421 00422 //! Adds expression to var database 00423 void addToVarDB(const Expr & e); 00424 //! Split compound vars into basic type variables 00425 /*! The results are saved in d_basicModelVars and 00426 * d_simplifiedModelVars. Also, add new basic vars as shared terms 00427 * whenever their type belongs to a different theory than the term 00428 * itself. 00429 */ 00430 void collectBasicVars(); 00431 //! Calls theory specific computeModel, results are placed in map 00432 void buildModel(ExprMap<Expr>& m); 00433 //! Recursively build a compound-type variable assignment for e 00434 void collectModelValues(const Expr& e, ExprMap<Expr>& m); 00435 00436 //! Set the resource limit (0==unlimited). 00437 void setResourceLimit(unsigned limit) { d_resourceLimit = limit; } 00438 //! Get the resource limit 00439 unsigned getResourceLimit() { return d_resourceLimit; } 00440 //! Return true if resources are exhausted 00441 bool outOfResources() { return d_resourceLimit == 1; } 00442 00443 //! Called by search engine 00444 Theorem rewriteLiteral(const Expr& e); 00445 00446 private: 00447 // Methods provided for benefit of theories. Access is made available through theory.h 00448 00449 //! Assert a system of equations (1 or more). 00450 /*! e is either a single equation, or a conjunction of equations 00451 */ 00452 void assertEqualities(const Theorem& e); 00453 00454 //! Mark the branch as incomplete 00455 void setIncomplete(const std::string& reason); 00456 00457 //! Return a theorem for the type predicate of e 00458 /*! Note: used only by theory_arith */ 00459 Theorem typePred(const Expr& e); 00460 00461 public: 00462 // TODO: These should be private 00463 //! Enqueue a new fact 00464 /*! not private because used in search_fast.cpp */ 00465 void enqueueFact(const Theorem& e); 00466 00467 // Must provide proof of inconsistency 00468 /*! not private because used in search_fast.cpp */ 00469 void setInconsistent(const Theorem& e); 00470 00471 //! Setup additional terms within a theory-specific setup(). 00472 /*! not private because used in theory_bitvector.cpp */ 00473 void setupTerm(const Expr& e, Theory* i, const Theorem& thm); 00474 00475 00476 }; 00477 00478 //! Printing NotifyList class 00479 std::ostream& operator<<(std::ostream& os, const NotifyList& l); 00480 00481 } 00482 00483 #endif