00001
00002
00003
00004
00005
00006
00007
00008
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
00078
00079 if (thm.getExpr().isAbsLiteral()
00080 ) return;
00081
00082
00083 d_rootLits.push_back(d_cnfManager->addLemma(thm, d_lemmas));
00084
00085
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
00105
00106
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
00233
00234
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
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
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
00551
00552 if (!isRestart) {
00553
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
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
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
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
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 }