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

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