/*****************************************************************************/ /*! *\file dpllt_minisat.cpp *\brief Implementation of dpllt module using MiniSat * * Author: Alexander Fuchs * * Created: Fri Sep 08 11:04:00 2006 * *
* * License to use, copy, modify, sell and/or distribute this software * and its documentation for any purpose is hereby granted without * royalty, subject to the terms and conditions defined in the \ref * LICENSE file provided with this distribution. * *
*/ /*****************************************************************************/ #include "dpllt_minisat.h" #include "minisat_solver.h" #include "exception.h" using namespace std; using namespace CVC3; using namespace SAT; DPLLTMiniSat::DPLLTMiniSat(TheoryAPI* theoryAPI, Decider* decider, bool printStats) : DPLLT(theoryAPI, decider), d_printStats(printStats) { pushSolver(); }; DPLLTMiniSat::~DPLLTMiniSat() { while (!d_solvers.empty()) { // don't pop theories, this is not allowed when cvc shuts down. delete (d_solvers.top()); d_solvers.pop(); } } MiniSat::Solver* DPLLTMiniSat::getActiveSolver() { DebugAssert(!d_solvers.empty(), "DPLLTMiniSat::getActiveSolver: no solver"); return d_solvers.top(); }; void DPLLTMiniSat::pushSolver() { if (d_solvers.empty()) { d_solvers.push(new MiniSat::Solver(d_theoryAPI, d_decider)); } else { d_solvers.push(MiniSat::Solver::createFrom(getActiveSolver())); } } QueryResult DPLLTMiniSat::search() { DebugAssert(d_solvers.size() > 0, "DPLLTMiniSat::search: no solver"); DebugAssert(getActiveSolver()->inPush(), "DPLLTMiniSat::search: solver not pushed"); // search MiniSat::Solver* solver = getActiveSolver(); QueryResult result = solver->search(); // print statistics if (d_printStats) { switch (result) { case SATISFIABLE: break; case UNSATISFIABLE: cout << "Instance unsatisfiable" << endl; break; case ABORT: cout << "aborted, unable to determine the satisfiablility of the instance" << endl; break; case UNKNOWN: cout << "unknown, unable to determing the satisfiablility of the instance" << endl; break; default: FatalAssert(false, "DPLTBasic::handle_result: Unknown outcome"); } cout << "Number of Decisions\t\t\t" << solver->getStats().decisions << endl; cout << "Number of Propagations\t\t\t" << solver->getStats().propagations << endl; cout << "Number of Propositional Conflicts\t" << (solver->getStats().conflicts - solver->getStats().theory_conflicts) << endl; cout << "Number of Theory Conflicts\t\t" << solver->getStats().theory_conflicts << endl; cout << "Number of Variables\t\t\t" << solver->nVars() << endl; cout << "Number of Literals\t\t\t" << (solver->getStats().clauses_literals + solver->getStats().learnts_literals) << endl; cout << "Max. Number of Literals\t\t\t" << solver->getStats().max_literals << endl; cout << "Number of Clauses\t\t\t" << solver->getClauses().size() << endl; cout << "Number of Lemmas\t\t\t" << solver->getLemmas().size() << endl; cout << "Max. Decision Level\t\t\t" << solver->getStats().max_level << endl; cout << "Number of Deleted Clauses\t\t" << solver->getStats().del_clauses << endl; cout << "Number of Deleted Lemmas\t\t" << solver->getStats().del_lemmas << endl; cout << "Number of Database Simplifications\t" << solver->getStats().db_simpl << endl; cout << "Number of Lemma Cleanups\t\t" << solver->getStats().lm_simpl << endl; cout << "Debug\t\t\t\t\t" << solver->getStats().debug << endl; } // the dpllt interface requires that for an unsat result // all theory pops are undone right away. if (result == UNSATISFIABLE) { d_solvers.top()->popTheories(); d_theoryAPI->pop(); } return result; } QueryResult DPLLTMiniSat::checkSat(const CNF_Formula& cnf) { DebugAssert(d_solvers.size() > 0, "DPLLTMiniSat::checkSat: no solver"); // perform any requested solver pops getActiveSolver()->doPops(); DebugAssert(!getActiveSolver()->inSearch(), "DPLLTMiniSat::checkSat: solver already in search"); // required by dpllt interface: theory push before search d_theoryAPI->push(); // solver already in use, so create a new solver if (getActiveSolver()->inSearch()) { pushSolver(); } // add new formula and search getActiveSolver()->addFormula(cnf, false); return search(); } QueryResult DPLLTMiniSat::continueCheck(const CNF_Formula& cnf) { DebugAssert(d_solvers.size() > 0, "DPLLTMiniSat::continueCheck: no solver"); // if the current solver has no push, all its pushes have already been undone, // so remove it if (!getActiveSolver()->inPush()) { DebugAssert(!getActiveSolver()->inSearch(), "DPLLTMiniSat::continueCheck: solver without push in search"); delete getActiveSolver(); d_solvers.pop(); } // perform any requested solver pops getActiveSolver()->doPops(); DebugAssert(d_solvers.size() > 0, "DPLLTMiniSat::continueCheck: no solver (2)"); DebugAssert(getActiveSolver()->inPush(), "DPLLTMiniSat::continueCheck: solver not in push"); DebugAssert(getActiveSolver()->inSearch(), "DPLLTMiniSat::continueCheck: solver not in search"); // add new formula and search getActiveSolver()->addFormula(cnf, false); return search(); } void DPLLTMiniSat::push() { // perform any requested solver pops getActiveSolver()->doPops(); // if the current solver is already in a search, then create a new one if (getActiveSolver()->inSearch()) { pushSolver(); } getActiveSolver()->push(); d_theoryAPI->push(); } void DPLLTMiniSat::pop() { DebugAssert(d_solvers.size() > 0, "DPLLTMiniSat::pop: no solver"); // if the current solver has no push, all its pushes have already been undone, // so remove it if (!getActiveSolver()->inPush()) { DebugAssert(!getActiveSolver()->inSearch(), "DPLLTMiniSat::pop: solver without push in search"); delete getActiveSolver(); d_solvers.pop(); } DebugAssert(d_solvers.size() > 0, "DPLLTMiniSat::pop: no solver 2"); DebugAssert(getActiveSolver()->inPush(), "DPLLTMiniSat::pop: solver not in push"); // undo checkSat theory push for an invalid query. // for a valid query this is done in search right away. if (getActiveSolver()->inSearch() && getActiveSolver()->isConsistent()) { d_theoryAPI->pop(); } getActiveSolver()->requestPop(); d_theoryAPI->pop(); } void DPLLTMiniSat::addAssertion(const CNF_Formula& cnf) { // perform any requested solver pops getActiveSolver()->doPops(); // if the current solver is already performing a search create a new solver if (getActiveSolver()->inSearch()) { pushSolver(); } getActiveSolver()->addFormula(cnf, false); // Immediately assert unit clauses - // the intention is to make these immediately available for interactive use for (CNF_Formula::const_iterator i = cnf.begin(); i != cnf.end(); ++i) { if ((*i).isUnit()) d_theoryAPI->assertLit(*(*i).begin()); } } Var::Val DPLLTMiniSat::getValue(Var var) { DebugAssert(d_solvers.size() > 0, "DPLLTMiniSat::getValue: should be called after a previous satisfiable result"); MiniSat::lbool value = getActiveSolver()->getValue(MiniSat::cvcToMiniSat(var)); if (value == MiniSat::l_True) return Var::TRUE_VAL; else if (value == MiniSat::l_False) return Var::FALSE_VAL; else return Var::UNKNOWN; }