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

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