search_sat.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  *\file search_sat.cpp
00004  *\brief Implementation of Search engine with generic external sat solver
00005  *
00006  * Author: Clark Barrett
00007  *
00008  * Created: Wed Dec  7 21:00:24 2005
00009  */
00010 /*****************************************************************************/
00011 
00012 
00013 #include "search_sat.h"
00014 #include "dpllt_basic.h"
00015 #include "theory_core.h"
00016 #include "eval_exception.h"
00017 #include "typecheck_exception.h"
00018 #include "expr_transform.h"
00019 #include "search_rules.h"
00020 
00021 
00022 using namespace std;
00023 using namespace CVCL;
00024 using namespace SAT;
00025 
00026 
00027 namespace CVCL {
00028 
00029 
00030 class SearchSatCoreSatAPI :public TheoryCore::CoreSatAPI {
00031   SearchSat* d_ss;
00032 public:
00033   SearchSatCoreSatAPI(SearchSat* ss) : d_ss(ss) {}
00034   ~SearchSatCoreSatAPI() {}
00035   void addLemma(const Theorem& thm) { d_ss->addLemma(thm); }
00036   int getBottomScope() { return d_ss->getBottomScope(); }
00037   Theorem addAssumption(const Expr& assump)
00038   { return d_ss->newUserAssumption(assump); }
00039   void addSplitter(const Expr& e, int priority)
00040   { d_ss->addSplitter(e, priority); }
00041 };
00042 
00043 
00044 class SearchSatTheoryAPI :public DPLLT::TheoryAPI {
00045   ContextManager* d_cm;
00046   SearchSat* d_ss;
00047 public:
00048   SearchSatTheoryAPI(SearchSat* ss)
00049     : d_cm(ss->theoryCore()->getCM()), d_ss(ss) {}
00050   ~SearchSatTheoryAPI() {}
00051   void push() { return d_cm->push(); }
00052   void pop() { return d_cm->pop(); }
00053   void assertLit(Lit l) { d_ss->assertLit(l); }
00054   DPLLT::ConsistentResult checkConsistent(Clause& c, bool fullEffort)
00055     { return d_ss->checkConsistent(c, fullEffort); }
00056   Lit getImplication() { return d_ss->getImplication(); }
00057   void getExplanation(Lit l, Clause& c) { return d_ss->getExplanation(l, c); }
00058   bool getNewClauses(CNF_Formula& cnf) { return d_ss->getNewClauses(cnf); }
00059 };
00060 
00061 
00062 class SearchSatDecider :public DPLLT::Decider {
00063   SearchSat* d_ss;
00064 public:
00065   SearchSatDecider(SearchSat* ss) : d_ss(ss) {}
00066   ~SearchSatDecider() {}
00067 
00068   Lit makeDecision() { return d_ss->makeDecision(); }
00069 };
00070 
00071 
00072 }
00073 
00074 
00075 void SearchSat::addLemma(const Theorem& thm)
00076 {
00077   //TODO: this should only hapen with new literals--
00078   //      others are handled by implication mechanism
00079   if (thm.getExpr().isAbsLiteral()// && !d_cnfManager->getCNFLit(thm.getExpr()).isNull()
00080       ) return;
00081 
00082   //  DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00083   d_rootLits.push_back(d_cnfManager->addLemma(thm, d_lemmas));
00084 
00085   // Register any new atoms
00086   Expr e;
00087   for (; d_lastRegisteredVar < d_lemmas.numVars(); ) {
00088     d_lastRegisteredVar = d_lastRegisteredVar + 1;
00089     e = d_cnfManager->concreteLit(Lit(int(d_lastRegisteredVar)));
00090     if (!e.isNull() && e.isAbsAtomicFormula()) {
00091       d_core->registerAtom(e);
00092     }
00093   }
00094   while (d_cnfManager->numVars() >= d_vars.size()) {
00095     d_vars.push_back(SmartCDO<SAT::Var::Val>(
00096                        d_core->getCM()->getCurrentContext(),
00097                        SAT::Var::UNKNOWN, 0));
00098   }
00099 }
00100 
00101 
00102 void SearchSat::addSplitter(const Expr& e, int priority)
00103 {
00104   // TODO: it's called during assertions from theory_arith.  Need to figure out the right invariant here.
00105   //  DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00106   // Not implemented yet
00107 }
00108 
00109 
00110 void SearchSat::assertLit(Lit l)
00111 {
00112   DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00113   setValue(l.getVar(), l.isPositive() ? Var::TRUE : Var::FALSE);
00114   Expr e = d_cnfManager->concreteLit(l);
00115   DebugAssert(!e.isNull(), "Expected known expr");
00116   if (!e.isAbsLiteral() || e.isUserAssumption()) return;
00117   DebugAssert(!e.isIntAssumption(), "Expected new assumption");
00118   e.setIntAssumption();
00119   Theorem thm = d_commonRules->assumpRule(e);
00120   d_intAssumptions.push_back(thm);
00121   d_core->addFact(thm);
00122 }
00123 
00124 
00125 DPLLT::ConsistentResult SearchSat::checkConsistent(Clause& c, bool fullEffort)
00126 {
00127   DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00128   if (d_core->inconsistent()) {
00129     d_cnfManager->convertLemma(d_core->inconsistentThm(), c);
00130     return DPLLT::INCONSISTENT;
00131   }
00132   if (fullEffort) {
00133     if (d_core->checkSATCore()) {
00134       if (d_core->inconsistent()) {
00135         d_cnfManager->convertLemma(d_core->inconsistentThm(), c);
00136         return DPLLT::INCONSISTENT;
00137       }
00138       else return DPLLT::CONSISTENT;
00139     }
00140   }
00141   return DPLLT::MAYBE_CONSISTENT;
00142 }
00143 
00144 
00145 Lit SearchSat::getImplication()
00146 {
00147   DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00148   Lit l;
00149   Theorem imp = d_core->getImpliedLiteral();
00150   while (!imp.isNull()) {
00151     l = d_cnfManager->getCNFLit(imp.getExpr());
00152     DebugAssert(!l.isNull() || imp.getExpr().unnegate().isUserRegisteredAtom(),
00153                 "implied literals should be registered by cnf or by user");
00154     if (!l.isNull() && getValue(l) != Var::TRUE) {
00155       d_theorems.insert(imp.getExpr(), imp);
00156       break;
00157     }
00158     l.reset();
00159     imp = d_core->getImpliedLiteral();
00160   }
00161   return l;
00162 }
00163 
00164 
00165 void SearchSat::getExplanation(Lit l, Clause& c)
00166 {
00167   DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00168   DebugAssert(c.size() == 0, "Expected size = 0");
00169   Expr e = d_cnfManager->concreteLit(l);
00170   CDMap<Expr, Theorem>::iterator i = d_theorems.find(e);
00171   DebugAssert(i != d_theorems.end(), "getExplanation: no explanation found");
00172   d_cnfManager->convertLemma((*i).second, c);  
00173 }
00174 
00175 
00176 bool SearchSat::getNewClauses(CNF_Formula& cnf)
00177 {
00178   DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00179   if (d_lemmasNext == d_lemmas.numClauses()) return false;
00180   do {
00181     cnf += d_lemmas[d_lemmasNext];
00182     d_lemmasNext = d_lemmasNext + 1;
00183   } while (d_lemmasNext < d_lemmas.numClauses());
00184   return true;
00185 }
00186 
00187 
00188 Lit SearchSat::makeDecision()
00189 {
00190   DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00191   Lit litDecision;
00192   CDList<SAT::Lit>::const_iterator i, iend;
00193   for (i = d_rootLits.begin(), iend = d_rootLits.end(); i != iend; ++i) {
00194     if (findSplitterRec(*i, getValue(*i), &litDecision)) {
00195       break;
00196     }
00197   }
00198   return litDecision;
00199 }
00200 
00201 
00202 bool SearchSat::findSplitterRec(Lit lit, Var::Val value, Lit* litDecision)
00203 {
00204   unsigned i, n;
00205   Lit litTmp;
00206   bool ret;
00207   Var v = lit.getVar();
00208 
00209   if (lit.isFalse() || lit.isTrue()) return false;
00210   DebugAssert(value != Var::UNKNOWN, "expected known value");
00211   DebugAssert(getValue(lit) == value || getValue(lit) == Var::UNKNOWN,
00212               "invariant violated");
00213 
00214   if (checkJustified(v)) return false;
00215 
00216   if (lit.isInverted()) {
00217     lit = !lit;
00218     value = Var::invertValue(value);
00219   }
00220 
00221   if (d_cnfManager->numFanins(lit) == 0) {
00222     if (getValue(lit) != Var::UNKNOWN) {
00223       setJustified(v);
00224       return false;
00225     }
00226     else {
00227       *litDecision = Lit(v, value == Var::TRUE);
00228       return true;
00229     }
00230   }
00231   else if (d_cnfManager->concreteLit(lit).isAbsAtomicFormula()) {
00232     // This node represents a predicate with embedded ITE's
00233     // We handle this case specially in order to catch the
00234     // corner case when a variable is in its own fanin.
00235     n = d_cnfManager->numFanins(lit);
00236     for (i=0; i < n; ++i) {
00237       litTmp = d_cnfManager->getFanin(lit, i);
00238       DebugAssert(!litTmp.isInverted(),"Expected positive fanin");
00239       if (checkJustified(litTmp.getVar())) continue;
00240       DebugAssert(d_cnfManager->concreteLit(litTmp.getVar()).getKind() == ITE,
00241                   "Expected ITE");
00242       DebugAssert(getValue(litTmp) == Var::TRUE,"Expected TRUE");
00243       Lit cIf = d_cnfManager->getFanin(litTmp,0);
00244       Lit cThen = d_cnfManager->getFanin(litTmp,1);
00245       Lit cElse = d_cnfManager->getFanin(litTmp,2);
00246       if (getValue(cIf) == Var::UNKNOWN) {
00247         if (getValue(cElse) == Var::TRUE ||
00248             getValue(cThen) == Var::FALSE) {
00249           ret = findSplitterRec(cIf, Var::FALSE, litDecision);
00250         }
00251         else {
00252           ret = findSplitterRec(cIf, Var::TRUE, litDecision);
00253         }
00254         if (!ret) {
00255           cout << d_cnfManager->concreteLit(cIf.getVar()) << endl;
00256           DebugAssert(false,"No controlling input found (1)");
00257         }         
00258         return true;
00259       }
00260       else if (getValue(cIf) == Var::TRUE) {
00261         if (findSplitterRec(cIf, Var::TRUE, litDecision)) {
00262             return true;
00263         }
00264         if (cThen.getVar() != v &&
00265             (getValue(cThen) == Var::UNKNOWN ||
00266              getValue(cThen) == Var::TRUE) &&
00267             findSplitterRec(cThen, Var::TRUE, litDecision)) {
00268           return true;
00269         }
00270       }
00271       else {
00272         if (findSplitterRec(cIf, Var::FALSE, litDecision)) {
00273           return true;
00274         }
00275         if (cElse.getVar() != v &&
00276             (getValue(cElse) == Var::UNKNOWN ||
00277              getValue(cElse) == Var::TRUE) &&
00278             findSplitterRec(cElse, Var::TRUE, litDecision)) {
00279           return true;
00280         }
00281       }
00282       setJustified(litTmp.getVar());
00283     }
00284     if (getValue(lit) != Var::UNKNOWN) {
00285       setJustified(v);
00286       return false;
00287     }
00288     else {
00289       *litDecision = Lit(v, value == Var::TRUE);
00290       return true;
00291     }
00292   }
00293 
00294   int kind = d_cnfManager->concreteLit(v).getKind();
00295   Var::Val valHard = Var::FALSE;
00296   switch (kind) {
00297     case AND:
00298       valHard = Var::TRUE;
00299     case OR:
00300       if (value == valHard) {
00301         n = d_cnfManager->numFanins(lit);
00302         for (i=0; i < n; ++i) {
00303           litTmp = d_cnfManager->getFanin(lit, i);
00304           if (findSplitterRec(litTmp, valHard, litDecision)) {
00305             return true;
00306           }
00307         }
00308         DebugAssert(getValue(lit) == valHard, "Output should be justified");
00309         setJustified(v);
00310         return false;
00311       }
00312       else {
00313         Var::Val valEasy = Var::invertValue(valHard);
00314         n = d_cnfManager->numFanins(lit);
00315         for (i=0; i < n; ++i) {
00316           litTmp = d_cnfManager->getFanin(lit, i);
00317           if (getValue(litTmp) != valHard) {
00318             if (findSplitterRec(litTmp, valEasy, litDecision)) {
00319               return true;
00320             }
00321             DebugAssert(getValue(lit) == valEasy, "Output should be justified");
00322             setJustified(v);
00323             return false;
00324           }
00325         }
00326         DebugAssert(false, "No controlling input found (2)");
00327       }
00328       break;
00329     case IMPLIES:
00330       DebugAssert(d_cnfManager->numFanins(lit) == 2, "Expected 2 fanins");
00331       if (value == Var::FALSE) {
00332         litTmp = d_cnfManager->getFanin(lit, 0);
00333         if (findSplitterRec(litTmp, Var::TRUE, litDecision)) {
00334           return true;
00335         }
00336         litTmp = d_cnfManager->getFanin(lit, 1);
00337         if (findSplitterRec(litTmp, Var::FALSE, litDecision)) {
00338           return true;
00339         }
00340         DebugAssert(getValue(lit) == Var::FALSE, "Output should be justified");
00341         setJustified(v);
00342         return false;
00343       }
00344       else {
00345         litTmp = d_cnfManager->getFanin(lit, 0);
00346         if (getValue(litTmp) != Var::TRUE) {
00347           if (findSplitterRec(litTmp, Var::FALSE, litDecision)) {
00348             return true;
00349           }
00350           DebugAssert(getValue(lit) == Var::TRUE, "Output should be justified");
00351           setJustified(v);
00352           return false;
00353         }
00354         litTmp = d_cnfManager->getFanin(lit, 1);
00355         if (getValue(litTmp) != Var::FALSE) {
00356           if (findSplitterRec(litTmp, Var::TRUE, litDecision)) {
00357             return true;
00358           }
00359           DebugAssert(getValue(lit) == Var::TRUE, "Output should be justified");
00360           setJustified(v);
00361           return false;
00362         }
00363         DebugAssert(false, "No controlling input found (3)");
00364       }
00365       break;
00366     case IFF: {
00367       litTmp = d_cnfManager->getFanin(lit, 0);
00368       Var::Val val = getValue(litTmp);
00369       if (val != Var::UNKNOWN) {
00370         if (findSplitterRec(litTmp, val, litDecision)) {
00371           return true;
00372         }
00373         if (value == Var::FALSE) val = Var::invertValue(val);
00374         litTmp = d_cnfManager->getFanin(lit, 1);
00375         if (findSplitterRec(litTmp, val, litDecision)) {
00376           return true;
00377         }
00378         DebugAssert(getValue(lit) == value, "Output should be justified");
00379         setJustified(v);
00380         return false;
00381       }
00382       else {
00383         val = getValue(d_cnfManager->getFanin(lit, 1));
00384         if (val == Var::UNKNOWN) val = Var::FALSE;
00385         if (value == Var::FALSE) val = Var::invertValue(val);
00386         if (findSplitterRec(litTmp, val, litDecision)) {
00387           return true;
00388         }
00389         DebugAssert(false, "Unable to find controlling input (4)");
00390       }
00391       break;
00392     }
00393     case XOR: {
00394       litTmp = d_cnfManager->getFanin(lit, 0);
00395       Var::Val val = getValue(litTmp);
00396       if (val != Var::UNKNOWN) {
00397         if (findSplitterRec(litTmp, val, litDecision)) {
00398           return true;
00399         }
00400         if (value == Var::TRUE) val = Var::invertValue(val);
00401         litTmp = d_cnfManager->getFanin(lit, 1);
00402         if (findSplitterRec(litTmp, val, litDecision)) {
00403           return true;
00404         }
00405         DebugAssert(getValue(lit) == value, "Output should be justified");
00406         setJustified(v);
00407         return false;
00408       }
00409       else {
00410         val = getValue(d_cnfManager->getFanin(lit, 1));
00411         if (val == Var::UNKNOWN) val = Var::FALSE;
00412         if (value == Var::TRUE) val = Var::invertValue(val);
00413         if (findSplitterRec(litTmp, val, litDecision)) {
00414           return true;
00415         }
00416         DebugAssert(false, "Unable to find controlling input (5)");
00417       }
00418       break;
00419     }
00420     case ITE: {
00421       Lit cIf = d_cnfManager->getFanin(lit, 0);
00422       Lit cThen = d_cnfManager->getFanin(lit, 1);
00423       Lit cElse = d_cnfManager->getFanin(lit, 2);
00424       if (getValue(cIf) == Var::UNKNOWN) {
00425         if (getValue(cElse) == value ||
00426             getValue(cThen) == Var::invertValue(value)) {
00427           ret = findSplitterRec(cIf, Var::FALSE, litDecision);
00428         }
00429         else {
00430           ret = findSplitterRec(cIf, Var::TRUE, litDecision);
00431         }
00432         if (!ret) {
00433           cout << d_cnfManager->concreteLit(cIf.getVar()) << endl;
00434           DebugAssert(false,"No controlling input found (6)");
00435         }         
00436         return true;
00437       }
00438       else if (getValue(cIf) == Var::TRUE) {
00439         if (findSplitterRec(cIf, Var::TRUE, litDecision)) {
00440             return true;
00441         }
00442         if (cThen.isVar() && cThen.getVar() != v &&
00443             (getValue(cThen) == Var::UNKNOWN ||
00444              getValue(cThen) == value) &&
00445             findSplitterRec(cThen, value, litDecision)) {
00446           return true;
00447         }
00448       }
00449       else {
00450         if (findSplitterRec(cIf, Var::FALSE, litDecision)) {
00451           return true;
00452         }
00453         if (cElse.isVar() && cElse.getVar() != v &&
00454             (getValue(cElse) == Var::UNKNOWN ||
00455              getValue(cElse) == value) &&
00456             findSplitterRec(cElse, value, litDecision)) {
00457           return true;
00458         }
00459       }
00460       DebugAssert(getValue(lit) == value, "Output should be justified");
00461       setJustified(v);
00462       return false;
00463     }
00464     default:
00465       DebugAssert(false, "Unexpected Boolean operator");
00466       break;
00467   }
00468   FatalAssert(false, "Should be unreachable");
00469   return false;
00470 }
00471 
00472 
00473 Theorem SearchSat::check(const Expr& e, bool isRestart)
00474 {
00475   if (!d_dplltReady) {
00476     throw Exception
00477       ("SAT solver is not ready: please pop all or none of SAT scopes");
00478   }
00479   if (isRestart && d_idxUserAssump != d_userAssumptions.size()) {
00480     throw Exception
00481       ("No user assumptions should be added before a restart");
00482   }
00483   if (isRestart && d_lastCheck.get().isNull()) {
00484     throw Exception
00485       ("restart called without former call to checkValid");
00486   }
00487 
00488   DebugAssert(!d_inCheckSat, "checkValid should not be called recursively");
00489   TRACE("searchsat", "checkValid: ", e, "");
00490 
00491   if (!e.getType().isBool())
00492     throw TypecheckException
00493       ("checking validity of a non-Boolean expression:\n\n  "
00494        + e.toString()
00495        + "\n\nwhich has the following type:\n\n  "
00496        + e.getType().toString());
00497 
00498   Expr e2 = e;
00499   Theorem thm;
00500   CNF_Formula_Impl cnf;
00501   DPLLT::Result res;
00502 
00503   // Set up and quick exits
00504   if (isRestart) {
00505     while (e2.isNot() && e2[0].isNot()) e2 = e2[0][0];
00506     if (e2.isTrue() || (e2.isNot() && e2[0].isFalse())) return d_lastValid;
00507     if (e2.isFalse() || (e2.isNot() && e2[0].isTrue())) {
00508       d_core->getCM()->popto(d_bottomScope);
00509       res = DPLLT::UNSAT;
00510       goto finalize;
00511     }
00512   }
00513   else {
00514     if (e.isTrue()) return (d_lastValid = d_commonRules->trueTheorem());
00515     d_core->getCM()->push();
00516     d_bottomScope = d_core->getCM()->scopeLevel();
00517     d_lastCheck = e;
00518     e2 = !e;
00519   }
00520 
00521   d_cnfManager->setBottomScope(d_bottomScope);
00522   d_dplltReady = false;
00523 
00524   newUserAssumption(e2, d_bottomScope);
00525 
00526   d_inCheckSat = true;
00527 
00528   // Translate user assumptions into cnf
00529   for (; d_idxUserAssump < d_userAssumptions.size();
00530          d_idxUserAssump.set(d_idxUserAssump + 1, d_bottomScope) ) {
00531     thm = d_userAssumptions[d_idxUserAssump];
00532     e2 = thm.getExpr();
00533     DebugAssert(e2.isUserAssumption(), "Expected only user assumptions");
00534     if (isRestart || (e2.isAbsLiteral() && !e2.unnegate().isBoolConst())) {
00535       d_rootLits.push_back(d_cnfManager->addAssumption(thm, cnf), d_bottomScope);
00536     }
00537     else {
00538       thm = d_core->getExprTrans()->preprocess(thm);
00539       e2 = thm.getExpr(); 
00540       if (e2.isFalse()) {
00541         res = DPLLT::UNSAT;
00542         goto finalize;
00543       }
00544       else if (!e2.isTrue()) {
00545         d_rootLits.push_back(d_cnfManager->addAssumption(thm, cnf), d_bottomScope);
00546       }
00547     }
00548   }
00549 
00550   // We can't register new atoms in a restart: new atoms have
00551   // to be registered at the bottom scope
00552   if (!isRestart) {
00553     // Register any new atoms
00554     for (; d_lastRegisteredVar < cnf.numVars(); ) {
00555       d_lastRegisteredVar = d_lastRegisteredVar + 1;
00556       e2 = d_cnfManager->concreteLit(Lit(int(d_lastRegisteredVar)));
00557       if (!e2.isNull() && e2.isAbsAtomicFormula()) {
00558         d_core->registerAtom(e2);
00559       }
00560     }
00561   }
00562 
00563   // Initialize d_vars vector
00564   while (d_cnfManager->numVars() >= d_vars.size()) {
00565     d_vars.push_back(SmartCDO<SAT::Var::Val>(
00566                        d_core->getCM()->getCurrentContext(),
00567                        SAT::Var::UNKNOWN, 0));
00568   }
00569 
00570   // Run DPLLT engine
00571   res = isRestart ? d_dpllt->continueCheck(cnf) : d_dpllt->checkSat(cnf);
00572 
00573  finalize:
00574   if (res == DPLLT::UNSAT) {
00575     DebugAssert(d_core->getCM()->scopeLevel() == d_bottomScope,
00576                 "Expected unchanged context after unsat");
00577     e2 = d_lastCheck;
00578     d_core->getCM()->pop();
00579     // Next line is a place-holder until we can actually get the proof
00580     d_lastValid = d_commonRules->assumpRule(e2);
00581   }
00582   else {
00583     DebugAssert(d_lemmasNext == d_lemmas.numClauses(),
00584                 "Expected no lemmas after satisfiable check");
00585     d_dplltReady = true;
00586     d_lastValid = Theorem();
00587   }
00588   d_cnfManager->setBottomScope(-1);
00589   d_inCheckSat = false;
00590   return d_lastValid;
00591 }
00592 
00593 
00594 SearchSat::SearchSat(TheoryCore* core)
00595   : SearchEngine(core),
00596     d_name("sat"),
00597     d_bottomScope(core->getCM()->getCurrentContext(), -1),
00598     d_lastCheck(core->getCM()->getCurrentContext()),
00599     d_lastValid(core->getCM()->getCurrentContext(),
00600                 d_commonRules->trueTheorem()),
00601     d_userAssumptions(core->getCM()->getCurrentContext()),
00602     d_intAssumptions(core->getCM()->getCurrentContext()),
00603     d_idxUserAssump(core->getCM()->getCurrentContext(), 0),
00604     d_theorems(core->getCM()->getCurrentContext()),
00605     d_inCheckSat(false),
00606     d_lemmas(core->getCM()->getCurrentContext()),
00607     d_lemmasNext(core->getCM()->getCurrentContext(), 0),
00608     d_rootLits(core->getCM()->getCurrentContext()),
00609     d_lastRegisteredVar(core->getCM()->getCurrentContext(), 0),
00610     d_dplltReady(core->getCM()->getCurrentContext(), true),
00611     d_nextImpliedLiteral(core->getCM()->getCurrentContext(), 0),
00612     d_restorer(core->getCM()->getCurrentContext(), this)
00613 {
00614   d_cnfManager = new CNF_Manager(core->getTM());
00615   d_coreSatAPI = new SearchSatCoreSatAPI(this);
00616   core->registerCoreSatAPI(d_coreSatAPI);
00617   d_theoryAPI = new SearchSatTheoryAPI(this);
00618   d_decider = new SearchSatDecider(this);
00619   d_dpllt = new DPLLTBasic(d_theoryAPI, d_decider);
00620 }
00621 
00622 
00623 SearchSat::~SearchSat()
00624 {
00625   delete d_dpllt;
00626   delete d_decider;
00627   delete d_theoryAPI;
00628   delete d_coreSatAPI;
00629   delete d_cnfManager;
00630 }
00631 
00632 
00633 void SearchSat::registerAtom(const Expr& e)
00634 {
00635   d_core->registerAtom(e);
00636   e.setUserRegisteredAtom();
00637 }
00638 
00639 
00640 Theorem SearchSat::getImpliedLiteral(void)
00641 {
00642   Theorem imp;
00643   while (d_nextImpliedLiteral < d_core->numImpliedLiterals()) {
00644     imp = d_core->getImpliedLiteralByIndex(d_nextImpliedLiteral);
00645     d_nextImpliedLiteral = d_nextImpliedLiteral + 1;
00646     if (imp.getExpr().unnegate().isUserRegisteredAtom()) return imp;
00647   }
00648   return Theorem();
00649 }
00650 
00651 
00652 void SearchSat::returnFromCheck()
00653 {
00654   if (d_bottomScope < 0) {
00655     throw Exception
00656       ("returnFromCheck called with no previous invalid call to checkValid");
00657   }
00658   d_core->getCM()->popto(d_bottomScope);
00659   d_core->getCM()->pop();
00660 }
00661 
00662 
00663 Theorem SearchSat::newUserAssumption(const Expr& e, int scope)
00664 {
00665   DebugAssert(!d_inCheckSat,
00666               "User assumptions should be added before calling checkSat");
00667   Theorem thm;
00668   if (!isAssumption(e)) {
00669     e.setUserAssumption(scope);
00670     thm = d_commonRules->assumpRule(e, scope);
00671     d_userAssumptions.push_back(thm, scope);
00672 
00673     // Immediately propagate facts at current scope level
00674     if ((scope == -1 || scope == d_core->getCM()->scopeLevel()) &&
00675         thm.getExpr().isAbsLiteral()) d_core->addFact(thm);
00676   }
00677   return thm;
00678 }
00679 
00680 
00681 void SearchSat::getUserAssumptions(vector<Expr>& assumptions)
00682 {
00683   for(CDList<Theorem>::const_iterator i=d_userAssumptions.begin(),
00684         iend=d_userAssumptions.end(); i!=iend; ++i)
00685     assumptions.push_back((*i).getExpr());
00686 }
00687 
00688 
00689 void SearchSat::getInternalAssumptions(vector<Expr>& assumptions)
00690 {
00691   for(CDList<Theorem>::const_iterator i=d_intAssumptions.begin(),
00692         iend=d_intAssumptions.end(); i!=iend; ++i)
00693     assumptions.push_back((*i).getExpr());
00694 }
00695 
00696 
00697 void SearchSat::getAssumptions(vector<Expr>& assumptions)
00698 {
00699   CDList<Theorem>::const_iterator iU=d_userAssumptions.begin(),
00700     iUend=d_userAssumptions.end(), iI = d_intAssumptions.begin(),
00701     iIend=d_intAssumptions.end();
00702   while (true) {
00703     if (iI == iIend) {
00704       if (iU == iUend) break;
00705       assumptions.push_back((*iU).getExpr());
00706       ++iU;
00707     }
00708     else if (iU == iUend) {
00709       assumptions.push_back((*iI).getExpr());
00710       ++iI;
00711     }
00712     else {
00713       if ((*iI).getScope() <= (*iU).getScope()) {
00714         assumptions.push_back((*iI).getExpr());
00715         ++iI;
00716       }
00717       else {
00718         assumptions.push_back((*iU).getExpr());
00719         ++iU;
00720       }
00721     }
00722   }
00723 }
00724 
00725 
00726 bool SearchSat::isAssumption(const Expr& e)
00727 {
00728   return e.isUserAssumption() || e.isIntAssumption();
00729 }
00730 
00731 
00732 void SearchSat::getCounterExample(vector<Expr>& assumptions, bool inOrder)
00733 {
00734   if (!d_lastValid.get().isNull()) {
00735     throw Exception("Expected last query to be invalid");
00736   }
00737   getInternalAssumptions(assumptions);
00738 }
00739 
00740 
00741 Proof SearchSat::getProof()
00742 {
00743   FatalAssert(false, "Not Implemented Yet");
00744   return Proof();
00745 }

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