00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "search_sat.h"
00023 #ifdef DPLL_BASIC
00024 #include "dpllt_basic.h"
00025 #endif
00026 #include "dpllt_minisat.h"
00027 #include "theory_core.h"
00028 #include "eval_exception.h"
00029 #include "typecheck_exception.h"
00030 #include "expr_transform.h"
00031 #include "search_rules.h"
00032 #include "command_line_flags.h"
00033 #include "theorem_manager.h"
00034 #include "theory.h"
00035 #include "debug.h"
00036
00037
00038 using namespace std;
00039 using namespace CVC3;
00040 using namespace SAT;
00041
00042
00043 namespace CVC3 {
00044
00045
00046 class SearchSatCoreSatAPI :public TheoryCore::CoreSatAPI {
00047 SearchSat* d_ss;
00048 public:
00049 SearchSatCoreSatAPI(SearchSat* ss) : d_ss(ss) {}
00050 ~SearchSatCoreSatAPI() {}
00051 void addLemma(const Theorem& thm, int priority, bool atBottomScope)
00052 { d_ss->addLemma(thm, priority, atBottomScope); }
00053 Theorem addAssumption(const Expr& assump)
00054 { return d_ss->newUserAssumption(assump); }
00055 void addSplitter(const Expr& e, int priority)
00056 { d_ss->addSplitter(e, priority); }
00057 bool check(const Expr& e);
00058
00059 };
00060
00061
00062 bool SearchSatCoreSatAPI::check(const Expr& e)
00063 {
00064 Theorem thm;
00065 d_ss->push();
00066 QueryResult res = d_ss->check(e, thm);
00067 d_ss->pop();
00068 return res == VALID;
00069 }
00070
00071
00072 class SearchSatTheoryAPI :public DPLLT::TheoryAPI {
00073 ContextManager* d_cm;
00074 SearchSat* d_ss;
00075 public:
00076 SearchSatTheoryAPI(SearchSat* ss)
00077 : d_cm(ss->theoryCore()->getCM()), d_ss(ss) {}
00078 ~SearchSatTheoryAPI() {}
00079 void push() { return d_cm->push(); }
00080 void pop() { return d_cm->pop(); }
00081 void assertLit(Lit l) { d_ss->assertLit(l); }
00082 SAT::DPLLT::ConsistentResult checkConsistent(CNF_Formula& cnf, bool fullEffort)
00083 { return d_ss->checkConsistent(cnf, fullEffort); }
00084 bool outOfResources() { return d_ss->theoryCore()->outOfResources(); }
00085 Lit getImplication() { return d_ss->getImplication(); }
00086 void getExplanation(Lit l, CNF_Formula& cnf) { return d_ss->getExplanation(l, cnf); }
00087 bool getNewClauses(CNF_Formula& cnf) { return d_ss->getNewClauses(cnf); }
00088 };
00089
00090
00091 class SearchSatDecider :public DPLLT::Decider {
00092 SearchSat* d_ss;
00093 public:
00094 SearchSatDecider(SearchSat* ss) : d_ss(ss) {}
00095 ~SearchSatDecider() {}
00096
00097 Lit makeDecision() { return d_ss->makeDecision(); }
00098 };
00099
00100
00101 class SearchSatCNFCallback :public CNF_Manager::CNFCallback {
00102 SearchSat* d_ss;
00103 public:
00104 SearchSatCNFCallback(SearchSat* ss) : d_ss(ss) {}
00105 ~SearchSatCNFCallback() {}
00106
00107 void registerAtom(const Expr& e, const Theorem& thm)
00108 { d_ss->theoryCore()->theoryOf(e)->registerAtom(e, thm); }
00109 };
00110
00111
00112 }
00113
00114
00115 void SearchSat::restorePre()
00116 {
00117 if (d_core->getCM()->scopeLevel() == d_bottomScope) {
00118 DebugAssert(d_prioritySetBottomEntriesSizeStack.size() > 0, "Expected non-empty stack");
00119 d_prioritySetBottomEntriesSize = d_prioritySetBottomEntriesSizeStack.back();
00120 d_prioritySetBottomEntriesSizeStack.pop_back();
00121 while (d_prioritySetBottomEntriesSize < d_prioritySetBottomEntries.size()) {
00122 d_prioritySet.erase(d_prioritySetBottomEntries.back());
00123 d_prioritySetBottomEntries.pop_back();
00124 }
00125 }
00126 }
00127
00128
00129 void SearchSat::restore()
00130 {
00131 while (d_prioritySetEntriesSize < d_prioritySetEntries.size()) {
00132 d_prioritySet.erase(d_prioritySetEntries.back());
00133 d_prioritySetEntries.pop_back();
00134 }
00135 while (d_pendingLemmasSize < d_pendingLemmas.size()) {
00136 d_pendingLemmas.pop_back();
00137 d_pendingScopes.pop_back();
00138 }
00139 while (d_varsUndoListSize < d_varsUndoList.size()) {
00140 d_vars[d_varsUndoList.back()] = SAT::Var::UNKNOWN;
00141 d_varsUndoList.pop_back();
00142 }
00143 }
00144
00145
00146 bool SearchSat::recordNewRootLit(Lit lit, int priority, bool atBottomScope)
00147 {
00148 DebugAssert(d_prioritySetEntriesSize == d_prioritySetEntries.size() &&
00149 d_prioritySetBottomEntriesSize == d_prioritySetBottomEntries.size(),
00150 "Size mismatch");
00151 pair<set<LitPriorityPair>::iterator,bool> status =
00152 d_prioritySet.insert(LitPriorityPair(lit, priority));
00153 if (!status.second) return false;
00154 if (!atBottomScope || d_bottomScope == d_core->getCM()->scopeLevel()) {
00155 d_prioritySetEntries.push_back(status.first);
00156 d_prioritySetEntriesSize = d_prioritySetEntriesSize + 1;
00157 }
00158 else {
00159 d_prioritySetBottomEntries.push_back(status.first);
00160 ++d_prioritySetBottomEntriesSize;
00161 }
00162
00163 if (d_prioritySetStart.get() == d_prioritySet.end() ||
00164 ((*status.first) < (*(d_prioritySetStart.get()))))
00165 d_prioritySetStart = status.first;
00166 return true;
00167 }
00168
00169
00170 void SearchSat::addLemma(const Theorem& thm, int priority, bool atBottomScope)
00171 {
00172 IF_DEBUG(
00173 string indentStr(theoryCore()->getCM()->scopeLevel(), ' ');
00174 TRACE("addLemma", indentStr, "AddLemma: ", thm.getExpr().toString(PRESENTATION_LANG));
00175 )
00176
00177 DebugAssert(d_pendingLemmasSize == d_pendingLemmas.size(), "Size mismatch");
00178 DebugAssert(d_pendingLemmasSize == d_pendingScopes.size(), "Size mismatch");
00179 DebugAssert(d_pendingLemmasNext <= d_pendingLemmas.size(), "Size mismatch");
00180 d_pendingLemmas.push_back(pair<Theorem,int>(thm, priority));
00181 d_pendingScopes.push_back(atBottomScope);
00182 d_pendingLemmasSize = d_pendingLemmasSize + 1;
00183 }
00184
00185
00186 void SearchSat::addSplitter(const Expr& e, int priority)
00187 {
00188 DebugAssert(!e.isEq() || e[0] != e[1], "Expected non-trivial splitter");
00189 addLemma(d_commonRules->excludedMiddle(e), priority);
00190 }
00191
00192
00193 void SearchSat::assertLit(Lit l)
00194 {
00195
00196 Expr e = d_cnfManager->concreteLit(l);
00197
00198 IF_DEBUG(
00199 string indentStr(theoryCore()->getCM()->scopeLevel(), ' ');
00200 string val = " := ";
00201
00202 std::stringstream ss;
00203 ss<<theoryCore()->getCM()->scopeLevel();
00204 std::string temp;
00205 ss>>temp;
00206
00207 if (l.isPositive()) val += "1"; else val += "0";
00208 TRACE("assertLit", "", "", "");
00209 TRACE("assertLitScope", indentStr, "Scope level = ", temp);
00210 TRACE("assertLit", indentStr, l.getVar(), val+": "+e.toString());
00211 )
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 bool isSATLemma = false;
00223 if (e.isNull()) {
00224 e = d_cnfManager->concreteLit(l, false);
00225 DebugAssert(!e.isNull(), "Expected known expr");
00226 isSATLemma = true;
00227 TRACE("quant-level", "found null expr ",e, "");
00228 }
00229
00230 DebugAssert(!e.isNull(), "Expected known expr");
00231 DebugAssert(!e.isIntAssumption() || getValue(l) == SAT::Var::TRUE_VAL,
00232 "internal assumptions should be true");
00233
00234 if (e.isIntAssumption()) return;
00235 if (getValue(l) == SAT::Var::UNKNOWN) {
00236 setValue(l.getVar(), l.isPositive() ? Var::TRUE_VAL : Var::FALSE_VAL);
00237 }
00238 else {
00239 DebugAssert(!e.isAbsLiteral(), "invariant violated");
00240 DebugAssert(getValue(l) == Var::TRUE_VAL, "invariant violated");
00241 return;
00242 }
00243 if (!e.isAbsLiteral()) return;
00244 e.setIntAssumption();
00245
00246 Theorem thm = d_commonRules->assumpRule(e);
00247 if (isSATLemma) {
00248 CNF_Formula_Impl cnf;
00249 d_cnfManager->addAssumption(thm, cnf);
00250 }
00251
00252 thm.setQuantLevel(theoryCore()->getQuantLevelForTerm(e.isNot() ? e[0] : e));
00253 d_intAssumptions.push_back(thm);
00254 d_core->addFact(thm);
00255 }
00256
00257
00258 SAT::DPLLT::ConsistentResult SearchSat::checkConsistent(SAT::CNF_Formula& cnf, bool fullEffort)
00259 {
00260 DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00261 if (d_core->inconsistent()) {
00262 d_cnfManager->convertLemma(d_core->inconsistentThm(), cnf);
00263 if (d_cnfManager->numVars() > d_vars.size()) {
00264 d_vars.resize(d_cnfManager->numVars(), SAT::Var::UNKNOWN);
00265 }
00266 return DPLLT::INCONSISTENT;
00267 }
00268 if (fullEffort) {
00269 if (d_core->checkSATCore() && d_pendingLemmasNext == d_pendingLemmas.size() && d_lemmasNext == d_lemmas.numClauses()) {
00270 if (d_core->inconsistent()) {
00271 d_cnfManager->convertLemma(d_core->inconsistentThm(), cnf);
00272 if (d_cnfManager->numVars() > d_vars.size()) {
00273 d_vars.resize(d_cnfManager->numVars(), SAT::Var::UNKNOWN);
00274 }
00275 return DPLLT::INCONSISTENT;
00276 }
00277 else return DPLLT::CONSISTENT;
00278 }
00279 }
00280 return DPLLT::MAYBE_CONSISTENT;
00281 }
00282
00283
00284 Lit SearchSat::getImplication()
00285 {
00286
00287 Lit l;
00288 Theorem imp = d_core->getImpliedLiteral();
00289 while (!imp.isNull()) {
00290 l = d_cnfManager->getCNFLit(imp.getExpr());
00291 DebugAssert(!l.isNull() || imp.getExpr().unnegate().isUserRegisteredAtom(),
00292 "implied literals should be registered by cnf or by user");
00293 if (!l.isNull() && getValue(l) != Var::TRUE_VAL) {
00294 d_theorems.insert(imp.getExpr(), imp);
00295 break;
00296 }
00297 l.reset();
00298 imp = d_core->getImpliedLiteral();
00299 }
00300 return l;
00301 }
00302
00303
00304 void SearchSat::getExplanation(Lit l, SAT::CNF_Formula& cnf)
00305 {
00306
00307 DebugAssert(cnf.empty(), "Expected empty cnf");
00308 Expr e = d_cnfManager->concreteLit(l);
00309 CDMap<Expr, Theorem>::iterator i = d_theorems.find(e);
00310 DebugAssert(i != d_theorems.end(), "getExplanation: no explanation found");
00311 d_cnfManager->convertLemma((*i).second, cnf);
00312 if (d_cnfManager->numVars() > d_vars.size()) {
00313 d_vars.resize(d_cnfManager->numVars(), SAT::Var::UNKNOWN);
00314 }
00315 }
00316
00317
00318 bool SearchSat::getNewClauses(CNF_Formula& cnf)
00319 {
00320 unsigned i;
00321
00322 Lit l;
00323 for (i = d_pendingLemmasNext; i < d_pendingLemmas.size(); ++i) {
00324 l = d_cnfManager->addLemma(d_pendingLemmas[i].first, d_lemmas);
00325 if (!recordNewRootLit(l, d_pendingLemmas[i].second, d_pendingScopes[i])) {
00326
00327 d_lemmas.deleteLast();
00328 }
00329 }
00330 d_pendingLemmasNext = d_pendingLemmas.size();
00331
00332 if (d_cnfManager->numVars() > d_vars.size()) {
00333 d_vars.resize(d_cnfManager->numVars(), SAT::Var::UNKNOWN);
00334 }
00335
00336 DebugAssert(d_lemmasNext <= d_lemmas.numClauses(), "");
00337 if (d_lemmasNext == d_lemmas.numClauses()) return false;
00338 do {
00339 cnf += d_lemmas[d_lemmasNext];
00340 d_lemmasNext = d_lemmasNext + 1;
00341 } while (d_lemmasNext < d_lemmas.numClauses());
00342 return true;
00343 }
00344
00345
00346 Lit SearchSat::makeDecision()
00347 {
00348 DebugAssert(d_inCheckSat, "Should only be used as a call-back");
00349 Lit litDecision;
00350
00351 set<LitPriorityPair>::const_iterator i, iend;
00352 Lit lit;
00353 for (i = d_prioritySetStart, iend = d_prioritySet.end(); i != iend; ++i) {
00354 lit = (*i).getLit();
00355 if (findSplitterRec(lit, getValue(lit), &litDecision)) {
00356 break;
00357 }
00358 }
00359 d_prioritySetStart = i;
00360 return litDecision;
00361 }
00362
00363
00364 bool SearchSat::findSplitterRec(Lit lit, Var::Val value, Lit* litDecision)
00365 {
00366 if (lit.isFalse() || lit.isTrue()) return false;
00367
00368 unsigned i, n;
00369 Lit litTmp;
00370 Var varTmp;
00371 bool ret;
00372 Var v = lit.getVar();
00373
00374 DebugAssert(value != Var::UNKNOWN, "expected known value");
00375 DebugAssert(getValue(lit) == value || getValue(lit) == Var::UNKNOWN,
00376 "invariant violated");
00377
00378 if (checkJustified(v)) return false;
00379
00380 if (lit.isInverted()) {
00381 value = Var::invertValue(value);
00382 }
00383
00384 if (d_cnfManager->numFanins(v) == 0) {
00385 if (getValue(v) != Var::UNKNOWN) {
00386 setJustified(v);
00387 return false;
00388 }
00389 else {
00390 *litDecision = Lit(v, value == Var::TRUE_VAL);
00391 return true;
00392 }
00393 }
00394 else if (d_cnfManager->concreteVar(v).isAbsAtomicFormula()) {
00395
00396
00397
00398 n = d_cnfManager->numFanins(v);
00399 for (i=0; i < n; ++i) {
00400 litTmp = d_cnfManager->getFanin(v, i);
00401 varTmp = litTmp.getVar();
00402 DebugAssert(!litTmp.isInverted(),"Expected positive fanin");
00403 if (checkJustified(varTmp)) continue;
00404 DebugAssert(d_cnfManager->concreteVar(varTmp).getKind() == ITE,
00405 "Expected ITE");
00406 DebugAssert(getValue(varTmp) == Var::TRUE_VAL,"Expected TRUE");
00407 Lit cIf = d_cnfManager->getFanin(varTmp,0);
00408 Lit cThen = d_cnfManager->getFanin(varTmp,1);
00409 Lit cElse = d_cnfManager->getFanin(varTmp,2);
00410 if (getValue(cIf) == Var::UNKNOWN) {
00411 if (getValue(cElse) == Var::TRUE_VAL ||
00412 getValue(cThen) == Var::FALSE_VAL) {
00413 ret = findSplitterRec(cIf, Var::FALSE_VAL, litDecision);
00414 }
00415 else {
00416 ret = findSplitterRec(cIf, Var::TRUE_VAL, litDecision);
00417 }
00418 if (!ret) {
00419 cout << d_cnfManager->concreteVar(cIf.getVar()) << endl;
00420 DebugAssert(false,"No controlling input found (1)");
00421 }
00422 return true;
00423 }
00424 else if (getValue(cIf) == Var::TRUE_VAL) {
00425 if (findSplitterRec(cIf, Var::TRUE_VAL, litDecision)) {
00426 return true;
00427 }
00428 if (cThen.getVar() != v &&
00429 (getValue(cThen) == Var::UNKNOWN ||
00430 getValue(cThen) == Var::TRUE_VAL) &&
00431 findSplitterRec(cThen, Var::TRUE_VAL, litDecision)) {
00432 return true;
00433 }
00434 }
00435 else {
00436 if (findSplitterRec(cIf, Var::FALSE_VAL, litDecision)) {
00437 return true;
00438 }
00439 if (cElse.getVar() != v &&
00440 (getValue(cElse) == Var::UNKNOWN ||
00441 getValue(cElse) == Var::TRUE_VAL) &&
00442 findSplitterRec(cElse, Var::TRUE_VAL, litDecision)) {
00443 return true;
00444 }
00445 }
00446 setJustified(varTmp);
00447 }
00448 if (getValue(v) != Var::UNKNOWN) {
00449 setJustified(v);
00450 return false;
00451 }
00452 else {
00453 *litDecision = Lit(v, value == Var::TRUE_VAL);
00454 return true;
00455 }
00456 }
00457
00458 int kind = d_cnfManager->concreteVar(v).getKind();
00459 Var::Val valHard = Var::FALSE_VAL;
00460 switch (kind) {
00461 case AND:
00462 valHard = Var::TRUE_VAL;
00463 case OR:
00464 if (value == valHard) {
00465 n = d_cnfManager->numFanins(v);
00466 for (i=0; i < n; ++i) {
00467 litTmp = d_cnfManager->getFanin(v, i);
00468 if (findSplitterRec(litTmp, valHard, litDecision)) {
00469 return true;
00470 }
00471 }
00472 DebugAssert(getValue(v) == valHard, "Output should be justified");
00473 setJustified(v);
00474 return false;
00475 }
00476 else {
00477 Var::Val valEasy = Var::invertValue(valHard);
00478 n = d_cnfManager->numFanins(v);
00479 for (i=0; i < n; ++i) {
00480 litTmp = d_cnfManager->getFanin(v, i);
00481 if (getValue(litTmp) != valHard) {
00482 if (findSplitterRec(litTmp, valEasy, litDecision)) {
00483 return true;
00484 }
00485 DebugAssert(getValue(v) == valEasy, "Output should be justified");
00486 setJustified(v);
00487 return false;
00488 }
00489 }
00490 DebugAssert(false, "No controlling input found (2)");
00491 }
00492 break;
00493 case IMPLIES:
00494 DebugAssert(d_cnfManager->numFanins(v) == 2, "Expected 2 fanins");
00495 if (value == Var::FALSE_VAL) {
00496 litTmp = d_cnfManager->getFanin(v, 0);
00497 if (findSplitterRec(litTmp, Var::TRUE_VAL, litDecision)) {
00498 return true;
00499 }
00500 litTmp = d_cnfManager->getFanin(v, 1);
00501 if (findSplitterRec(litTmp, Var::FALSE_VAL, litDecision)) {
00502 return true;
00503 }
00504 DebugAssert(getValue(v) == Var::FALSE_VAL, "Output should be justified");
00505 setJustified(v);
00506 return false;
00507 }
00508 else {
00509 litTmp = d_cnfManager->getFanin(v, 0);
00510 if (getValue(litTmp) != Var::TRUE_VAL) {
00511 if (findSplitterRec(litTmp, Var::FALSE_VAL, litDecision)) {
00512 return true;
00513 }
00514 DebugAssert(getValue(v) == Var::TRUE_VAL, "Output should be justified");
00515 setJustified(v);
00516 return false;
00517 }
00518 litTmp = d_cnfManager->getFanin(v, 1);
00519 if (getValue(litTmp) != Var::FALSE_VAL) {
00520 if (findSplitterRec(litTmp, Var::TRUE_VAL, litDecision)) {
00521 return true;
00522 }
00523 DebugAssert(getValue(v) == Var::TRUE_VAL, "Output should be justified");
00524 setJustified(v);
00525 return false;
00526 }
00527 DebugAssert(false, "No controlling input found (3)");
00528 }
00529 break;
00530 case IFF: {
00531 litTmp = d_cnfManager->getFanin(v, 0);
00532 Var::Val val = getValue(litTmp);
00533 if (val != Var::UNKNOWN) {
00534 if (findSplitterRec(litTmp, val, litDecision)) {
00535 return true;
00536 }
00537 if (value == Var::FALSE_VAL) val = Var::invertValue(val);
00538 litTmp = d_cnfManager->getFanin(v, 1);
00539
00540 if (findSplitterRec(litTmp, val, litDecision)) {
00541 return true;
00542 }
00543 DebugAssert(getValue(v) == value, "Output should be justified");
00544 setJustified(v);
00545 return false;
00546 }
00547 else {
00548 val = getValue(d_cnfManager->getFanin(v, 1));
00549 if (val == Var::UNKNOWN) val = Var::FALSE_VAL;
00550 if (value == Var::FALSE_VAL) val = Var::invertValue(val);
00551 if (findSplitterRec(litTmp, val, litDecision)) {
00552 return true;
00553 }
00554 DebugAssert(false, "Unable to find controlling input (4)");
00555 }
00556 break;
00557 }
00558 case XOR: {
00559 litTmp = d_cnfManager->getFanin(v, 0);
00560 Var::Val val = getValue(litTmp);
00561 if (val != Var::UNKNOWN) {
00562 if (findSplitterRec(litTmp, val, litDecision)) {
00563 return true;
00564 }
00565 if (value == Var::TRUE_VAL) val = Var::invertValue(val);
00566 litTmp = d_cnfManager->getFanin(v, 1);
00567 if (findSplitterRec(litTmp, val, litDecision)) {
00568 return true;
00569 }
00570 DebugAssert(getValue(v) == value, "Output should be justified");
00571 setJustified(v);
00572 return false;
00573 }
00574 else {
00575 val = getValue(d_cnfManager->getFanin(v, 1));
00576 if (val == Var::UNKNOWN) val = Var::FALSE_VAL;
00577 if (value == Var::TRUE_VAL) val = Var::invertValue(val);
00578 if (findSplitterRec(litTmp, val, litDecision)) {
00579 return true;
00580 }
00581 DebugAssert(false, "Unable to find controlling input (5)");
00582 }
00583 break;
00584 }
00585 case ITE: {
00586 Lit cIf = d_cnfManager->getFanin(v, 0);
00587 Lit cThen = d_cnfManager->getFanin(v, 1);
00588 Lit cElse = d_cnfManager->getFanin(v, 2);
00589 if (getValue(cIf) == Var::UNKNOWN) {
00590 if (getValue(cElse) == value ||
00591 getValue(cThen) == Var::invertValue(value)) {
00592 ret = findSplitterRec(cIf, Var::FALSE_VAL, litDecision);
00593 }
00594 else {
00595 ret = findSplitterRec(cIf, Var::TRUE_VAL, litDecision);
00596 }
00597 if (!ret) {
00598 cout << d_cnfManager->concreteVar(cIf.getVar()) << endl;
00599 DebugAssert(false,"No controlling input found (6)");
00600 }
00601 return true;
00602 }
00603 else if (getValue(cIf) == Var::TRUE_VAL) {
00604 if (findSplitterRec(cIf, Var::TRUE_VAL, litDecision)) {
00605 return true;
00606 }
00607 if (cThen.isVar() && cThen.getVar() != v &&
00608 (getValue(cThen) == Var::UNKNOWN ||
00609 getValue(cThen) == value) &&
00610 findSplitterRec(cThen, value, litDecision)) {
00611 return true;
00612 }
00613 }
00614 else {
00615 if (findSplitterRec(cIf, Var::FALSE_VAL, litDecision)) {
00616 return true;
00617 }
00618 if (cElse.isVar() && cElse.getVar() != v &&
00619 (getValue(cElse) == Var::UNKNOWN ||
00620 getValue(cElse) == value) &&
00621 findSplitterRec(cElse, value, litDecision)) {
00622 return true;
00623 }
00624 }
00625 DebugAssert(getValue(v) == value, "Output should be justified");
00626 setJustified(v);
00627 return false;
00628 }
00629 default:
00630 DebugAssert(false, "Unexpected Boolean operator");
00631 break;
00632 }
00633 FatalAssert(false, "Should be unreachable");
00634 return false;
00635 }
00636
00637
00638 QueryResult SearchSat::check(const Expr& e, Theorem& result, bool isRestart)
00639 {
00640 DebugAssert(d_dplltReady, "SAT solver is not ready");
00641 if (isRestart && d_lastCheck.get().isNull()) {
00642 throw Exception
00643 ("restart called without former call to checkValid");
00644 }
00645
00646 DebugAssert(!d_inCheckSat, "checkValid should not be called recursively");
00647 TRACE("searchsat", "checkValid: ", e, "");
00648
00649 if (!e.getType().isBool())
00650 throw TypecheckException
00651 ("checking validity of a non-Boolean expression:\n\n "
00652 + e.toString()
00653 + "\n\nwhich has the following type:\n\n "
00654 + e.getType().toString());
00655
00656 Expr e2 = e;
00657
00658
00659 if (isRestart) {
00660 while (e2.isNot() && e2[0].isNot()) e2 = e2[0][0];
00661 if (e2.isTrue() || (e2.isNot() && e2[0].isFalse())) {
00662 result = d_lastValid;
00663 return INVALID;
00664 }
00665 if (e2.isFalse() || (e2.isNot() && e2[0].isTrue())) {
00666 pop();
00667
00668 d_lastValid = d_commonRules->assumpRule(d_lastCheck);
00669 result = d_lastValid;
00670 return VALID;
00671 }
00672 }
00673 else {
00674 if (e.isTrue()) {
00675 d_lastValid = d_commonRules->trueTheorem();
00676 result = d_lastValid;
00677 return VALID;
00678 }
00679 push();
00680 d_bottomScope = d_core->getCM()->scopeLevel();
00681 d_prioritySetBottomEntriesSizeStack.push_back(d_prioritySetBottomEntriesSize);
00682 d_lastCheck = e;
00683 e2 = !e;
00684 }
00685
00686 Theorem thm;
00687 CNF_Formula_Impl cnf;
00688 QueryResult qres;
00689 d_cnfManager->setBottomScope(d_bottomScope);
00690 d_dplltReady = false;
00691
00692 newUserAssumptionInt(e2, cnf, true);
00693
00694 d_inCheckSat = true;
00695
00696 getNewClauses(cnf);
00697
00698 if (!isRestart && d_core->inconsistent()) {
00699 qres = UNSATISFIABLE;
00700 thm = d_rules->proofByContradiction(e, d_core->inconsistentThm());
00701 pop();
00702 d_lastValid = thm;
00703 d_cnfManager->setBottomScope(-1);
00704 d_inCheckSat = false;
00705 result = d_lastValid;
00706 return qres;
00707 }
00708 else {
00709
00710 qres = isRestart ? d_dpllt->continueCheck(cnf) : d_dpllt->checkSat(cnf);
00711 }
00712
00713 if (qres == UNSATISFIABLE) {
00714 DebugAssert(d_core->getCM()->scopeLevel() == d_bottomScope,
00715 "Expected unchanged context after unsat");
00716 e2 = d_lastCheck;
00717 pop();
00718 if (d_core->getTM()->withProof()) {
00719 Proof pf = d_dpllt->getSatProof(d_cnfManager, d_core);
00720 d_lastValid = d_rules->satProof(e2, pf);
00721 }
00722 else {
00723 d_lastValid = d_commonRules->assumpRule(d_lastCheck);
00724 }
00725 }
00726 else {
00727 DebugAssert(d_lemmasNext == d_lemmas.numClauses(),
00728 "Expected no lemmas after satisfiable check");
00729 d_dplltReady = true;
00730 d_lastValid = Theorem();
00731 if (qres == SATISFIABLE && d_core->incomplete()) qres = UNKNOWN;
00732
00733 #ifdef _CVC3_DEBUG_MODE
00734
00735 if( CVC3::debugger.trace("quant debug") ){
00736 d_core->theoryOf(FORALL)->debug(1);
00737 }
00738
00739
00740 if( CVC3::debugger.trace("sat model unknown") ){
00741 std::vector<SAT::Lit> cur_assigns = d_dpllt->getCurAssignments();
00742 cout<<"Current assignments"<<endl;
00743 {
00744 for(size_t i = 0 ; i < cur_assigns.size(); i++){
00745 Lit l = cur_assigns[i];
00746 Expr e = d_cnfManager->concreteLit(l);
00747
00748 string val = " := ";
00749
00750 if (l.isPositive()) val += "1"; else val += "0";
00751 cout<<l.getVar()<<val<<endl;
00752
00753
00754 }
00755 }
00756
00757
00758 std::vector< std::vector<SAT::Lit> > cur_clauses = d_dpllt->getCurClauses();
00759 cout<<"Current Clauses"<<endl;
00760 {
00761 for(size_t i = 0 ; i < cur_clauses.size(); i++){
00762
00763 for(size_t j = 0; j < cur_clauses[i].size(); j++){
00764
00765 Lit l = cur_clauses[i][j];
00766 string val ;
00767 if (l.isPositive()) val += "+"; else val += "-";
00768 cout<<val<<l.getVar()<<" ";
00769 }
00770 cout<<endl;
00771 }
00772 }
00773 }
00774
00775 if( CVC3::debugger.trace("model unknown") ){
00776 const CDList<Expr>& allterms = d_core->getTerms();
00777 cout<<"===========terms begin=========="<<endl;
00778
00779 for (size_t i=0; i<allterms.size(); i++){
00780
00781 cout<<"i="<<i<<" :"<<allterms[i].getFindLevel()<<":"<<d_core->simplifyExpr(allterms[i])<<"|"<<allterms[i]<<endl;
00782
00783
00784
00785 }
00786 cout<<"-----------term end ---------"<<endl;
00787 const CDList<Expr>& allpreds = d_core->getPredicates();
00788 cout<<"===========pred begin=========="<<endl;
00789
00790 for (size_t i=0; i<allpreds.size(); i++){
00791 if(allpreds[i].hasFind()){
00792 if( (d_core->findExpr(allpreds[i])).isTrue()){
00793 cout<<"ASSERT "<< allpreds[i] <<";" <<endl;
00794 }
00795 else{
00796 cout<<"ASSERT NOT("<< allpreds[i] <<");" <<endl;
00797 }
00798
00799
00800
00801 }
00802
00803
00804
00805
00806
00807 }
00808 cout<<"-----------end----------pred"<<endl;
00809 }
00810
00811 if( CVC3::debugger.trace("model unknown quant") ){
00812 cout<<"=========== quant pred begin=========="<<endl;
00813 const CDList<Expr>& allpreds = d_core->getPredicates();
00814 for (size_t i=0; i<allpreds.size(); i++){
00815
00816 Expr cur = allpreds[i];
00817 if(cur.isForall() || cur.isExists() || (cur.isNot() && (cur[0].isForall()||cur[0].isExists()))){
00818 if(allpreds[i].hasFind()) {
00819 cout<<"i="<<i<<" :";
00820 cout<<allpreds[i].getFindLevel();
00821 cout<<":"<<d_core->findExpr(allpreds[i])<<"|"<<allpreds[i]<<endl;
00822 }
00823 }
00824 }
00825 cout<<"-----------end----------pred"<<endl;
00826 }
00827
00828 if( CVC3::debugger.trace("model unknown nonquant") ){
00829 cout<<"=========== quant pred begin=========="<<endl;
00830 const CDList<Expr>& allpreds = d_core->getPredicates();
00831 for (size_t i=0; i<allpreds.size(); i++){
00832
00833 Expr cur = allpreds[i];
00834 if(cur.isForall() || cur.isExists() ||
00835 (cur.isNot() && (cur[0].isForall()||cur[0].isExists())) ||
00836 cur.isEq() ||
00837 (cur.isNot() && cur[0].isEq())){
00838 }
00839 else{
00840 if(allpreds[i].hasFind()) {
00841 cout<<"i="<<i<<" :";
00842 cout<<allpreds[i].getFindLevel();
00843 cout<<":"<<d_core->findExpr(allpreds[i])<<"|"<<allpreds[i]<<endl;
00844 }
00845 }
00846 }
00847 cout<<"-----------end----------pred"<<endl;
00848 }
00849
00850 if( CVC3::debugger.trace("unknown state") ){
00851 const CDList<Expr>& allpreds = d_core->getPredicates();
00852 cout<<"===========pred begin=========="<<endl;
00853
00854 for (size_t i=0; i<allpreds.size(); i++){
00855 if(allpreds[i].hasFind()){
00856
00857
00858
00859
00860
00861
00862
00863 if( (d_core->findExpr(allpreds[i])).isTrue()){
00864 cout<<":assumption "<< allpreds[i] <<"" <<endl;
00865 }
00866 else{
00867 cout<<":assumption(not "<< allpreds[i] <<")" <<endl;
00868 }
00869
00870
00871
00872 }
00873
00874
00875
00876
00877
00878 }
00879 cout<<"-----------end----------pred"<<endl;
00880 }
00881
00882 if( CVC3::debugger.trace("unknown state noforall") ){
00883 const CDList<Expr>& allpreds = d_core->getPredicates();
00884 cout<<"===========pred begin=========="<<endl;
00885
00886 for (size_t i=0; i<allpreds.size(); i++){
00887 if(allpreds[i].hasFind()){
00888 Expr cur(allpreds[i]);
00889
00890
00891
00892
00893
00894
00895 if( (d_core->findExpr(allpreds[i])).isTrue()){
00896
00897
00898
00899 cout<<"ASSERT "<< allpreds[i] <<";" <<endl;
00900
00901 }
00902 else if ( (d_core->findExpr(allpreds[i])).isFalse()){
00903
00904
00905
00906 cout<<"ASSERT (NOT "<< allpreds[i] <<");" <<endl;
00907
00908 }
00909 else{
00910 cout<<"--ERROR"<<endl;
00911 }
00912
00913
00914
00915 }
00916
00917
00918
00919
00920
00921 }
00922 cout<<"-----------end----------pred"<<endl;
00923 }
00924
00925
00926 #endif
00927 }
00928 d_cnfManager->setBottomScope(-1);
00929 d_inCheckSat = false;
00930 result = d_lastValid;
00931 return qres;
00932 }
00933
00934
00935 SearchSat::SearchSat(TheoryCore* core, const string& name)
00936 : SearchEngine(core),
00937 d_name(name),
00938 d_bottomScope(core->getCM()->getCurrentContext(), -1),
00939 d_lastCheck(core->getCM()->getCurrentContext()),
00940 d_lastValid(core->getCM()->getCurrentContext(),
00941 d_commonRules->trueTheorem()),
00942 d_userAssumptions(core->getCM()->getCurrentContext()),
00943 d_intAssumptions(core->getCM()->getCurrentContext()),
00944 d_idxUserAssump(core->getCM()->getCurrentContext(), 0),
00945 d_decider(NULL),
00946 d_theorems(core->getCM()->getCurrentContext()),
00947 d_inCheckSat(false),
00948 d_lemmas(core->getCM()->getCurrentContext()),
00949 d_pendingLemmasSize(core->getCM()->getCurrentContext(), 0),
00950 d_pendingLemmasNext(core->getCM()->getCurrentContext(), 0),
00951 d_lemmasNext(core->getCM()->getCurrentContext(), 0),
00952 d_varsUndoListSize(core->getCM()->getCurrentContext(), 0),
00953 d_prioritySetStart(core->getCM()->getCurrentContext()),
00954 d_prioritySetEntriesSize(core->getCM()->getCurrentContext(), 0),
00955 d_prioritySetBottomEntriesSize(0),
00956 d_lastRegisteredVar(core->getCM()->getCurrentContext(), 0),
00957 d_dplltReady(core->getCM()->getCurrentContext(), true),
00958 d_nextImpliedLiteral(core->getCM()->getCurrentContext(), 0),
00959 d_restorer(core->getCM()->getCurrentContext(), this)
00960 {
00961 d_cnfManager = new CNF_Manager(core->getTM(), core->getStatistics(),
00962 core->getFlags());
00963
00964 d_cnfCallback = new SearchSatCNFCallback(this);
00965 d_cnfManager->registerCNFCallback(d_cnfCallback);
00966 d_coreSatAPI = new SearchSatCoreSatAPI(this);
00967 core->registerCoreSatAPI(d_coreSatAPI);
00968 d_theoryAPI = new SearchSatTheoryAPI(this);
00969 if (core->getFlags()["de"].getString() == "dfs") d_decider = new SearchSatDecider(this);
00970
00971 if (core->getFlags()["sat"].getString() == "sat") {
00972 #ifdef DPLL_BASIC
00973 d_dpllt = new DPLLTBasic(d_theoryAPI, d_decider, core->getCM(),
00974 core->getFlags()["stats"].getBool());
00975 #else
00976 throw CLException("SAT solver 'sat' not supported in this build");
00977 #endif
00978 } else if (core->getFlags()["sat"].getString() == "minisat") {
00979 d_dpllt = new DPLLTMiniSat(d_theoryAPI, d_decider,
00980 core->getFlags()["stats"].getBool(),
00981 core->getTM()->withProof());
00982 } else {
00983 throw CLException("Unrecognized SAT solver name: " + (core->getFlags()["sat"].getString()));
00984 }
00985
00986 d_prioritySetStart = d_prioritySet.end();
00987 }
00988
00989
00990 SearchSat::~SearchSat()
00991 {
00992 delete d_dpllt;
00993 delete d_decider;
00994 delete d_theoryAPI;
00995 delete d_coreSatAPI;
00996 delete d_cnfCallback;
00997 delete d_cnfManager;
00998 }
00999
01000
01001 void SearchSat::registerAtom(const Expr& e)
01002 {
01003 e.setUserRegisteredAtom();
01004 if (!e.isRegisteredAtom())
01005 d_core->registerAtom(e, Theorem());
01006 }
01007
01008
01009 Theorem SearchSat::getImpliedLiteral(void)
01010 {
01011 Theorem imp;
01012 while (d_nextImpliedLiteral < d_core->numImpliedLiterals()) {
01013 imp = d_core->getImpliedLiteralByIndex(d_nextImpliedLiteral);
01014 d_nextImpliedLiteral = d_nextImpliedLiteral + 1;
01015 if (imp.getExpr().unnegate().isUserRegisteredAtom()) return imp;
01016 }
01017 return Theorem();
01018 }
01019
01020
01021 void SearchSat::returnFromCheck()
01022 {
01023 if (d_bottomScope < 0) {
01024 throw Exception
01025 ("returnFromCheck called with no previous invalid call to checkValid");
01026 }
01027 pop();
01028 }
01029
01030
01031 static void setRecursiveInUserAssumption(const Expr& e, int scope)
01032 {
01033 if (e.inUserAssumption()) return;
01034 for (int i = 0; i < e.arity(); ++i) {
01035 setRecursiveInUserAssumption(e[i], scope);
01036 }
01037 e.setInUserAssumption(scope);
01038 }
01039
01040
01041 void SearchSat::newUserAssumptionIntHelper(const Theorem& thm, CNF_Formula_Impl& cnf, bool atBottomScope)
01042 {
01043 Expr e = thm.getExpr();
01044 if (e.isAnd()) {
01045 for (int i = 0; i < e.arity(); ++i) {
01046 newUserAssumptionIntHelper(d_commonRules->andElim(thm, i), cnf, atBottomScope);
01047 }
01048 }
01049 else {
01050 if ( ! d_core->getFlags()["cnf-formula"].getBool()) {
01051 if (!recordNewRootLit(d_cnfManager->addAssumption(thm, cnf), 0, atBottomScope)) {
01052 cnf.deleteLast();
01053 }
01054 }
01055 else{
01056 d_cnfManager->addAssumption(thm, cnf);
01057 }
01058
01059 }
01060 }
01061
01062
01063 Theorem SearchSat::newUserAssumptionInt(const Expr& e, CNF_Formula_Impl& cnf, bool atBottomScope)
01064 {
01065 DebugAssert(!d_inCheckSat,
01066 "User assumptions should be added before calling checkSat");
01067 Theorem thm;
01068 int scope;
01069 if (atBottomScope) scope = d_bottomScope;
01070 else scope = -1;
01071 setRecursiveInUserAssumption(e, scope);
01072 if (!isAssumption(e)) {
01073 e.setUserAssumption(scope);
01074 thm = d_commonRules->assumpRule(e, scope);
01075 d_userAssumptions.push_back(thm, scope);
01076
01077 if (atBottomScope && d_bottomScope != d_core->getCM()->scopeLevel()) {
01078
01079
01080 newUserAssumptionIntHelper(thm, cnf, true);
01081 }
01082 else {
01083 Theorem thm2 = d_core->getExprTrans()->preprocess(thm);
01084 Expr e2 = thm2.getExpr();
01085 if (e2.isFalse()) {
01086 d_core->addFact(thm2);
01087 return thm;
01088 }
01089 else if (!e2.isTrue()) {
01090 newUserAssumptionIntHelper(thm2, cnf, false);
01091 }
01092 }
01093 if (d_cnfManager->numVars() > d_vars.size()) {
01094 d_vars.resize(d_cnfManager->numVars(), SAT::Var::UNKNOWN);
01095 }
01096 }
01097 return thm;
01098 }
01099
01100
01101 Theorem SearchSat::newUserAssumption(const Expr& e)
01102 {
01103 CNF_Formula_Impl cnf;
01104 Theorem thm = newUserAssumptionInt(e, cnf, false);
01105 d_dpllt->addAssertion(cnf);
01106 return thm;
01107 }
01108
01109
01110 void SearchSat::getUserAssumptions(vector<Expr>& assumptions)
01111 {
01112 for(CDList<Theorem>::const_iterator i=d_userAssumptions.begin(),
01113 iend=d_userAssumptions.end(); i!=iend; ++i)
01114 assumptions.push_back((*i).getExpr());
01115 }
01116
01117
01118 void SearchSat::getInternalAssumptions(vector<Expr>& assumptions)
01119 {
01120 for(CDList<Theorem>::const_iterator i=d_intAssumptions.begin(),
01121 iend=d_intAssumptions.end(); i!=iend; ++i)
01122 assumptions.push_back((*i).getExpr());
01123 }
01124
01125
01126
01127 void SearchSat::getAssumptions(vector<Expr>& assumptions)
01128 {
01129 CDList<Theorem>::const_iterator iU=d_userAssumptions.begin(),
01130 iUend=d_userAssumptions.end(), iI = d_intAssumptions.begin(),
01131 iIend=d_intAssumptions.end();
01132 while (true) {
01133 if (iI == iIend) {
01134 if (iU == iUend) break;
01135 assumptions.push_back((*iU).getExpr());
01136 ++iU;
01137 }
01138 else if (iU == iUend) {
01139 Expr intAssump = (*iI).getExpr();
01140 if (!intAssump.isUserAssumption()) {
01141 assumptions.push_back(intAssump);
01142 }
01143 ++iI;
01144 }
01145 else {
01146 if ((*iI).getScope() <= (*iU).getScope()) {
01147 Expr intAssump = (*iI).getExpr();
01148 if (!intAssump.isUserAssumption()) {
01149 assumptions.push_back(intAssump);
01150 }
01151 ++iI;
01152 }
01153 else {
01154 assumptions.push_back((*iU).getExpr());
01155 ++iU;
01156 }
01157 }
01158 }
01159 }
01160
01161
01162 bool SearchSat::isAssumption(const Expr& e)
01163 {
01164 return e.isUserAssumption() || e.isIntAssumption();
01165 }
01166
01167
01168 void SearchSat::getCounterExample(vector<Expr>& assumptions, bool inOrder)
01169 {
01170 if (!d_lastValid.get().isNull()) {
01171 throw Exception("Expected last query to be invalid");
01172 }
01173 getInternalAssumptions(assumptions);
01174 }
01175
01176
01177 Proof SearchSat::getProof()
01178 {
01179 if(!d_core->getTM()->withProof())
01180 throw EvalException
01181 ("getProof cannot be called without proofs activated");
01182 if(d_lastValid.get().isNull())
01183 throw EvalException
01184 ("getProof must be called only after a successful check");
01185 if(d_lastValid.get().isNull()) return Proof();
01186 else return d_lastValid.get().getProof();
01187 }