minisat_derivation.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  *\file minisat_derivation.cpp
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 
00022 #include "minisat_derivation.h"
00023 #include "minisat_solver.h"
00024 #include <set>
00025 #include <iostream>
00026 
00027 using namespace MiniSat;
00028 using namespace std;
00029 
00030 std::string Inference::toString() const {
00031   ostringstream buffer;
00032   buffer << getStart();
00033   for (Inference::TSteps::const_iterator step = d_steps.begin(); step != d_steps.end(); ++step) {
00034     buffer << " " << step->first.toString() << " " << step->second;
00035   }
00036   return buffer.str();
00037 }
00038 
00039 
00040 
00041 
00042 
00043 Derivation::~Derivation() {
00044   // deallocate generated unit clauses
00045   for (TClauses::iterator i = d_unitClauses.begin(); i != d_unitClauses.end(); ++i) {
00046     xfree(i->second);
00047   }
00048   
00049   // deallocate removed clauses
00050   for (std::deque<Clause*>::iterator i = d_removedClauses.begin(); i != d_removedClauses.end(); ++i) {
00051     xfree(*i);
00052   }
00053   
00054   // deallocate inferences
00055   for (TInferences::iterator i = d_inferences.begin(); i != d_inferences.end(); ++i) {
00056     delete i->second;
00057   }
00058 }
00059 
00060 
00061 int Derivation::computeRootReason(Lit implied, Solver* solver) {
00062   Clause* reason = solver->getReason(implied);
00063   DebugAssert(reason != NULL, "MiniSat::Derivation::computeRootReason: implied reason is NULL");
00064   DebugAssert(reason != Clause::Decision(), "MiniSat::Derivation::computeRootReason: implied is a decision");
00065   DebugAssert((*reason)[0] == implied, "MiniSat::Derivation::computeRootReason: implied is not in its reason");
00066   IF_DEBUG (
00067     DebugAssert(solver->getValue((*reason)[0]) == l_True,
00068     "MiniSat::Derivation::computeRootReason: literal not implied (TRUE)");
00069     for (int i = 1; i < reason->size(); ++i) {
00070       DebugAssert(solver->getValue((*reason)[i]) == l_False,
00071       "MiniSat::Derivation::computeRootReason: literal not implied (FALSE)");
00072     }
00073   )
00074 
00075   // already a unit clause, so done
00076   if (reason->size() == 1) {
00077     return reason->id();
00078   }
00079 
00080   // already derived the unit clause internally
00081   TClauses::const_iterator iter = d_unitClauses.find(implied.index());
00082   if (iter != d_unitClauses.end()) {
00083     return iter->second->id();
00084   }
00085 
00086 
00087   // otherwise resolve the reason ...
00088   Inference* inference = new Inference(reason->id());
00089   for (int i = 1; i < reason->size(); ++i) {
00090     Lit lit((*reason)[i]);
00091     inference->add(lit, computeRootReason(~lit, solver));
00092   }
00093 
00094   // and create the new unit clause
00095   // (after resolve, so that clause ids are chronological wrt. inference)
00096   vector<Lit> literals;
00097   literals.push_back(implied);
00098   Clause* unit = Clause_new(literals, solver->nextClauseID());
00099 
00100   d_unitClauses[implied.index()] = unit;
00101   registerClause(unit);
00102   registerInference(unit->id(), inference);
00103 
00104   return unit->id();
00105 }
00106 
00107 
00108 void Derivation::finish(Clause* clause, Solver* solver) {
00109   DebugAssert(clause != NULL, "MiniSat::derivation:finish:");
00110 
00111   // already the empty clause
00112   if (clause->size() == 0) {
00113     d_emptyClause = clause;
00114   }
00115   // derive the empty clause
00116   else {
00117     Inference* inference = new Inference(clause->id());
00118     for (int i = 0; i < clause->size(); ++i) {
00119       Lit lit((*clause)[i]);
00120       inference->add(lit, computeRootReason(~lit, solver));
00121     }
00122     vector<Lit> literals;
00123     Clause* empty = Clause_new(literals, solver->nextClauseID());
00124     removedClause(empty);
00125     d_emptyClause = empty;
00126     registerClause(empty);
00127     registerInference(empty->id(), inference);
00128   }
00129 
00130 //     cout << "PROOF_START" << endl;
00131 //     printProof();
00132 //     cout << "PROOF_END" << endl;
00133 };
00134 
00135 
00136 void Derivation::printProof() {
00137   DebugAssert(d_emptyClause != NULL, "MiniSat::Derivation:printProof: no empty clause");
00138   printProof(d_emptyClause);
00139 }
00140 
00141 void Derivation::printProof(Clause* clause) {
00142   // find all relevant clauses
00143 
00144   // - relevant: set clauses used in derivation
00145   // - regress: relevant clauses whose antecedents have to be checked
00146   std::set<int> relevant;
00147   std::set<int> regress;
00148 
00149   regress.insert(clause->id());
00150   while (!regress.empty()) {
00151     // pick next clause to derive - start from bottom, i.e. latest derived clause
00152     int clauseID = *(regress.rbegin());
00153     regress.erase(clauseID);
00154 
00155     // move to clauses relevant for the derivation
00156     DebugAssert(relevant.count(clauseID) == 0, "Solver::printProof: already in relevant");
00157     relevant.insert(clauseID);
00158 
00159     // process antecedents
00160     TInferences::const_iterator iter = d_inferences.find(clauseID);
00161     // input clause
00162     if (iter == d_inferences.end()) {
00163       DebugAssert(d_inputClauses.contains(clauseID),
00164       "Solver::printProof: clause without antecedents is not marked as input clause");
00165     }
00166 
00167     else {
00168       Inference* inference = iter->second;
00169       regress.insert(inference->getStart());
00170       const Inference::TSteps& steps = inference->getSteps();
00171       for (Inference::TSteps::const_iterator step = steps.begin(); step != steps.end(); ++step) {
00172   regress.insert(step->second);
00173       }
00174     }
00175   }
00176 
00177 
00178   // print proof
00179   for (std::set<int>::iterator i = relevant.begin(); i != relevant.end(); ++i) {
00180     int clauseID = *i;
00181     DebugAssert(d_clauses.contains(clauseID), "Solver::printProof: clause id in proof is not in clauses");
00182     Clause* clause = d_clauses.find(clauseID)->second;
00183 
00184     Inference* inference = NULL;
00185     TInferences::const_iterator j = d_inferences.find(clauseID);
00186     if (j != d_inferences.end()) {
00187       inference = j->second;
00188     }
00189 
00190     // ID D : L1 ... Ln : C1 K1 C2 K2 ... Cm
00191     cout << clauseID;
00192     // input clause or derived clause?
00193     if (d_inputClauses.contains(clauseID)) {
00194       cout << " I ";
00195     } else {
00196       cout << " D ";
00197     }      
00198     cout << ": " << clause->toString() << " : ";
00199     if (inference != NULL) cout << inference->toString();
00200     cout << endl;    
00201   }
00202 }
00203 
00204 
00205 void Derivation::push(int clauseID) {
00206 }
00207 
00208 void Derivation::pop(int clauseID) {
00209   // remove all popped clauses
00210   TClauses::iterator i = d_clauses.begin();
00211   while (i != d_clauses.end()) {
00212     if ((*i).second->pushID() > clauseID) {
00213       int id = (*i).first;
00214       ++i;
00215       d_clauses.erase(id);
00216       d_unitClauses.erase(id);
00217       d_inferences.erase(id);
00218     }
00219     else {
00220       ++i;
00221     }
00222   }
00223 
00224   // undo conflicting clause
00225   if (d_emptyClause != NULL && d_emptyClause->pushID() > clauseID)
00226     d_emptyClause = NULL;
00227 
00228   // delete popped and removed clauses
00229   std::deque<Clause*>::iterator j = d_removedClauses.begin();
00230   while (j != d_removedClauses.end()) {
00231     if ((*j)->pushID() > clauseID) {
00232       xfree(*j);
00233       j = d_removedClauses.erase(j);
00234     } else {
00235       ++j;
00236     }
00237   }
00238 }

Generated on Tue Jul 3 14:33:37 2007 for CVC3 by  doxygen 1.5.1