CVC3

minisat_derivation.h

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  *\file minisat_derivation.h
00004  *\brief MiniSat proof logging
00005  *
00006  * Author: Alexander Fuchs
00007  *
00008  * Created: Sun Dec 07 11:09:00 2007
00009  *
00010  * <hr>
00011  *
00012  * License to use, copy, modify, sell and/or distribute this software
00013  * and its documentation for any purpose is hereby granted without
00014  * royalty, subject to the terms and conditions defined in the \ref
00015  * LICENSE file provided with this distribution.
00016  * 
00017  * <hr>
00018  */
00019 /*****************************************************************************/
00020 
00021 #ifndef _cvc3__sat__minisat_derivation_h_
00022 #define _cvc3__sat__minisat_derivation_h_
00023 
00024 
00025 #include "minisat_types.h"
00026 #include <hash_map.h>
00027 #include <hash_set.h>
00028 #include <set>
00029 #include <vector>
00030 #include <deque>
00031 #include <algorithm>
00032 #include <string>
00033 
00034 namespace SAT {
00035   class SatProof;
00036 }
00037 
00038 namespace MiniSat {
00039   // a resolution inference as a sequence of binary resolution steps
00040   class Inference {
00041   public:
00042     typedef std::vector<std::pair<Lit, int> > TSteps;
00043 
00044   private:
00045     // id of first clause
00046     int d_start;
00047 
00048     // binary resolution step:
00049     // result of previous step (or d_start)
00050     // on literal with next clause (given by id)
00051     TSteps d_steps;
00052 
00053   public:
00054     Inference(int clauseID) : d_start(clauseID) {
00055       //      std::cout << "Start inference: " << clauseID << std::endl;
00056     };
00057 
00058     void add(Lit lit, int clauseID) {
00059       d_steps.push_back(std::make_pair(lit, clauseID));
00060     };
00061 
00062     void add(Lit lit, Clause* clause) {
00063       add(lit, clause->id());
00064     };
00065 
00066     int getStart() const {
00067       return d_start;
00068     }
00069 
00070     const TSteps& getSteps() const {
00071       return d_steps;
00072     }
00073 
00074     // returns steps as a lits: clauseId0 literal0.toString clauseID1 ...
00075     std::string toString() const;
00076   };
00077 
00078 
00079   class Solver;
00080 
00081   // Heavily based on the proof logging version of MiniSat (1.14p)
00082   //
00083   // Note: this implementation keeps the whole derivation in memory -
00084   // for many problems this is not feasible.
00085   // should provide an alternative implementation that logs the derivation
00086   // to a file and constructs the proof from it.
00087   class Derivation {
00088   public:
00089     typedef Hash::hash_map<int, Clause*> TClauses;
00090     typedef Hash::hash_set<int> TInputClauses;
00091     typedef Hash::hash_map<int, Inference*> TInferences;
00092 
00093   private:
00094     // mapping from id to clause
00095     TClauses d_clauses;
00096 
00097     // as an additional check, explicitely mark which clauses are input clauses
00098     // by adding their id to this set.
00099     //
00100     // as an invariant an id should be either in d_inferences or d_inputClauses,
00101     // as a clause does exactly have no inference attached if it is an input clause.
00102     TInputClauses d_inputClauses;
00103 
00104     // unit clauses derived with computeRootReason
00105     // mapping from index of literal to clause
00106     TClauses d_unitClauses;
00107 
00108     // mapping from clause id to the inference it was derived by
00109     TInferences d_inferences;
00110 
00111     // clauses removed from the solver
00112     std::deque<Clause*> d_removedClauses;
00113 
00114     // empty clause of derivation, if derived
00115     Clause* d_emptyClause;
00116 
00117   public:
00118     Derivation() : d_emptyClause(NULL) {};
00119     ~Derivation();
00120 
00121     // note: allow for duplicate insertion of clauses registerClause and registerInputClause,
00122     // as this can happen in the current implementation
00123     // for theory clauses which are inconsistent on insertion.
00124 
00125     // register a new clause
00126     void registerClause(Clause* clause) {
00127       //      std::cout << "register clause  : " << clause->id() << " : " << clause->toString() << std::endl;
00128 
00129       //IF_DEBUG (
00130         if (d_clauses.contains(clause->id())) {
00131     // if clause with id does already exist,
00132     // then it must be a simplification of the original clause
00133     Clause* old = d_clauses[clause->id()];
00134     FatalAssert(old->size() == clause->size(),
00135           "MiniSat::Derivation::registerClause: new clause of different size than old clause of same id");
00136 
00137     std::set<Lit> oldS;
00138     for (int i = 0; i < old->size(); ++i) {
00139       oldS.insert((*old)[i]);
00140     }
00141 
00142     for (int i = 0; i < clause->size(); ++i) {
00143       FatalAssert(oldS.find((*clause)[i]) != oldS.end(),
00144       "MiniSat::Derivation::registerClause: new clause not subset of old clause of same id");
00145       oldS.erase((*clause)[i]);
00146     }
00147     FatalAssert(oldS.empty(),
00148           "MiniSat::Derivation::registerClause: old clause not subset of new clause of same id");
00149   }
00150   //)
00151       d_clauses[clause->id()] = clause;
00152     };
00153 
00154     // mark clause as input clause, i.e. true without premises
00155     void registerInputClause(int clauseID) {
00156       //      std::cout << "registerInputClause: " << clauseID << std::endl;
00157       d_inputClauses.insert(clauseID);
00158     };
00159 
00160     // clause has been removed from the solver or created internally in Derivation,
00161     // so store it here for later garbage collection.
00162     void removedClause(Clause* clause) {
00163       FatalAssert(clause != NULL, "MiniSat::derivation:removedClause: NULL");
00164       d_removedClauses.push_back(clause);
00165     };
00166 
00167     // register the inference of a clause; takes ownership of inference
00168     void registerInference(int clauseID, Inference* inference) {
00169       FatalAssert(!d_inferences.contains(clauseID),
00170       "MiniSat::Derivation::registerInference: inference for clauseID already registered");
00171       //      std::cout << "Register inference: " << clauseID << " : " << inference->toString() << std::endl;
00172       d_inferences[clauseID] = inference;
00173     };
00174 
00175     // implied is a literal that is implied at the root level.
00176     // return the id of the implying unit clause [literal], if it exists.
00177     //
00178     // otherwise derive it from its reasons and return the new clause id.
00179     // derived unit clauses are stored internally, independently of the Solver
00180     //
00181     // may resolve theory implications with Solver::resolveTheoryImplication
00182     int computeRootReason(Lit implied, Solver* solver);
00183 
00184 
00185     // register the empty clause (or a clause falsified in the root level)
00186     // showing that the clause set is unsatisfiable.
00187     //
00188     // if clause is not the empty clause, the empty clause is derived from it,
00189     // possible using computeRootReason
00190     void finish(Clause* clause, Solver* solver);
00191 
00192 
00193     // print the derivation of the given clause
00194     //
00195     // output is of the form:
00196     // ID D : L1 ... Ln : C1 K1 C2 K2 ... Cm
00197     // where:
00198     // ID - the id of a clause
00199     // D - 'I' for an input clause, 'D' for a clause derived from other clauses
00200     // Li - the clause literals
00201     // Ci Ki - the clause is derived from these clauses by binary resolution on the given literals
00202     //
00203     // factoring is done after each resolution step, i.e. duplicate literals are removed from the clause.
00204     //
00205     // example:
00206     // 3 D : +12 -2 -33 : 1 +10 2
00207     // says that the clause with the id 3 consists of the literals +12, -2, -33,
00208     // and was derived by resolution between the clauses with ids 1 and 2,
00209     // where the literal +10 is in clause 1 and -10 is in clause 2.
00210     //
00211     // for example, 1 may be the clause +12 +10 -2, and 2 may be -10 -2 -33,
00212     // which resolved on +10 yield the clause +12 -2 -2 -33,
00213     // which after factoring simplified to +12 -2 -33.
00214     void printDerivation(Clause* clause);
00215 
00216     // print the derivation of the empty clause.
00217     void printDerivation();
00218 
00219     // for debugging only
00220     void checkDerivation(Clause* clause);
00221 
00222     // creates a new proof; ownership transferred to caller
00223     SAT::SatProof* createProof();
00224     SAT::SatProof* createProof(Clause* clause);
00225 
00226     // see Solver::push - clauseID is the highest currently used clause id
00227     void push(int clauseID);
00228 
00229     // see Solver::pop - clauseID corresponds to a clause id used in a push
00230     void pop(int clauseID);
00231   };
00232 }
00233 
00234 
00235 #endif