theory_core.h

Go to the documentation of this file.
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

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