CVC3
|
00001 /*****************************************************************************/ 00002 /*! 00003 * \file variable.h 00004 * 00005 * Author: Sergey Berezin 00006 * 00007 * Created: Fri Apr 25 11:52:17 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 * A data structure representing a variable in the search engine. It 00019 * is a smart pointer with a uniquifying mechanism similar to Expr, 00020 * and a variable is uniquely determined by its expression. It can be 00021 * thought of as an Expr with additional attributes, but the type is 00022 * different, so it will not be confused with other Exprs. 00023 */ 00024 /*****************************************************************************/ 00025 00026 #ifndef _cvc3__variable_h_ 00027 #define _cvc3__variable_h_ 00028 00029 #include "expr.h" 00030 00031 namespace CVC3 { 00032 00033 class VariableManager; 00034 class VariableValue; 00035 class Clause; 00036 class SearchEngineRules; 00037 00038 // The main "smart pointer" class 00039 class Variable { 00040 private: 00041 VariableValue* d_val; 00042 // Private methods 00043 Theorem deriveThmRec(bool checkAssump) const; 00044 public: 00045 // Default constructor 00046 Variable(): d_val(NULL) { } 00047 // Constructor from an Expr; if such variable already exists, it 00048 // will be found and used. 00049 Variable(VariableManager* vm, const Expr& e); 00050 // Copy constructor 00051 Variable(const Variable& l); 00052 // Destructor 00053 ~Variable(); 00054 // Assignment 00055 Variable& operator=(const Variable& l); 00056 00057 bool isNull() const { return d_val == NULL; } 00058 00059 // Accessors 00060 00061 // Expr is the only constant attribute of a variable; other 00062 // attributes can be changed. 00063 const Expr& getExpr() const; 00064 // The Expr of the inverse of the variable. This function is 00065 // caching, so !e is only constructed once. 00066 const Expr& getNegExpr() const; 00067 00068 // IMPORTANT: Value can be -1 (false), 1 (true), or 0 (unresolved) 00069 int getValue() const; 00070 // If the value is set, scope level and either a theorem or 00071 // an antecedent clause must be defined 00072 int getScope() const; 00073 const Theorem& getTheorem() const; 00074 const Clause& getAntecedent() const; 00075 // Index of this variable in the antecedent clause; if it is -1, 00076 // the variable is FALSE, and that clause caused the contradiction 00077 int getAntecedentIdx() const; 00078 // Theorem of the form l |- l produced by the 'assump' rule, if 00079 // this variable is a splitter, or a new intermediate assumption 00080 // is generated for it. 00081 const Theorem& getAssumpThm() const; 00082 // Setting the attributes: it can be either derived from the 00083 // antecedent clause, or by a theorem. The scope level is set to 00084 // the current scope. 00085 void setValue(int val, const Clause& c, int idx); 00086 // The theorem's expr must be the same as the variable's expr or 00087 // its negation, and the scope is the lowest scope where all 00088 // assumptions of the theorem are true 00089 void setValue(const Theorem& thm); 00090 void setValue(const Theorem& thm, int scope); 00091 00092 void setAssumpThm(const Theorem& a, int scope); 00093 // Derive the theorem for either the variable or its negation. If 00094 // the value is set by a theorem, that theorem is returned; 00095 // otherwise a unit propagation rule is applied to the antecedent 00096 // clause. 00097 Theorem deriveTheorem() const; 00098 00099 // Accessing Chaff counters (read and modified by reference) 00100 unsigned& count(bool neg); 00101 unsigned& countPrev(bool neg); 00102 int& score(bool neg); 00103 bool& added(bool neg); 00104 // Read-only versions 00105 unsigned count(bool neg) const; 00106 unsigned countPrev(bool neg) const; 00107 int score(bool neg) const; 00108 bool added(bool neg) const; 00109 // Watch pointer access 00110 std::vector<std::pair<Clause, int> >& wp(bool neg) const; 00111 // Friend methods 00112 friend bool operator==(const Variable& l1, const Variable& l2) { 00113 return l1.d_val == l2.d_val; 00114 } 00115 // Printing 00116 friend std::ostream& operator<<(std::ostream& os, const Variable& l); 00117 std::string toString() const; 00118 }; // end of class Variable 00119 00120 class Literal { 00121 private: 00122 Variable d_var; 00123 bool d_negative; 00124 public: 00125 // Constructors: from a variable 00126 Literal(const Variable& v, bool positive = true) 00127 : d_var(v), d_negative(!positive) { } 00128 // Default constructor 00129 Literal(): d_negative(false) { } 00130 // from Expr: if e == !e', construct negative literal of e', 00131 // otherwise positive of e 00132 Literal(VariableManager* vm, const Expr& e) 00133 : d_var(vm, (e.isNot())? e[0] : e), d_negative(e.isNot()) { } 00134 Variable& getVar() { return d_var; } 00135 const Variable& getVar() const { return d_var; } 00136 bool isPositive() const { return !d_negative; } 00137 bool isNegative() const { return d_negative; } 00138 bool isNull() const { return d_var.isNull(); } 00139 // Return var or !var 00140 const Expr& getExpr() const { 00141 if(d_negative) return d_var.getNegExpr(); 00142 else return d_var.getExpr(); 00143 } 00144 int getValue() const { 00145 if(d_negative) return -(d_var.getValue()); 00146 else return d_var.getValue(); 00147 } 00148 int getScope() const { return getVar().getScope(); } 00149 // Set the value of the literal 00150 // void setValue(int val, const Clause& c, int idx) { 00151 // d_var.setValue(d_negative? -val : val, c, idx); 00152 // } 00153 void setValue(const Theorem& thm) { 00154 d_var.setValue(thm, thm.getScope()); 00155 } 00156 void setValue(const Theorem& thm, int scope) { 00157 d_var.setValue(thm, scope); 00158 } 00159 const Theorem& getTheorem() const { return d_var.getTheorem(); } 00160 // const Clause& getAntecedent() const { return d_var.getAntecedent(); } 00161 // int getAntecedentIdx() const { return d_var.getAntecedentIdx(); } 00162 // Defined when the literal has a value. Derives a theorem 00163 // proving either this literal or its inverse. 00164 Theorem deriveTheorem() const { return d_var.deriveTheorem(); } 00165 // Accessing Chaff counters (read and modified by reference) 00166 unsigned& count() { return d_var.count(d_negative); } 00167 unsigned& countPrev() { return d_var.countPrev(d_negative); } 00168 int& score() { return d_var.score(d_negative); } 00169 bool& added() { return d_var.added(d_negative); } 00170 // Read-only versions 00171 unsigned count() const { return d_var.count(d_negative); } 00172 unsigned countPrev() const { return d_var.countPrev(d_negative); } 00173 int score() const { return d_var.score(d_negative); } 00174 bool added() const { return d_var.added(d_negative); } 00175 // Watch pointer access 00176 std::vector<std::pair<Clause, int> >& wp() const 00177 { return d_var.wp(d_negative); } 00178 // Printing 00179 friend std::ostream& operator<<(std::ostream& os, const Literal& l); 00180 std::string toString() const; 00181 // Equality 00182 friend bool operator==(const Literal& l1, const Literal& l2) { 00183 return (l1.d_negative == l2.d_negative && l1.d_var==l1.d_var); 00184 } 00185 }; // end of class Literal 00186 00187 // Non-member methods: negation of Variable and Literal 00188 inline Literal operator!(const Variable& v) { 00189 return Literal(v, false); 00190 } 00191 00192 inline Literal operator!(const Literal& l) { 00193 return Literal(l.getVar(), l.isNegative()); 00194 } 00195 00196 std::ostream& operator<<(std::ostream& os, const Literal& l); 00197 00198 } // end of namespace CVC3 00199 00200 // Clause uses class Variable, have to include it here 00201 #include "clause.h" 00202 00203 namespace CVC3 { 00204 00205 // The value holding class 00206 class VariableValue { 00207 friend class Variable; 00208 friend class VariableManager; 00209 private: 00210 VariableManager* d_vm; 00211 int d_refcount; 00212 00213 Expr d_expr; 00214 // The inverse expression (initally Null) 00215 Expr d_neg; 00216 00217 // Non-backtracking attributes (Chaff counters) 00218 00219 // For positive instances 00220 unsigned d_count; 00221 unsigned d_countPrev; 00222 int d_score; 00223 // For negative instances 00224 unsigned d_negCount; 00225 unsigned d_negCountPrev; 00226 int d_negScore; 00227 // Whether the corresponding literal is in the list of active literals 00228 bool d_added; 00229 bool d_negAdded; 00230 // Watch pointer lists 00231 std::vector<std::pair<Clause, int> > d_wp; 00232 std::vector<std::pair<Clause, int> > d_negwp; 00233 00234 // Backtracking attributes 00235 00236 // Value of the variable: -1 (false), 1 (true), 0 (unresolved) 00237 CDO<int>* d_val; 00238 CDO<int>* d_scope; // Scope level where the variable is assigned 00239 // Theorem of the form (d_expr) or (!d_expr), reflecting d_val 00240 CDO<Theorem>* d_thm; 00241 CDO<Clause>* d_ante; // Antecedent clause and index of the variable 00242 CDO<int>* d_anteIdx; 00243 CDO<Theorem>* d_assump; // Theorem generated by assump rule, if any 00244 // Constructor is private; only class Variable can create it 00245 VariableValue(VariableManager* vm, const Expr& e) 00246 : d_vm(vm), d_refcount(0), d_expr(e), 00247 d_count(0), d_countPrev(0), d_score(0), 00248 d_negCount(0), d_negCountPrev(0), d_negScore(0), 00249 d_added(false), d_negAdded(false), 00250 d_val(NULL), d_scope(NULL), d_thm(NULL), 00251 d_ante(NULL), d_anteIdx(NULL), d_assump(NULL) { } 00252 public: 00253 ~VariableValue(); 00254 // Accessor methods 00255 const Expr& getExpr() const { return d_expr; } 00256 00257 const Expr& getNegExpr() const { 00258 if(d_neg.isNull()) { 00259 const_cast<VariableValue*>(this)->d_neg 00260 = d_expr.negate(); 00261 } 00262 return d_neg; 00263 } 00264 00265 int getValue() const { 00266 if(d_val==NULL) return 0; 00267 else return d_val->get(); 00268 } 00269 00270 int getScope() const { 00271 if(d_scope==NULL) return 0; 00272 else return d_scope->get(); 00273 } 00274 00275 const Theorem& getTheorem() const { 00276 static Theorem null; 00277 if(d_thm==NULL) return null; 00278 else return d_thm->get(); 00279 } 00280 00281 const Clause& getAntecedent() const { 00282 static Clause null; 00283 if(d_ante==NULL) return null; 00284 else return d_ante->get(); 00285 } 00286 00287 int getAntecedentIdx() const { 00288 if(d_anteIdx==NULL) return 0; 00289 else return d_anteIdx->get(); 00290 } 00291 00292 const Theorem& getAssumpThm() const { 00293 static Theorem null; 00294 if(d_assump==NULL) return null; 00295 else return d_assump->get(); 00296 } 00297 00298 // Setting the attributes: it can be either derived from the 00299 // antecedent clause, or by a theorem 00300 void setValue(int val, const Clause& c, int idx); 00301 // The theorem's expr must be the same as the variable's expr or 00302 // its negation 00303 void setValue(const Theorem& thm, int scope); 00304 00305 void setAssumpThm(const Theorem& a, int scope); 00306 00307 // Chaff counters: read and modified by reference 00308 unsigned& count(bool neg) { 00309 if(neg) return d_negCount; 00310 else return d_count; 00311 } 00312 unsigned& countPrev(bool neg) { 00313 if(neg) return d_negCountPrev; 00314 else return d_countPrev; 00315 } 00316 int& score(bool neg) { 00317 if(neg) return d_negScore; 00318 else return d_score; 00319 } 00320 bool& added(bool neg) { 00321 if(neg) return d_negAdded; 00322 else return d_added; 00323 } 00324 00325 // Memory management 00326 void* operator new(size_t size, MemoryManager* mm) { 00327 return mm->newData(size); 00328 } 00329 void operator delete(void* pMem, MemoryManager* mm) { 00330 mm->deleteData(pMem); 00331 } 00332 void operator delete(void*) { } 00333 00334 // friend methods 00335 friend std::ostream& operator<<(std::ostream& os, const VariableValue& v); 00336 friend bool operator==(const VariableValue& v1, const VariableValue& v2) { 00337 return v1.d_expr == v2.d_expr; 00338 } 00339 }; // end of class VariableValue 00340 00341 // Accessing Chaff counters (read and modified by reference) 00342 inline unsigned& Variable::count(bool neg) { return d_val->count(neg); } 00343 inline unsigned& Variable::countPrev(bool neg) 00344 { return d_val->countPrev(neg); } 00345 inline int& Variable::score(bool neg) { return d_val->score(neg); } 00346 inline bool& Variable::added(bool neg) { return d_val->added(neg); } 00347 00348 inline unsigned Variable::count(bool neg) const { return d_val->count(neg); } 00349 inline unsigned Variable::countPrev(bool neg) const 00350 { return d_val->countPrev(neg); } 00351 inline int Variable::score(bool neg) const { return d_val->score(neg); } 00352 inline bool Variable::added(bool neg) const { return d_val->added(neg); } 00353 00354 inline std::vector<std::pair<Clause, int> >& Variable::wp(bool neg) const { 00355 if(neg) return d_val->d_negwp; 00356 else return d_val->d_wp; 00357 } 00358 00359 00360 class VariableManagerNotifyObj; 00361 00362 // The manager class 00363 class VariableManager { 00364 friend class Variable; 00365 friend class VariableValue; 00366 private: 00367 ContextManager* d_cm; 00368 MemoryManager* d_mm; 00369 SearchEngineRules* d_rules; 00370 VariableManagerNotifyObj* d_notifyObj; 00371 //! Disable the garbage collection 00372 /*! Normally, it's set in the destructor, so that we can delete 00373 * all remaining variables without GC getting in the way 00374 */ 00375 bool d_disableGC; 00376 //! Postpone garbage collection 00377 bool d_postponeGC; 00378 //! Vector of variables to be deleted (postponed during pop()) 00379 std::vector<VariableValue*> d_deleted; 00380 00381 // Hash only by the Expr 00382 class HashLV { 00383 public: 00384 size_t operator()(VariableValue* v) const { return v->getExpr().hash(); } 00385 }; 00386 class EqLV { 00387 public: 00388 bool operator()(const VariableValue* lv1, const VariableValue* lv2) const 00389 { return lv1->getExpr() == lv2->getExpr(); } 00390 }; 00391 00392 // Hash set for existing variables 00393 typedef std::hash_set<VariableValue*, HashLV, EqLV> VariableValueSet; 00394 VariableValueSet d_varSet; 00395 00396 // Creating unique VariableValue 00397 VariableValue* newVariableValue(const Expr& e); 00398 00399 public: 00400 // Constructor. mmFlag indicates which memory manager to use. 00401 VariableManager(ContextManager* cm, SearchEngineRules* rules, 00402 const std::string& mmFlag); 00403 // Destructor 00404 ~VariableManager(); 00405 00406 //! Garbage collect VariableValue pointer 00407 void gc(VariableValue* v); 00408 //! Postpone garbage collection 00409 void postponeGC() { d_postponeGC = true; } 00410 //! Resume garbage collection 00411 void resumeGC(); 00412 // Accessors 00413 ContextManager* getCM() const { return d_cm; } 00414 SearchEngineRules* getRules() const { return d_rules; } 00415 00416 }; // end of class VariableManager 00417 00418 /*****************************************************************************/ 00419 /*! 00420 *\class VariableManagerNotifyObj 00421 *\brief Notifies VariableManager before and after each pop() 00422 * 00423 * Author: Sergey Berezin 00424 * 00425 * Created: Tue Mar 1 13:52:28 2005 00426 * 00427 * Disables the deletion of VariableValue objects during context 00428 * restoration (backtracking). This solves the problem of circular 00429 * dependencies (e.g. a Variable pointing to its antecedent Clause). 00430 */ 00431 /*****************************************************************************/ 00432 class VariableManagerNotifyObj: public ContextNotifyObj { 00433 VariableManager* d_vm; 00434 public: 00435 //! Constructor 00436 VariableManagerNotifyObj(VariableManager* vm, Context* cxt) 00437 : ContextNotifyObj(cxt), d_vm(vm) { } 00438 00439 void notifyPre(void) { d_vm->postponeGC(); } 00440 void notify(void) { d_vm->resumeGC(); } 00441 }; 00442 00443 00444 } // end of namespace CVC3 00445 #endif