CVC3

clause.h

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file clause.h
00004  * 
00005  * Author: Sergey Berezin
00006  * 
00007  * Created: Fri Mar  7 16:03:38 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  * Class to represent a clause, which is a disjunction of formulas
00019  * which are literals for conflict clauses, and possibly more complex
00020  * formulas for the clauses derived from the user-asserted formulas.
00021  * 
00022  * class Clause is implemented as a smart pointer to ClauseValue, so
00023  * it can be freely copied and assigned with low overhead (like
00024  * Theorem or Expr).
00025  */
00026 /*****************************************************************************/
00027 
00028 // Include it before ifndef, since it includes this file recursively
00029 #ifndef DOXYGEN
00030 #include "variable.h"
00031 #endif
00032 
00033 #ifndef _cvc3__include__clause_h_
00034 #define _cvc3__include__clause_h_
00035 
00036 namespace CVC3 {
00037 
00038   class Clause;
00039   class ClauseOwner;
00040   class TheoryCore;
00041 
00042   class ClauseValue {
00043     friend class Clause;
00044   private:
00045     //! Ref. counter
00046     int d_refcount;
00047     //! Ref. counter of ClauseOwner classes holding it
00048     int d_refcountOwner;
00049     // The original clause (disjunction of literals)
00050     Theorem d_thm;
00051     // Scope where the clause is valid
00052     int d_scope;
00053     // Theorems l_i <=> l'_i for each literal l_i
00054     // FIXME: more efficient implementation for fixed arrays of CDOs
00055     std::vector<Literal> d_literals;
00056     // Disallow copy constructor and assignment (make private)
00057     ClauseValue(const ClauseValue& c); // Undefined (since it cannot be used)
00058     ClauseValue& operator=(const ClauseValue& c) { return *this; }
00059     // Pointers to watched literals (Watch Pointers).  They are not
00060     // backtrackable.
00061     size_t d_wp[2];
00062     // Direction flags for the watch pointers (1 or -1)
00063     // FIXME: should we use one bit of d_wp{1,2} instead? (efficiency
00064     // vs. space)
00065     int d_dir[2];
00066     // A flag indicating that the clause is shown satisfiable
00067     CDO<bool> d_sat;
00068     // Marks the clause as deleted
00069     bool d_deleted;
00070     // Creation file and line number (for debugging)
00071     IF_DEBUG(std::string d_file; int d_line;)
00072     // Constructor: takes the main clause theorem which must be a
00073     // disjunction of literals and have no assumptions.
00074     ClauseValue(TheoryCore* core, VariableManager* vm,
00075     const Theorem& clause, int scope);
00076   public:
00077     // Destructor
00078     ~ClauseValue();
00079       
00080   }; // end of class ClauseValue
00081 
00082   //! A class representing a CNF clause (a smart pointer)
00083   class Clause {
00084   private:
00085     friend class ClauseOwner;
00086     //! The only value member
00087     ClauseValue* d_clause;
00088     //! Export owner refcounting to ClauseOwner
00089     int& countOwner() {
00090       DebugAssert(d_clause != NULL, "");
00091       return d_clause->d_refcountOwner;
00092     }
00093   public:
00094     Clause(): d_clause(NULL) { }
00095     // Constructors
00096     Clause(TheoryCore* core, VariableManager* vm, const Theorem& clause,
00097            int scope, const std::string& file = "", int line = 0)
00098       : d_clause(new ClauseValue(core, vm, clause, scope)) {
00099       d_clause->d_refcount++;
00100       IF_DEBUG(d_clause->d_file = file; d_clause->d_line=line;)
00101     }
00102     // Copy constructor
00103     Clause(const Clause& c): d_clause(c.d_clause) {
00104       if(d_clause != NULL) d_clause->d_refcount++;
00105     }
00106     // Destructor
00107     ~Clause();
00108     // Assignment operator
00109     Clause& operator=(const Clause& c);
00110 
00111     bool isNull() const { return d_clause == NULL; }
00112     // Other public methods
00113     size_t size() const {
00114       return (d_clause == NULL)? 0 : d_clause->d_literals.size();
00115     }
00116     // Get the theorem representing the entire clause
00117     const Theorem& getTheorem() const {
00118       DebugAssert(!isNull(), "Clause::getTheorem(): Null Clause");
00119       return d_clause->d_thm;
00120     }
00121     // Get the scope where the clause is valid
00122     int getScope() const {
00123       if(isNull()) return 0;
00124       else return d_clause->d_scope;
00125     }
00126     // Get the current value of the i-th literal
00127     const Literal& getLiteral(size_t i) const {
00128       DebugAssert(!isNull(), "Clause::getLiteral(): Null Clause");
00129       DebugAssert(i < size(), 
00130       "Clause::getLiteral(" + int2string(i)
00131       + "): i >= size = " + int2string(size()));
00132       return d_clause->d_literals[i];
00133     }
00134     // Get the current value of the i-th literal
00135     const Literal& operator[](size_t i) const { return getLiteral(i); }
00136 
00137     // Get the reference to the vector of literals, for fast access
00138     const std::vector<Literal>& getLiterals() const {
00139       DebugAssert(!isNull(), "Clause::getLiterals(): Null Clause");
00140       return d_clause->d_literals;
00141     }
00142     // Get the values of watch pointers
00143     size_t wp(int i) const {
00144       DebugAssert(!isNull(), "Clause::wp(i): Null Clause");
00145       DebugAssert(i==0 || i==1, 
00146       "wp(i): Watch pointer index is out of bounds: i = "
00147       + int2string(i));
00148       return d_clause->d_wp[i];
00149     }
00150     // Get the watched literals
00151     const Literal& watched(int i) const { return getLiteral(wp(i)); }
00152     // Set the watch pointers and return the new value
00153     size_t wp(int i, size_t l) const {
00154       DebugAssert(!isNull(), "Clause::wp(i,l): Null Clause");
00155       DebugAssert(i==0 || i==1, 
00156       "wp(i,l): Watch pointer index is out of bounds: i = "
00157       + int2string(i));
00158       DebugAssert(l < size(), "Clause::wp(i = " + int2string(i)
00159       + ", l = " + int2string(l)
00160       + "): l >= size() = " + int2string(size()));
00161       TRACE("clauses", " **clauses** UPDATE wp(idx="
00162       +int2string(i)+", l="+int2string(l),
00163       ")\n  clause #: ", id());
00164       d_clause->d_wp[i] = l;
00165       return l;
00166     }
00167     // Get the direction of the i-th watch pointer
00168     int dir(int i) const {
00169       DebugAssert(!isNull(), "Clause::dir(i): Null Clause");
00170       DebugAssert(i==0 || i==1, 
00171       "dir(i): Watch pointer index is out of bounds: i = "
00172       + int2string(i));
00173       return d_clause->d_dir[i];
00174     }
00175     // Set the direction of the i-th watch pointer
00176     int dir(int i, int d) const {
00177       DebugAssert(!isNull(), "Clause::dir(i,d): Null Clause");
00178       DebugAssert(i==0 || i==1, 
00179       "dir(i="+int2string(i)+",d="+int2string(d)
00180       +"): Watch pointer index is out of bounds");
00181       DebugAssert(d==1 || d==-1, "dir(i="+int2string(i)+",d="+int2string(d)
00182       +"): Direction is out of bounds");
00183       d_clause->d_dir[i] = d;
00184       return d;
00185     }
00186     //! Check if the clause marked as SAT
00187     bool sat() const {
00188       DebugAssert(!isNull(), "Clause::sat()");
00189       return d_clause->d_sat;
00190     }
00191     //! Precise version of sat(): check all the literals and cache the result
00192     bool sat(bool ignored) const {
00193       DebugAssert(!isNull(), "Clause::sat()");
00194       bool flag = false;
00195       if (!d_clause->d_sat) {
00196         for (size_t i = 0; !flag && i < d_clause->d_literals.size(); ++i)
00197           if (d_clause->d_literals[i].getValue() == 1)
00198             flag = true;
00199       }
00200       if (flag) {
00201         //std::cout << "*** Manually marking SAT" << std::endl;
00202         markSat();
00203       }
00204       return d_clause->d_sat;
00205     }
00206     // Mark the clause as SAT
00207     void markSat() const {
00208       DebugAssert(!isNull(), "Clause::markSat()");
00209       d_clause->d_sat = true;
00210     }
00211     // Check / mark the clause as deleted
00212     bool deleted() const {
00213       DebugAssert(!isNull(), "Clause::deleted()");
00214       return d_clause->d_deleted;
00215     }
00216     void markDeleted() const;
00217 
00218     // For debugging: return some kind of unique ID
00219     size_t id() const { return (size_t) d_clause; }
00220 
00221     // Equality: compare the pointers
00222     bool operator==(const Clause& c) const { return d_clause == c.d_clause; }
00223 
00224     //! Tell how many owners this clause has (for debugging)
00225     int owners() const { return d_clause->d_refcountOwner; }
00226     
00227     // Printing
00228     std::string toString() const;
00229 
00230     friend std::ostream& operator<<(std::ostream& os, const Clause& c);
00231 
00232     IF_DEBUG(bool wpCheck() const;)
00233     IF_DEBUG(const std::string& getFile() const { return d_clause->d_file; })
00234     IF_DEBUG(int getLine() const { return d_clause->d_line; })
00235 
00236   }; // end of class Clause
00237 
00238   //! Same as class Clause, but when destroyed, marks the clause as deleted
00239   /*! Needed for backtraking data structures.  When the SAT solver
00240     backtracks, some clauses will be thrown away automatically, and we
00241     need to mark those as deleted. */
00242   class ClauseOwner {
00243     Clause d_clause;
00244     //! Disable default constructor
00245     ClauseOwner() { }
00246   public:
00247     //! Constructor from class Clause
00248     ClauseOwner(const Clause& c): d_clause(c) { d_clause.countOwner()++; }
00249     //! Construct a new Clause
00250     ClauseOwner(TheoryCore* core, VariableManager* vm, const Theorem& clause,
00251     int scope): d_clause(core, vm, clause, scope) {
00252       d_clause.countOwner()++;
00253     }
00254     //! Copy constructor (keep track of refcounts)
00255     ClauseOwner(const ClauseOwner& c): d_clause(c.d_clause) {
00256       d_clause.countOwner()++;
00257     }
00258     //! Assignment (keep track of refcounts)
00259     ClauseOwner& operator=(const ClauseOwner& c) {
00260       if(&c == this) return *this; // Seft-assignment
00261       DebugAssert(d_clause.countOwner() > 0, "in operator=");
00262       if(--(d_clause.countOwner()) == 0)
00263   d_clause.markDeleted();
00264       d_clause = c.d_clause;
00265       d_clause.countOwner()++;
00266       return *this;
00267     }
00268     //! Destructor: mark the clause as deleted
00269     ~ClauseOwner() {
00270       FatalAssert(d_clause.countOwner() > 0, "in ~ClauseOwner");
00271       if(--(d_clause.countOwner()) == 0) {
00272   d_clause.markDeleted();
00273       }
00274     }
00275     //! Automatic type conversion to Clause ref
00276     operator Clause& () { return d_clause; }
00277     //! Automatic type conversion to Clause const ref
00278     operator const Clause& () const { return d_clause; }
00279   }; // end of class ClauseOwner
00280     
00281 
00282   // I/O Manipulators
00283 
00284   // Print clause in a compact form: Clause[x=-1@scope, ...], mark
00285   // watched literals by '*'
00286   class CompactClause {
00287   private:
00288     Clause d_clause;
00289   public:
00290     CompactClause(const Clause& c): d_clause(c) { }
00291     friend std::ostream& operator<<(std::ostream& os, const CompactClause& c);
00292     std::string toString() const;
00293   };
00294 
00295 } // end of namespace CVC3
00296     
00297 #endif