00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "search_fast.h"
00031 #include "typecheck_exception.h"
00032 #include "search_rules.h"
00033 #include "command_line_flags.h"
00034 #include "cdmap.h"
00035 #include "decision_engine_dfs.h"
00036 #include "decision_engine_caching.h"
00037 #include "decision_engine_mbtf.h"
00038 #include "expr_transform.h"
00039
00040
00041 using namespace CVCL;
00042 using namespace std;
00043
00044
00045
00046 #define followChaff false
00047
00048
00049 void SearchEngineFast::ConflictClauseManager::setRestorePoint()
00050 {
00051 TRACE("conflict clauses",
00052 "ConflictClauseManager::setRestorePoint(): scope=",
00053 d_se->scopeLevel(), "");
00054 d_se->d_conflictClauseStack.push_back(new deque<ClauseOwner>());
00055 d_se->d_conflictClauses = d_se->d_conflictClauseStack.back();
00056 d_restorePoints.push_back(d_se->scopeLevel());
00057 }
00058
00059
00060 void SearchEngineFast::ConflictClauseManager::notify()
00061 {
00062 if (d_restorePoints.size() > 0) {
00063 int scope = d_restorePoints.back();
00064 if (scope > d_se->scopeLevel()) {
00065 TRACE("conflict clauses",
00066 "ConflictClauseManager::notify(): restore to scope ", scope, "");
00067 d_restorePoints.pop_back();
00068 while (d_se->d_conflictClauses->size() > 0)
00069 d_se->d_conflictClauses->pop_back();
00070 delete d_se->d_conflictClauseStack.back();
00071 d_se->d_conflictClauseStack.pop_back();
00072 d_se->d_conflictClauses = d_se->d_conflictClauseStack.back();
00073 }
00074 }
00075 }
00076
00077
00078
00079 SearchEngineFast::SearchEngineFast(TheoryCore* core)
00080 : SearchImplBase(core),
00081 d_name("fast"),
00082 d_unitPropCount(core->getStatistics().counter("unit propagations")),
00083 d_circuitPropCount(core->getStatistics().counter("circuit propagations")),
00084 d_conflictCount(core->getStatistics().counter("conflicts")),
00085 d_conflictClauseCount(core->getStatistics().counter("conflict clauses")),
00086 d_clauses(core->getCM()->getCurrentContext()),
00087 d_unreportedLits(core->getCM()->getCurrentContext()),
00088 d_unreportedLitsHandled(core->getCM()->getCurrentContext()),
00089 d_nonLiterals(core->getCM()->getCurrentContext()),
00090 d_nonLiteralsSaved(core->getCM()->getCurrentContext()),
00091 d_simplifiedThm(core->getCM()->getCurrentContext()),
00092 d_nonlitQueryStart(core->getCM()->getCurrentContext()),
00093 d_nonlitQueryEnd(core->getCM()->getCurrentContext()),
00094 d_clausesQueryStart(core->getCM()->getCurrentContext()),
00095 d_clausesQueryEnd(core->getCM()->getCurrentContext()),
00096 d_conflictClauseManager(core->getCM()->getCurrentContext(), this),
00097 d_literalSet(core->getCM()->getCurrentContext()),
00098 d_useEnqueueFact(false),
00099 d_inCheckSAT(false),
00100 d_litsAlive(core->getCM()->getCurrentContext()),
00101 d_litsMaxScorePos(0),
00102 d_splitterCount(0),
00103 d_litSortCount(0),
00104 d_berkminFlag(core->getFlags()["berkmin"].getBool())
00105 {
00106 if (core->getFlags()["de"].getString() == "caching")
00107 d_decisionEngine = new DecisionEngineCaching(core, this);
00108 else if (core->getFlags()["de"].getString() == "mbtf")
00109 d_decisionEngine = new DecisionEngineMBTF(core, this);
00110 else
00111 d_decisionEngine = new DecisionEngineDFS(core, this);
00112
00113 IF_DEBUG (
00114 d_nonLiterals.setName("CDList[SearchEngineDefault.d_nonLiterals]");
00115 d_clauses.setName("CDList[SearchEngineDefault.d_clauses]");
00116 )
00117
00118 d_conflictClauseStack.push_back(new deque<ClauseOwner>());
00119 d_conflictClauses = d_conflictClauseStack.back();
00120 }
00121
00122
00123
00124
00125 SearchEngineFast::~SearchEngineFast() {
00126 for (unsigned i=0; i < d_circuits.size(); i++)
00127 delete d_circuits[i];
00128 delete d_decisionEngine;
00129 for(size_t i=0, iend=d_conflictClauseStack.size(); i<iend; ++i)
00130 delete d_conflictClauseStack[i];
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 vector<std::pair<Clause, int> >&
00143 SearchEngineFast::wp(const Literal& literal) {
00144
00145 return literal.wp();
00146 }
00147
00148 #ifdef DEBUG
00149 static void checkAssump(const Theorem& t, const Theorem& orig,
00150 const CDMap<Expr,Theorem>& assumptions) {
00151 const Assumptions::iterator iend = t.getAssumptions().end();
00152 if(!(!t.isAssump() || assumptions.count(t.getExpr()) > 0))
00153 orig.printDebug();
00154 DebugAssert((!t.isAssump() || assumptions.count(t.getExpr()) > 0),
00155 "checkAssump: found stray theorem:\n "
00156 + t.toString());
00157 if(t.isAssump()) return;
00158 for (Assumptions::iterator i = t.getAssumptions().begin(); i != iend; ++i) {
00159 if (!i->isFlagged()) {
00160 i->setFlag();
00161
00162 checkAssump(*i, orig, assumptions);
00163 }
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 static void
00174 checkAssumpDebug(const Theorem& res,
00175 const CDMap<Expr,Theorem>& assumptions) {
00176
00177
00178 if(!res.withAssumptions()) return;
00179 if(!res.getAssumptions().isNull()) {
00180 res.clearAllFlags();
00181 checkAssump(res, res, assumptions);
00182 }
00183 }
00184 #endif
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 bool SearchEngineFast::checkSAT()
00195 {
00196 d_inCheckSAT=true;
00197 if (!bcp()) {
00198 DebugAssert(d_factQueue.empty(), "checkSAT()");
00199 if (!fixConflict()) {
00200 d_inCheckSAT=false;
00201 return false;
00202 }
00203 }
00204 while (true) {
00205 if (split()) {
00206
00207 while (!bcp()) {
00208 DebugAssert(d_factQueue.empty(), "checkSAT()");
00209 d_decisionEngine->goalSatisfied();
00210
00211
00212
00213 if (!fixConflict()) {
00214 d_inCheckSAT=false;
00215 return false;
00216 }
00217 }
00218 }
00219
00220
00221 else {
00222 d_inCheckSAT=false;
00223 return true;
00224 }
00225 }
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 bool SearchEngineFast::split()
00263 {
00264 TRACE_MSG("search basic", "Choosing splitter");
00265 Expr splitter = findSplitter();
00266 if (splitter.isNull()) {
00267 TRACE_MSG("search basic", "No splitter");
00268 bool res(d_core->inconsistent() || !d_core->checkSATCore());
00269 if(!res) {
00270 d_splitterCount = 0;
00271 res = !bcp();
00272 }
00273 return res;
00274 }
00275 Literal l(newLiteral(splitter));
00276 Theorem simp;
00277 if(l.getValue() != 0) {
00278
00279
00280 simp = l.deriveTheorem();
00281 d_literals.push_back((l.getValue() == 1)? l : !l);
00282 d_core->addFact(simp);
00283 return true;
00284 }
00285 else {
00286 simp = d_core->simplify(splitter);
00287 const Expr& e = simp.getRHS();
00288 if(e.isBoolConst()) {
00289 IF_DEBUG(debugger.counter("splitter simplified to TRUE or FALSE")++);
00290 if(e.isTrue()) simp = d_commonRules->iffTrueElim(simp);
00291 else {
00292 if(splitter.isNot())
00293 simp = d_commonRules->notNotElim(d_commonRules->iffFalseElim(simp));
00294 else
00295 simp = d_commonRules->iffFalseElim(simp);
00296 }
00297 TRACE("search full", "Simplified candidate: ", splitter.toString(), "");
00298 TRACE("search full", " to: ",
00299 simp.getExpr().toString(), "");
00300
00301 d_core->addFact(simp);
00302 addLiteralFact(simp);
00303 DebugAssert(l.getValue()!=0, "SearchFast::split(): l = "+l.toString());
00304 return true;
00305 }
00306 }
00307
00308 TRACE("search terse", "Asserting splitter: #"
00309 +int2string(d_core->getStatistics().counter("splitters"))+": ",
00310 splitter, "");
00311 d_decisionEngine->pushDecision(splitter);
00312 return true;
00313 }
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 static inline bool compareLits(const Literal& l1,
00332 const Literal& l2)
00333 {
00334 return (l1.score() > l2.score());
00335 }
00336
00337 IF_DEBUG(static string lits2str(const vector<Literal>& lits) {
00338 ostringstream ss;
00339 ss << "\n[";
00340 for(vector<Literal>::const_iterator i=lits.begin(), iend=lits.end();
00341 i!=iend; ++i)
00342 ss << *i << "\n ";
00343 ss << "\n]";
00344 return ss.str();
00345 });
00346
00347
00348
00349
00350
00351
00352
00353 void SearchEngineFast::updateLitScores(bool firstTime)
00354 {
00355 TRACE("search literals", "updateLitScores(size=", d_litsByScores.size(),
00356 ") {");
00357 unsigned count, score;
00358
00359 if (firstTime && followChaff) {
00360 ::stable_sort(d_litsByScores.begin(), d_litsByScores.end(), compareLits);
00361 }
00362
00363 for(size_t i=0; i< d_litsByScores.size(); ++i) {
00364
00365 Literal lit = d_litsByScores[i];
00366
00367 while(lit.count()==0 && i+1 < d_litsByScores.size()) {
00368 TRACE("search literals", "Removing lit["+int2string(i)+"] = ", lit,
00369 " from d_litsByScores");
00370
00371 lit.added()=false;
00372 lit = d_litsByScores.back();
00373 d_litsByScores[i] = lit;
00374 d_litsByScores.pop_back();
00375 }
00376
00377 if(lit.count()==0 && i+1 == d_litsByScores.size()) {
00378 TRACE("search literals", "Removing last lit["+int2string(i)+"] = ", lit,
00379 " from d_litsByScores");
00380 lit.added()=false;
00381 d_litsByScores.pop_back();
00382 break;
00383 }
00384
00385 TRACE("search literals", "Updating lit["+int2string(i)+"] = ", lit, " {");
00386
00387 DebugAssert(lit == d_litsByScores[i], "lit = "+lit.toString());
00388 DebugAssert(lit.added(), "lit = "+lit.toString());
00389 DebugAssert(lit.count()>0, "lit = "+lit.toString());
00390
00391 count = lit.count();
00392 unsigned& countPrev = lit.countPrev();
00393 int& scoreRef = lit.score();
00394
00395 score = scoreRef/2 + count - countPrev;
00396 scoreRef = score;
00397 countPrev = count;
00398
00399 TRACE("search literals", "Updated lit["+int2string(i)+"] = ", lit, " }");
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 }
00412 ::stable_sort(d_litsByScores.begin(), d_litsByScores.end(), compareLits);
00413 d_litsMaxScorePos = 0;
00414 d_litSortCount=d_litsByScores.size();
00415 TRACE("search splitters","updateLitScores => ", lits2str(d_litsByScores),"");
00416 TRACE("search literals", "updateLitScores(size=", d_litsByScores.size(),
00417 ") => }");
00418 }
00419
00420 void SearchEngineFast::updateLitCounts(const Clause& c)
00421 {
00422 TRACE("search literals", "updateLitCounts(", CompactClause(c), ") {");
00423 for(unsigned i=0; i<c.size(); ++i) {
00424
00425 Literal lit = c[i];
00426 DebugAssert(lit.getExpr().isAbsLiteral(),"Expected literal");
00427
00428
00429
00430 d_litSortCount--;
00431
00432 if(!lit.added()) {
00433 TRACE("search literals", "adding literal ", lit, " to d_litsByScores");
00434 d_litsByScores.push_back(lit);
00435 lit.added()=true;
00436 }
00437 }
00438 if(d_litSortCount < 0) {
00439 ::stable_sort(d_litsByScores.begin(), d_litsByScores.end(), compareLits);
00440 d_litSortCount=d_litsByScores.size();
00441 }
00442 TRACE("search splitters","updateLitCounts => ", lits2str(d_litsByScores),"");
00443 TRACE_MSG("search literals", "updateLitCounts => }");
00444 }
00445
00446 Expr SearchEngineFast::findSplitter()
00447 {
00448 TRACE_MSG("splitters", "SearchEngineFast::findSplitter() {");
00449 Expr splitter;
00450 unsigned i;
00451
00452
00453
00454
00455 if (d_berkminFlag && !d_conflictClauses->empty())
00456 {
00457 unsigned sCount = 0;
00458 std::deque<ClauseOwner>::reverse_iterator foundUnsat = d_conflictClauses->rend();
00459 for (std::deque<ClauseOwner>::reverse_iterator i = d_conflictClauses->rbegin();
00460 i != d_conflictClauses->rend();
00461 ++i) {
00462 ++sCount;
00463 if (!((Clause)*i).sat(true)) {
00464 foundUnsat = i;
00465 break;
00466 }
00467 }
00468 if (foundUnsat != d_conflictClauses->rend()) {
00469 Clause &topClause = *foundUnsat;
00470 int numLits = topClause.size();
00471 int bestScore = 0;
00472 int bestLit = -1;
00473 unsigned numChoices = 0;
00474 for (int i = 0; i < numLits; ++i) {
00475 const Literal& lit = topClause[i];
00476 if (lit.getValue() != 0) continue;
00477 if (bestLit == -1) bestLit = i;
00478 ++numChoices;
00479 int s = lit.score();
00480 if (s > bestScore) {
00481 bestLit = i;
00482 bestScore = s;
00483 }
00484 }
00485 if (bestLit != -1) {
00486 splitter = topClause[bestLit].getExpr();
00487 IF_DEBUG(debugger.counter("BerkMin heuristic")++);
00488 TRACE("splitters", "SearchEngineFast::findSplitter()[berkmin] => ",
00489 splitter, " }");
00490 return splitter;
00491 }
00492 }
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 for (int i = d_nonLiterals.size()-1; i >= 0; --i) {
00507 const Expr& e = d_nonLiterals[i].get().getExpr();
00508 if (e.isTrue()) continue;
00509
00510 DebugAssert(!e.isBoolConst(), "Expected non-bool const");
00511 DebugAssert(d_core->simplifyExpr(e) == e,
00512 "Expected non-literal to be simplified:\n e = "
00513 +e.toString()+"\n simplify(e) = "
00514 +d_core->simplifyExpr(e).toString());
00515 splitter = d_decisionEngine->findSplitter(e);
00516
00517
00518
00519 if (splitter.isNull()) continue;
00520 IF_DEBUG(debugger.counter("splitters from non-literals")++);
00521 TRACE("splitters", "SearchEngineFast::findSplitter()[non-lit] => ",
00522 splitter, " }");
00523 return splitter;
00524 }
00525
00526
00527 if (d_splitterCount <= 0) {
00528 updateLitScores(false);
00529
00530
00531 d_splitterCount = 0x10;
00532 } else
00533 d_splitterCount--;
00534
00535 for (i=d_litsMaxScorePos; i<d_litsByScores.size(); ++i) {
00536 const Literal& splitterLit = d_litsByScores[i];
00537 TRACE("search splitters", "d_litsByScores["+int2string(i)+"] = ",
00538 splitterLit,"");
00539
00540 if(splitterLit.getValue() != 0) continue;
00541 splitter = splitterLit.getExpr();
00542
00543 if(!isGoodSplitter(splitter)) continue;
00544 d_litsMaxScorePos = i+1;
00545 IF_DEBUG(debugger.counter("splitters from literals")++);
00546 TRACE("splitters", "d_litsMaxScorePos: ", d_litsMaxScorePos, "");
00547 TRACE("splitters", "SearchEngineFast::findSplitter()[lit] => ",
00548 splitter, " }");
00549 return splitter;
00550 }
00551 TRACE_MSG("splitters",
00552 "SearchEngineFast::findSplitter()[not found] => Null }");
00553 return Expr();
00554 }
00555
00556
00557 void SearchEngineFast::recordFact(const Theorem& thm)
00558 {
00559 Literal l(newLiteral(thm.getExpr()));
00560 if(l.getValue() == 0) {
00561 l.setValue(thm, thm.getScope());
00562 IF_DEBUG(debugger.counter("recordFact adds unreported lit")++);
00563 d_unreportedLits.insert(l.getExpr(),thm,thm.getScope());
00564 } else if (l.getValue() == 1 && l.getScope() > thm.getScope()) {
00565
00566
00567 IF_DEBUG(debugger.counter("recordFact adds unreported lit")++);
00568 d_unreportedLits.insert(l.getExpr(),thm,thm.getScope());
00569 } else if(l.getValue() < 0) {
00570 if(l.isNegative())
00571 setInconsistent(d_commonRules->contradictionRule(l.deriveTheorem(), thm));
00572 else
00573 setInconsistent(d_commonRules->contradictionRule(thm, l.deriveTheorem()));
00574 }
00575
00576
00577
00578 }
00579
00580 #ifdef DEBUG
00581 void SearchEngineFast::fullCheck()
00582 {
00583 for (unsigned i = 0;
00584 i < d_clauses.size();
00585 ++i) {
00586 if (!((Clause)d_clauses[i]).sat()) {
00587 bool sat = false;
00588 const Clause &theClause = d_clauses[i];
00589 unsigned numLits = theClause.size();
00590 unsigned numChoices = 0;
00591 for (unsigned j = 0; !sat && j < numLits; ++j) {
00592 if (theClause[j].getValue() == 0)
00593 ++numChoices;
00594 else if (theClause[j].getValue() == 1)
00595 sat = true;
00596 }
00597 if (sat) continue;
00598 if (numChoices <= 1 || !theClause.wpCheck()) {
00599 CVCL::debugger.getOS() << CompactClause(theClause) << endl;
00600 CVCL::debugger.getOS() << theClause.toString() << endl;
00601 }
00602 DebugAssert(numChoices > 1, "BCP postcondition violated: unsat or unit clause(s)");
00603 DebugAssert(theClause.wpCheck(), "Watchpointers broken");
00604 }
00605 }
00606
00607 if (!d_conflictClauses->empty())
00608 {
00609 for (std::deque<ClauseOwner>::reverse_iterator i = d_conflictClauses->rbegin();
00610 i != d_conflictClauses->rend();
00611 ++i) {
00612 if (!((Clause)*i).sat()) {
00613 bool sat = false;
00614 Clause &theClause = *i;
00615 unsigned numLits = theClause.size();
00616 unsigned numChoices = 0;
00617 for (unsigned j = 0; !sat && j < numLits; ++j) {
00618 if (theClause[j].getValue() == 0)
00619 ++numChoices;
00620 else if (theClause[j].getValue() == 1)
00621 sat = true;
00622 }
00623 if (sat) continue;
00624 if (numChoices <= 1 || !theClause.wpCheck()) {
00625 CVCL::debugger.getOS() << CompactClause(theClause) << endl;
00626 CVCL::debugger.getOS() << theClause.toString() << endl;
00627 }
00628
00629 DebugAssert(numChoices > 1, "BCP postcondition violated: unsat or unit conflict clause(s)");
00630 DebugAssert(theClause.wpCheck(), "Watchpointers broken");
00631
00632 }
00633 }
00634 }
00635 }
00636 #endif
00637
00638
00639 void SearchEngineFast::clearLiterals() {
00640 TRACE_MSG("search literals", "clearLiterals()");
00641 d_literals.clear();
00642 }
00643
00644
00645 bool SearchEngineFast::bcp()
00646 {
00647 TRACE("search bcp", "bcp@"+int2string(scopeLevel())+"(#lits=",
00648 d_literals.size(), ") {");
00649 IF_DEBUG(TRACE_MSG("search bcp", "literals=[\n");
00650 for(size_t i=0,iend=d_literals.size(); i<iend; i++)
00651 TRACE("search bcp", " ", d_literals[i], ",");
00652 TRACE_MSG("search bcp", "]"));
00653 DebugAssert(d_factQueue.empty(), "bcp(): start");
00654 bool newInfo = true;
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 while (newInfo) {
00678 IF_DEBUG(debugger.counter("BCP: while(newInfo)")++);
00679 TRACE_MSG("search bcp", "while(newInfo) {");
00680 newInfo = false;
00681 while(!d_core->inconsistent() && d_literals.size() > 0) {
00682 for(unsigned i=0; !d_core->inconsistent() && i<d_literals.size(); ++i) {
00683 Literal l = d_literals[i];
00684 TRACE("search props", "Propagating literal: [", l.toString(), "]");
00685 DebugAssert(l.getValue() == 1, "Bad literal is d_literals: "
00686 +l.toString());
00687 d_litsAlive.push_back(l);
00688
00689
00690
00691 std::vector<std::pair<Clause, int> >& wps = wp(l);
00692 TRACE("search props", "Appears in ", wps.size(), " clauses.");
00693 for(unsigned j=0; j<wps.size(); ++j) {
00694 const Clause& c = wps[j].first;
00695 int k = wps[j].second;
00696 DebugAssert(c.watched(k).getExpr() == (!l).getExpr(),
00697 "Bad watched literal:\n l = "+l.toString()
00698 +"\n c[k] = "+c.watched(k).toString());
00699 if(c.deleted()) {
00700 if(wps.size() > 1) {
00701 wps[j] = wps.back();
00702 --j;
00703 }
00704 wps.pop_back();
00705 } else if(true || !c.sat()) {
00706
00707 bool wpUpdated;
00708 bool conflict = !propagate(c, k, wpUpdated);
00709
00710 if(wpUpdated) {
00711 if(wps.size() > 1) {
00712 wps[j] = wps.back();
00713 --j;
00714 }
00715 wps.pop_back();
00716 }
00717 if (conflict) {
00718 clearFacts();
00719 DebugAssert(d_factQueue.empty(), "bcp(): conflict");
00720 TRACE_MSG("search bcp", "bcp[conflict] => false }}");
00721 return false;
00722 }
00723 }
00724 }
00725
00726 vector<Circuit*>& cps = d_circuitsByExpr[l.getExpr()];
00727 for (vector<Circuit*>::iterator it = cps.begin(), end = cps.end();
00728 it < end; it++)
00729 {
00730 if (!(*it)->propagate(this)) {
00731 clearFacts();
00732 DebugAssert(d_factQueue.empty(), "bcp(): conflict-2");
00733 TRACE_MSG("search bcp", "bcp[circuit propagate] => false }}");
00734 return false;
00735 }
00736 }
00737 }
00738
00739 clearLiterals();
00740
00741 if(!d_core->inconsistent()) commitFacts();
00742 }
00743 if (d_core->inconsistent()) {
00744 d_conflictTheorem = d_core->inconsistentThm();
00745 clearFacts();
00746 TRACE_MSG("search bcp", "bcp[DP conflict] => false }}");
00747 return false;
00748 }
00749 else
00750 TRACE("search basic", "Processed ", d_literals.size(), " propagations");
00751 IF_DEBUG(fullCheck());
00752 clearLiterals();
00753
00754 bool dfs_heuristic = (d_core->getFlags()["de"].getString() == "dfs");
00755 TRACE("search dfs", "DFS is ", (dfs_heuristic? "on" : "off"),
00756 " (de = "+d_core->getFlags()["de"].getString()+") {");
00757
00758
00759
00760
00761
00762
00763
00764 size_t origSize = d_nonLiterals.size();
00765 bool done(false);
00766 for(int i=origSize-1; !done && !d_core->inconsistent() && i>=0; --i) {
00767 const Theorem& thm = d_nonLiterals[i].get();
00768 const Expr& e = thm.getExpr();
00769 TRACE("search dfs", "Simplifying non-literal", e, "");
00770 if (e.isTrue()) {
00771
00772 IF_DEBUG(debugger.counter("BCP: simplified non-literals: skipped [stale]")++);
00773 TRACE_MSG("search bcp", "}[continue]// end of while(newInfo)");
00774 continue;
00775 }
00776 IF_DEBUG(debugger.counter("BCP: simplified non-literals")++);
00777 Theorem simpThm = simplify(thm);
00778 Expr simp = simpThm.getExpr();
00779 if(simp != e) {
00780 IF_DEBUG(debugger.counter("BCP: simplified non-literals: changed")++);
00781 newInfo = true;
00782
00783 if (!simp.isFalse()) {
00784 while (simp.isExists()) {
00785 simpThm = d_commonRules->skolemize(simpThm);
00786 simp = simpThm.getExpr();
00787 }
00788 if (simp.isAbsLiteral()) {
00789 enqueueFact(simpThm);
00790 commitFacts();
00791 }
00792 d_nonLiterals[i] = simpThm;
00793 if(dfs_heuristic) {
00794
00795
00796
00797
00798 done = true;
00799 if(d_nonLiterals.size() > origSize && d_literals.empty())
00800 newInfo = false;
00801 }
00802 } else
00803 setInconsistent(simpThm);
00804 } else if (dfs_heuristic) done = true;
00805 }
00806 TRACE("search dfs", "End of non-literal simplification: newInfo = ",
00807 (newInfo? "true" : "false"), " }}");
00808 if (d_core->inconsistent()) {
00809 d_conflictTheorem = d_core->inconsistentThm();
00810 DebugAssert(d_factQueue.empty(), "bcp(): inconsistent (nonLits)");
00811 TRACE_MSG("search bcp", "bcp[nonCNF conflict] => false }}");
00812 return false;
00813 }
00814 TRACE_MSG("search bcp", "}// end of while(newInfo)");
00815 }
00816 IF_DEBUG(fullCheck());
00817 DebugAssert(d_factQueue.empty(), "bcp(): end");
00818 TRACE_MSG("search bcp", "bcp => true }");
00819 return true;
00820 }
00821
00822
00823
00824 bool SearchEngineFast::propagate(const Clause &c, int idx, bool& wpUpdated)
00825 {
00826 TRACE("search propagate", "propagate(", CompactClause(c),
00827 ", idx = "+int2string(idx)+") {");
00828 DebugAssert(idx==0 || idx==1, "propagate(): bad index = "+int2string(idx));
00829
00830
00831 DebugAssert((c.size() == 1) || c.watched(idx).getValue() < 0,
00832 "propagate(): this literal must be FALSE: c.watched("
00833 +int2string(idx)+")\n c = "+c.toString());
00834 wpUpdated = false;
00835 int lit = c.wp(idx), otherLit = c.wp(1-idx);
00836 int dir = c.dir(idx);
00837 int size = c.size();
00838 while(true) {
00839 TRACE_MSG("search propagate", "propagate: lit="+int2string(lit)
00840 +", otherLit="+int2string(otherLit)+", dir="+int2string(dir));
00841 lit += dir;
00842 if(lit < 0 || lit >= size) {
00843 if(dir == c.dir(idx)) {
00844
00845 lit = c.wp(idx);
00846 dir = -dir;
00847 continue;
00848 }
00849
00850
00851 Literal l(c[otherLit]);
00852 if(l.getValue() < 0) {
00853
00854
00855
00856 vector<Theorem> thms;
00857 for (unsigned i = 0; i < c.size(); ++i)
00858 thms.push_back(c[i].getTheorem());
00859 d_conflictTheorem = d_rules->conflictRule(thms,c.getTheorem());
00860 TRACE("search propagate", "propagate[", CompactClause(c),
00861 "] => false }");
00862 return false;
00863 }
00864 else if(l.getValue() == 0) {
00865 DebugAssert(c.size() > 1 && l.getExpr().isAbsLiteral(), "BCP: Expr should be literal");
00866 d_unitPropCount++;
00867 c.markSat();
00868
00869 unitPropagation(c,otherLit);
00870
00871
00872 TRACE("search propagate", "propagate[", CompactClause(c),
00873 "] => true }");
00874 return true;
00875 }
00876 else {
00877 c.markSat();
00878 TRACE("search propagate", "propagate[", CompactClause(c),
00879 "] => true }");
00880 return true;
00881 }
00882 }
00883
00884 if(lit == otherLit) continue;
00885
00886 Literal l(c[lit]);
00887 int val(l.getValue());
00888
00889 if(val < 0) continue;
00890
00891
00892
00893 if(val > 0) {
00894 c.markSat();
00895
00896 }
00897
00898
00899
00900
00901 c.wp(idx, lit);
00902 c.dir(idx, dir);
00903 DebugAssert(c.watched(idx).getValue() >= 0,
00904 "Bad watched literals in clause:\n"
00905 +CompactClause(c).toString());
00906
00907 Literal inv(!c[lit]);
00908
00909 DebugAssert(inv.getExpr().isAbsLiteral(), "Expr should be literal: inv = "
00910 +inv.getExpr().toString());
00911
00912 pair<Clause, int> p(c, idx);
00913 wp(inv).push_back(p);
00914
00915
00916 wpUpdated = true;
00917 TRACE("search propagate", "propagate[", CompactClause(c),
00918 "] => true }");
00919 return true;
00920 }
00921 }
00922
00923 void SearchEngineFast::unitPropagation(const Clause &c, unsigned idx)
00924 {
00925 vector<Theorem> thms;
00926 for (unsigned i = 0; i < c.size(); ++i)
00927 if (i != idx) {
00928 thms.push_back(c[i].getTheorem());
00929 DebugAssert(!thms.back().isNull(),
00930 "unitPropagation(idx = "+int2string(idx)+", i = "
00931 +int2string(i)+",\n"+c.toString()+")");
00932 }
00933 Theorem thm(d_rules->unitProp(thms,c.getTheorem(),idx));
00934 enqueueFact(thm);
00935
00936
00937 DebugAssert(thm.isAbsLiteral(),
00938 "unitPropagation(): pushing non-literal to d_literals:\n "
00939 +thm.getExpr().toString());
00940 Literal l(newLiteral(thm.getExpr()));
00941 DebugAssert(l.getValue() == 1, "unitPropagation: bad literal: "
00942 +l.toString());
00943 d_literals.push_back(l);
00944 }
00945
00946
00947 bool SearchEngineFast::fixConflict()
00948 {
00949 TRACE_MSG("search basic", "FixConflict");
00950 Theorem res, conf;
00951 d_conflictCount++;
00952 TRACE("conflicts", "found conflict # ", d_conflictCount, "");
00953 IF_DEBUG(if(debugger.trace("impl graph verbose")) {
00954 d_conflictTheorem.printDebug();
00955 });
00956
00957 if (scopeLevel() == d_bottomScope)
00958 return false;
00959 else if(d_conflictTheorem.getScope() <= d_bottomScope) {
00960 d_decisionEngine->popTo(d_bottomScope);
00961 d_litsMaxScorePos = 0;
00962 clearLiterals();
00963 return false;
00964 }
00965
00966 traceConflict(d_conflictTheorem);
00967
00968 if (d_lastConflictScope <= d_bottomScope)
00969 return false;
00970
00971
00972
00973 if(d_unitConflictClauses.size() > 0) {
00974 TRACE_MSG("search basic", "Found unit conflict clause");
00975 d_decisionEngine->popTo(d_bottomScope);
00976 d_litsMaxScorePos = 0;
00977 clearLiterals();
00978 for (vector<Clause>::reverse_iterator i = d_unitConflictClauses.rbegin();
00979 i != d_unitConflictClauses.rend();
00980 ++i) {
00981
00982
00983 Theorem thm = i->getTheorem();
00984 if(thm.getExpr().isOr())
00985 thm = d_commonRules->iffMP(thm, d_commonRules->rewriteOr(thm.getExpr()));
00986 enqueueFact(thm);
00987 commitFacts();
00988 }
00989 d_unitConflictClauses.clear();
00990 return true;
00991 }
00992
00993
00994 DebugAssert(!d_lastConflictClause.isNull(), "");
00995
00996
00997
00998
00999
01000 Clause &c = d_lastConflictClause;
01001 Literal unit_lit;
01002 unsigned idx=0;
01003 unsigned current_dl = d_lastConflictScope;
01004 unsigned back_dl = d_bottomScope;
01005 for (unsigned i = 0; i < c.size(); ++i) {
01006 unsigned dl = c[i].getVar().getScope();
01007 if (dl < current_dl) {
01008 if (dl > back_dl)
01009 back_dl = dl;
01010 }
01011 else {
01012 DebugAssert(unit_lit.getExpr().isNull(),
01013 "Only one lit from the current decision level is allowed.\n"
01014 "current_dl="
01015 +int2string(current_dl)+", scopeLevel="
01016 +int2string(scopeLevel())
01017 +"\n l1 = "
01018 +unit_lit.toString()
01019 +"\n l2 = "+c[i].toString()
01020 +"\nConflict clause: "+c.toString());
01021 unit_lit = c[i];
01022 idx = i;
01023 }
01024 }
01025
01026
01027
01028 DebugAssert(!unit_lit.getExpr().isNull(),"Need to have an FDA in "
01029 "conflict clause: "+c.toString());
01030 d_decisionEngine->popTo(back_dl);
01031 d_litsMaxScorePos = 0;
01032 clearLiterals();
01033 unitPropagation(c,idx);
01034 commitFacts();
01035 return true;
01036 }
01037
01038
01039 void SearchEngineFast::enqueueFact(const Theorem& thm) {
01040
01041 TRACE("search props", "SearchEngineFast::enqueueFact(",
01042 thm.getExpr(), ") {");
01043 if(thm.isAbsLiteral()) {
01044 addLiteralFact(thm);
01045 }
01046 d_factQueue.push_back(thm);
01047 TRACE_MSG("search props", "SearchEngineFast::enqueueFact => }");
01048 }
01049
01050
01051 void SearchEngineFast::setInconsistent(const Theorem& thm) {
01052 TRACE_MSG("search props", "SearchEngineFast::setInconsistent()");
01053 d_factQueue.clear();
01054 IF_DEBUG(debugger.counter("conflicts from SAT solver")++);
01055 d_core->setInconsistent(thm);
01056 }
01057
01058 void SearchEngineFast::commitFacts() {
01059 for(vector<Theorem>::iterator i=d_factQueue.begin(), iend=d_factQueue.end();
01060 i!=iend; ++i) {
01061 TRACE("search props", "commitFacts(", i->getExpr(), ")");
01062 if(d_useEnqueueFact)
01063 d_core->enqueueFact(*i);
01064 else
01065 d_core->addFact(*i);
01066 }
01067 d_factQueue.clear();
01068 }
01069
01070
01071 void SearchEngineFast::clearFacts() {
01072 TRACE_MSG("search props", "clearFacts()");
01073 d_factQueue.clear();
01074 }
01075
01076
01077 void SearchEngineFast::addNewClause(Clause &c)
01078 {
01079 DebugAssert(c.size() > 1, "New clauses should have size > 1");
01080 d_clauses.push_back(c);
01081 updateLitCounts(c);
01082
01083
01084 size_t i=0, iend=c.size();
01085 for(; i<iend && c[i].getValue() != 0; ++i);
01086 DebugAssert(i<iend, "SearchEngineFast::addNewClause:\n"
01087 "no unassigned literals in the clause:\nc = "
01088 +CompactClause(c).toString());
01089 c.wp(0,i); ++i;
01090 for(; i<iend && c[i].getValue() != 0; ++i);
01091 DebugAssert(i<iend, "SearchEngineFast::addNewClause:\n"
01092 "Only one unassigned literal in the clause:\nc = "
01093 +CompactClause(c).toString());
01094 c.wp(1,i);
01095
01096 for(int i=0; i<=1; i++) {
01097 Literal l(!c.watched(i));
01098
01099 pair<Clause, int> p(c, i);
01100 wp(l).push_back(p);
01101 }
01102 }
01103
01104 inline bool TheoremEq(const Theorem& t1, const Theorem& t2) {
01105 DebugAssert(!t1.isNull() && !t2.isNull(),
01106 "analyzeUIPs() Null Theorem found");
01107 return t1.getExpr() == t2.getExpr();
01108 }
01109
01110
01111
01112
01113
01114
01115
01116 static void processNode(const Theorem& thm,
01117 vector<Theorem>& lits,
01118 vector<Theorem>& gamma,
01119 vector<Theorem>& fringe,
01120 int& pending) {
01121
01122 int fanOutCount(thm.getCachedValue() - 1);
01123 thm.setCachedValue(fanOutCount);
01124 bool wasFlagged(thm.isFlagged());
01125 thm.setFlag();
01126 DebugAssert(fanOutCount >= 0,
01127 "analyzeUIPs(): node visited too many times: "
01128 +thm.toString());
01129 if(fanOutCount == 0) {
01130 if(thm.getExpandFlag()) {
01131 if(wasFlagged) {
01132 TRACE("impl graph", "pending.erase(", thm.getExpr(), ")");
01133 DebugAssert(pending > 0,
01134 "analyzeUIPs(): pending set shouldn't be empty here");
01135 pending--;
01136 }
01137 TRACE("impl graph", "fringe.insert(", thm.getExpr(), ")");
01138 fringe.push_back(thm);
01139 } else if(thm.getLitFlag()) {
01140 DebugAssert(thm.isAbsLiteral(), "analyzeUIPs(): bad flag on "
01141 +thm.toString());
01142 if(wasFlagged) {
01143 TRACE("impl graph", "pending.erase(", thm.getExpr(), ")");
01144 DebugAssert(pending > 0,
01145 "analyzeUIPs(): pending set shouldn't be empty here");
01146 pending--;
01147 }
01148 TRACE("impl graph", "lits.insert(", thm.getExpr(), ")");
01149 lits.push_back(thm);
01150 } else {
01151 if(!wasFlagged) {
01152 TRACE("impl graph", "gamma.insert(", thm.getExpr(), ")");
01153 gamma.push_back(thm);
01154 } else {
01155 TRACE("impl graph", "already in gamma: ", thm.getExpr(), "");
01156 }
01157 }
01158 } else {
01159 if(thm.getExpandFlag()) {
01160
01161 if(!wasFlagged) {
01162 pending++;
01163 TRACE("impl graph", "pending.insert(", thm.getExpr(), ")");
01164 } else {
01165 TRACE("impl graph", "already in pending: ", thm.getExpr(), "");
01166 }
01167 } else if(thm.getLitFlag()) {
01168
01169 if(!wasFlagged) {
01170 pending++;
01171 TRACE("impl graph", "pending.insert(", thm.getExpr(), ")");
01172 } else {
01173 TRACE("impl graph", "already in pending: ", thm.getExpr(), "");
01174 }
01175 } else {
01176 if(!wasFlagged) {
01177 TRACE("impl graph", "gamma.insert(", thm.getExpr(), ")");
01178 gamma.push_back(thm);
01179 } else {
01180 TRACE("impl graph", "already in gamma: ", thm.getExpr(), "");
01181 }
01182 }
01183 }
01184
01185
01186
01187
01188 }
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 void SearchEngineFast::analyzeUIPs(const Theorem &falseThm, int conflictScope)
01275 {
01276 TRACE("impl graph", "analyzeUIPs(scope = ", conflictScope, ") {");
01277 vector<Theorem> fringe[2];
01278 unsigned curr(0), next(1);
01279
01280 int pending(0);
01281 vector<Theorem> lits;
01282 vector<Theorem> gamma;
01283
01284 Theorem start = falseThm;
01285 d_lastConflictClause = Clause();
01286 d_lastConflictScope = conflictScope;
01287 start.clearAllFlags();
01288
01289 TRACE("search full", "Analysing UIPs at level: ", conflictScope, "");
01290
01291
01292 const Assumptions& a=start.getAssumptionsRef();
01293 for(Assumptions::iterator i=a.begin(), iend=a.end(); i!=iend; ++i) {
01294 processNode(*i, lits, gamma, fringe[curr], pending);
01295 }
01296
01297 while (true) {
01298 TRACE_MSG("impl graph", "analyzeUIPs(): fringe size = "
01299 +int2string(fringe[curr].size())
01300 +", pending size = "+int2string(pending));
01301
01302
01303
01304
01305 if(fringe[curr].size() <= 1 && pending == 0
01306 && (fringe[curr].size() == 0
01307 || !fringe[curr].back().getExpandFlag())) {
01308
01309 if(fringe[curr].size() > 0)
01310 lits.push_back(fringe[curr].back());
01311 IF_DEBUG(if(debugger.trace("impl graph")) {
01312 ostream& os = debugger.getOS();
01313 os << "Creating conflict clause:"
01314 << "\n start: " << start.getExpr()
01315 << "\n Lits: [\n";
01316 for(size_t i=0; i<lits.size(); i++)
01317 os << " " << lits[i].getExpr() << "\n";
01318 os << "]\n Gamma: [\n";
01319 for(size_t i=0; i<gamma.size(); i++)
01320 os << " " << gamma[i].getExpr() << "\n";
01321 os << "]" << endl;
01322 });
01323
01324 Theorem clause = d_rules->conflictClause(start, lits, gamma);
01325 d_conflictClauseCount++;
01326
01327 Clause c(d_core, d_vm, clause, d_bottomScope, __FILE__, __LINE__);
01328 updateLitCounts(c);
01329 if (c.size() > 1) {
01330
01331
01332 int firstLit = 0;
01333 int secondLit = 1;
01334 int firstDL = c[0].getScope();
01335 int secondDL = c[1].getScope();
01336
01337 if(firstDL < secondDL) {
01338 firstLit=1; secondLit=0;
01339 int tmp(secondDL);
01340 secondDL=firstDL; firstDL=tmp;
01341 }
01342 for(unsigned i = 2; i < c.size(); ++i) {
01343 int cur = c[i].getScope();
01344 if(cur >= firstDL) {
01345 secondLit=firstLit; secondDL=firstDL;
01346 firstLit=i; firstDL=cur;
01347 } else if(cur > secondDL) {
01348 secondLit=i; secondDL=cur;
01349 }
01350 }
01351
01352 c.wp(0, firstLit);
01353 c.wp(1, secondLit);
01354
01355
01356 for(int i=0; i<=1; i++) {
01357
01358 Literal l(!c.watched(i));
01359
01360 pair<Clause, int> p(c, i);
01361 wp(l).push_back(p);
01362 }
01363 }
01364 TRACE("conflict clauses",
01365 "Conflict clause #"+int2string(d_conflictClauseCount)
01366 +": ", CompactClause(c), "");
01367 if(c.size() == 1) {
01368
01369 TRACE("conflict clauses", "analyzeUIPs(): unit clause: ",
01370 CompactClause(c), "");
01371 d_unitConflictClauses.push_back(c);
01372 }
01373 else {
01374 TRACE("conflict clauses", "analyzeUIPs(): conflict clause ",
01375 CompactClause(c), "");
01376 DebugAssert(c.getScope() <= d_bottomScope,
01377 "Conflict clause should be at bottom scope.");
01378 d_conflictClauses->push_back(c);
01379 if (d_lastConflictClause.isNull()) {
01380 d_lastConflictClause = c;
01381
01382
01383
01384 }
01385 }
01386 if(fringe[curr].size() > 0) {
01387
01388 IF_DEBUG(debugger.counter("UIPs")++);
01389 start = fringe[curr].back();
01390 lits.clear();
01391 gamma.clear();
01392 start.clearAllFlags();
01393 } else {
01394
01395
01396 TRACE_MSG("impl graph", "analyzeUIPs => }");
01397 return;
01398 }
01399 }
01400
01401 for(vector<Theorem>::iterator i=fringe[curr].begin(),
01402 iend=fringe[curr].end();
01403 i!=iend; ++i) {
01404 const Assumptions& a=i->getAssumptionsRef();
01405 for(Assumptions::iterator j=a.begin(), jend=a.end(); j!=jend; ++j) {
01406 processNode(*j, lits, gamma, fringe[next], pending);
01407 }
01408 }
01409
01410 fringe[curr].clear();
01411 curr = 1 - curr;
01412 next = 1 - next;
01413 IF_DEBUG(if(pending > 0 && fringe[curr].size()==0)
01414 falseThm.printDebug());
01415 DebugAssert(pending == 0 || fringe[curr].size() > 0,
01416 "analyzeUIPs(scope = "
01417 +int2string(conflictScope)+"): empty fringe");
01418 }
01419 }
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432 void SearchEngineFast::getCounterExample(std::vector<Expr>& assertions) {
01433
01434
01435 SearchImplBase::getCounterExample(assertions);
01436 getAssumptions(assertions);
01437 }
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452 void
01453 SearchEngineFast::addNonLiteralFact(const Theorem& thm) {
01454 TRACE("search", "addNonLiteralFact(", thm, ") {");
01455 TRACE("search", "d_nonLiteralsSaved.size()=",d_nonLiteralsSaved.size(),
01456 "@"+int2string(scopeLevel()));
01457
01458 const Expr& e(thm.getExpr());
01459 if(d_nonLiteralsSaved.count(e) > 0) {
01460
01461 TRACE_MSG("search", "addNonLiteralFact[skipping] => }");
01462 IF_DEBUG(debugger.counter("skipped repeated non-literals")++);
01463 return;
01464 }
01465
01466 d_nonLiteralsSaved[e]=thm;
01467 bool isCNFclause(false);
01468
01469
01470
01471 int k = e.getKind();
01472 if (k == AND_R || k == IFF_R || k == ITE_R)
01473 {
01474 d_circuits.push_back(new Circuit(this, thm));
01475 }
01476
01477 else if(e.isAnd()) {
01478 for(int i=0, iend=e.arity(); i<iend; ++i) {
01479 Theorem t_i(d_commonRules->andElim(thm, i));
01480
01481
01482 if(e[i].isAbsLiteral()) {
01483 d_core->enqueueFact(t_i);
01484 }
01485 else addNonLiteralFact(t_i);
01486 }
01487 } else {
01488 int unsetLits(0);
01489 size_t unitLit(0);
01490 vector<Theorem> thms;
01491 if(e.isOr()) {
01492 isCNFclause = true;
01493 for(int i=0; isCNFclause && i<e.arity(); ++i) {
01494 isCNFclause=e[i].isAbsLiteral();
01495 if(isCNFclause) {
01496
01497 Literal l(newLiteral(e[i]));
01498 if(l.getValue() > 0)
01499 return;
01500 if(l.getValue() == 0) {
01501 unsetLits++; unitLit = i;
01502 } else
01503 thms.push_back(l.deriveTheorem());
01504 }
01505 }
01506 }
01507 if(isCNFclause) {
01508 DebugAssert(e.arity() > 1, "Clause should have more than one literal");
01509
01510 if(unsetLits==0) {
01511 TRACE("search", "contradictory clause:\n",
01512 CompactClause(Clause(d_core, d_vm, thm, scopeLevel())),"");
01513 setInconsistent(d_rules->conflictRule(thms, thm));
01514 } else if(unsetLits==1) {
01515 TRACE("search", "unit clause, unitLit = "+int2string(unitLit)+":\n",
01516 CompactClause(Clause(d_core, d_vm, thm, scopeLevel())),"");
01517 d_core->enqueueFact(d_rules->unitProp(thms, thm, unitLit));
01518 } else {
01519 Clause c(d_core, d_vm, thm, scopeLevel(), __FILE__, __LINE__);
01520 IF_DEBUG(debugger.counter("CNF clauses added")++);
01521 TRACE("search", "addNonLiteralFact: adding CNF: ", c, "");
01522 addNewClause(c);
01523 }
01524 } else {
01525 TRACE("search", "addNonLiteralFact: adding non-literal: ", thm, "");
01526 IF_DEBUG(debugger.counter("added non-literals")++);
01527 d_nonLiterals.push_back(SmartCDO<Theorem>(d_core->getCM()->getCurrentContext(), thm));
01528
01529 }
01530 }
01531 TRACE_MSG("search", "addNonLiteralFact => }");
01532 }
01533
01534
01535
01536
01537 void
01538 SearchEngineFast::addLiteralFact(const Theorem& thm) {
01539 TRACE("search", "addLiteralFact(", thm, ")");
01540
01541 bool useEF(d_useEnqueueFact);
01542 d_useEnqueueFact=true;
01543
01544 DebugAssert(thm.isAbsLiteral(),
01545 "addLiteralFact: not a literal: " + thm.toString());
01546
01547 Literal l(newLiteral(thm.getExpr()));
01548 TRACE("search", "addLiteralFact: literal = ", l, "");
01549
01550
01551
01552 if ((l.getValue() == 0 )
01553 ) {
01554 l.setValue(thm, scopeLevel());
01555 DebugAssert(l.getExpr().isAbsLiteral(),
01556 "addLiteralFact(): pushing non-literal to d_literals:\n "
01557 +l.getExpr().toString());
01558 DebugAssert(l.getValue() == 1, "addLiteralFact(): l = "+l.toString());
01559 d_literals.push_back(l);
01560 d_literalSet.insert(l.getExpr(),l);
01561
01562
01563 if(!d_inCheckSAT) bcp();
01564
01565
01566
01567
01568
01569 } else if(l.getValue() < 0) {
01570 if(l.isNegative())
01571 setInconsistent(d_commonRules->contradictionRule(l.deriveTheorem(), thm));
01572 else
01573 setInconsistent(d_commonRules->contradictionRule(thm, l.deriveTheorem()));
01574 }
01575 d_useEnqueueFact=useEF;
01576 }
01577
01578
01579
01580 Theorem
01581 SearchEngineFast::newIntAssumption(const Expr& e) {
01582 Theorem thm(SearchImplBase::newIntAssumption(e));
01583 DebugAssert(thm.isAssump(), "Splitter should be an assumption:" + thm.toString());
01584 TRACE("search full", "Splitter: ", thm.toString(), "");
01585 const Expr& expr = thm.getExpr();
01586 Literal l(newLiteral(expr));
01587 if(l.getValue() == 0) {
01588 l.setValue(thm, scopeLevel());
01589 if(l.getExpr().isAbsLiteral()) {
01590 DebugAssert(l.getValue() == 1, "newIntAssumption(): l = "+l.toString());
01591 d_literals.push_back(l);
01592 }
01593 else
01594 d_litsAlive.push_back(l);
01595 }
01596
01597
01598 return thm;
01599 }
01600
01601 bool
01602 SearchEngineFast::isAssumption(const Expr& e) {
01603 return (SearchImplBase::isAssumption(e)
01604 || (d_nonLiteralsSaved.count(e) > 0));
01605 }
01606
01607
01608 void
01609 SearchEngineFast::addSplitter(const Expr& e, int priority) {
01610
01611 DebugAssert(e.isAbsLiteral(), "SearchEngineFast::addSplitter("+e.toString()+")");
01612 Literal lit(newLiteral(e));
01613 d_dpSplitters.push_back(Splitter(lit));
01614 if(priority != 0) {
01615 d_litSortCount--;
01616 lit.score() += priority*10;
01617 }
01618 if(!lit.added()) {
01619 TRACE("search literals", "addSplitter(): adding literal ", lit, " to d_litsByScores");
01620 d_litsByScores.push_back(lit);
01621 lit.added()=true;
01622 if(priority == 0) d_litSortCount--;
01623 }
01624 if(d_litSortCount < 0) {
01625 ::stable_sort(d_litsByScores.begin(), d_litsByScores.end(), compareLits);
01626 d_litSortCount=d_litsByScores.size();
01627 }
01628 TRACE("search splitters","addSplitter => ", lits2str(d_litsByScores),"");
01629 }
01630
01631
01632 bool SearchEngineFast::checkValidMain(const Expr& e2)
01633 {
01634
01635 for(CDMap<Expr,Literal>::iterator i=d_literalSet.begin(),
01636 iend=d_literalSet.end(); i!=iend; ++i)
01637 d_literals.push_back((*i).second);
01638
01639
01640 bool result = checkSAT();
01641
01642 Theorem res;
01643 if (!result)
01644 res = d_conflictTheorem;
01645 else {
01646
01647 vector<Expr> a;
01648 unsigned i;
01649 Theorem thm;
01650
01651 d_lastCounterExample.clear();
01652 for (i=d_nonlitQueryStart; i < d_nonlitQueryEnd; ++i) {
01653 thm = d_nonLiterals[i].get();
01654 DebugAssert(thm.getExpr().isTrue(),
01655 "original nonLiteral doesn't simplify to true");
01656 thm.getLeafAssumptions(a);
01657 for (vector<Expr>::iterator i=a.begin(), iend=a.end(); i != iend; ++i) {
01658 d_lastCounterExample[*i] = true;
01659 }
01660 a.clear();
01661 }
01662 for (i=d_clausesQueryStart; i < d_clausesQueryEnd; ++i) {
01663 thm = simplify(((Clause)d_clauses[i]).getTheorem());
01664 DebugAssert(thm.getExpr().isTrue(),
01665 "original nonLiteral doesn't simplify to true");
01666 thm.getLeafAssumptions(a);
01667 for (vector<Expr>::iterator i=a.begin(), iend=a.end(); i != iend; ++i) {
01668 d_lastCounterExample[*i] = true;
01669 }
01670 a.clear();
01671 }
01672 }
01673
01674 bool r = processResult(res, e2);
01675
01676 if (r) {
01677 d_core->getCM()->popto(d_bottomScope);
01678 d_litsMaxScorePos = 0;
01679
01680
01681 d_unitConflictClauses.clear();
01682 clearLiterals();
01683 clearFacts();
01684
01685 Theorem e_iff_e2(d_commonRules->iffContrapositive(d_simplifiedThm));
01686 d_lastValid =
01687 d_commonRules->iffMP(d_lastValid, d_commonRules->symmetryRule(e_iff_e2));
01688 IF_DEBUG(checkAssumpDebug(d_lastValid, d_assumptions));
01689 TRACE_MSG("search terse", "checkValid => true}");
01690 TRACE("search", "checkValid => true; theorem = ", d_lastValid, "}");
01691 d_core->getCM()->pop();
01692 }
01693 else {
01694 TRACE_MSG("search terse", "checkValid => false}");
01695 TRACE_MSG("search", "checkValid => false; }");
01696 DebugAssert(d_unitConflictClauses.size() == 0, "checkValid(): d_unitConflictClauses postcondition violated");
01697 DebugAssert(d_literals.size() == 0, "checkValid(): d_literals postcondition violated");
01698 DebugAssert(d_factQueue.empty(), "checkValid(): d_factQueue postcondition violated");
01699 }
01700
01701 return r;
01702 }
01703
01704
01705 bool SearchEngineFast::checkValidInternal(const Expr& e)
01706 {
01707 DebugAssert(d_unitConflictClauses.size() == 0, "checkValid(): d_unitConflitClauses precondition violated");
01708 DebugAssert(d_factQueue.empty(), "checkValid(): d_factQueue precondition violated");
01709
01710 TRACE("search", "checkValid(", e, ") {");
01711 TRACE_MSG("search terse", "checkValid() {");
01712
01713 if (!e.getType().isBool()) {
01714 throw TypecheckException
01715 ("checking validity of a non-boolean expression:\n\n "
01716 + e.toString()
01717 + "\n\nwhich has the following type:\n\n "
01718 + e.getType().toString());
01719 }
01720
01721
01722 d_core->getCM()->push();
01723 d_conflictClauseManager.setRestorePoint();
01724 d_bottomScope = scopeLevel();
01725
01726
01727
01728 d_simplifiedThm = d_core->getExprTrans()->preprocess(e.negate());
01729 TRACE("search", "checkValid: simplifiedThm = ", d_simplifiedThm, "");
01730
01731 const Expr& not_e2 = d_simplifiedThm.get().getRHS();
01732 Expr e2 = not_e2.negate();
01733
01734
01735 TRACE_MSG("search terse", "checkValid: Asserting !e: ");
01736 TRACE("search", "checkValid: Asserting !e: ", not_e2, "");
01737 Theorem not_e2_thm;
01738 d_nonlitQueryStart = d_nonLiterals.size();
01739 d_clausesQueryStart = d_clauses.size();
01740 if(d_assumptions.count(not_e2) == 0) {
01741 not_e2_thm = newUserAssumption(not_e2);
01742 } else {
01743 not_e2_thm = d_assumptions[not_e2];
01744 }
01745
01746 d_nonlitQueryEnd = d_nonLiterals.size();
01747 d_clausesQueryEnd = d_clauses.size();
01748
01749
01750
01751
01752 d_splitterCount=0;
01753
01754 return checkValidMain(e2);
01755 }
01756
01757
01758 bool SearchEngineFast::restartInternal(const Expr& e)
01759 {
01760 DebugAssert(d_unitConflictClauses.size() == 0, "restart(): d_unitConflitClauses precondition violated");
01761 DebugAssert(d_factQueue.empty(), "restart(): d_factQueue precondition violated");
01762
01763 TRACE("search", "restart(", e, ") {");
01764 TRACE_MSG("search terse", "restart() {");
01765
01766 if (!e.getType().isBool()) {
01767 throw TypecheckException
01768 ("argument to restart is a non-boolean expression:\n\n "
01769 + e.toString()
01770 + "\n\nwhich has the following type:\n\n "
01771 + e.getType().toString());
01772 }
01773
01774 if (d_bottomScope == 0) {
01775 throw Exception("Call to restart with no current query");
01776 }
01777 d_core->getCM()->popto(d_bottomScope);
01778
01779 Expr e2 = d_simplifiedThm.get().getRHS().negate();
01780
01781 TRACE_MSG("search terse", "restart: Asserting e: ");
01782 TRACE("search", "restart: Asserting e: ", e, "");
01783 if(d_assumptions.count(e) == 0) {
01784 d_core->addFact(newUserAssumption(e));
01785 }
01786
01787 return checkValidMain(e2);
01788 }
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845 void SearchEngineFast::traceConflict(const Theorem& conflictThm) {
01846 TRACE("impl graph", "traceConflict(", conflictThm.getExpr(), ") {");
01847
01848
01849
01850 DebugAssert(conflictThm.getScope() <= scopeLevel(),
01851 "conflictThm.getScope()="+int2string(conflictThm.getScope())
01852 +", scopeLevel()="+int2string(scopeLevel()));
01853 if(conflictThm.getScope() < scopeLevel()) {
01854 int scope(conflictThm.getScope());
01855 if(scope < d_bottomScope) scope = d_bottomScope;
01856 d_decisionEngine->popTo(scope);
01857 }
01858
01859 if(scopeLevel() <= d_bottomScope) {
01860
01861 TRACE_MSG("impl graph", "traceConflict[bottom scope] => }");
01862 return;
01863 }
01864
01865
01866 vector<Theorem> stack;
01867
01868 int maxScope(d_bottomScope);
01869
01870 IF_DEBUG(vector<Theorem> splitters);
01871 TRACE("impl graph", "traceConflict: maxScope = ", maxScope, "");
01872
01873 conflictThm.clearAllFlags();
01874 conflictThm.setExpandFlag(true);
01875 conflictThm.setCachedValue(0);
01876
01877 const Assumptions& assump = conflictThm.getAssumptionsRef();
01878 for(Assumptions::iterator i=assump.begin(),iend=assump.end();i!=iend;++i) {
01879 TRACE("impl graph", "traceConflict: adding ", *i, "");
01880 stack.push_back(*i);
01881 }
01882
01883
01884 IF_DEBUG(Literal maxScopeLit);
01885 while(stack.size() > 0) {
01886 Theorem thm(stack.back());
01887 stack.pop_back();
01888 TRACE("impl graph", "traceConflict: while() { thm = ", thm, "");
01889 if (thm.isFlagged()) {
01890
01891 thm.setCachedValue(thm.getCachedValue() + 1);
01892 TRACE("impl graph", "Found again: ", thm.getExpr().toString(), "");
01893 TRACE("impl graph", "With fanout: ", thm.getCachedValue(), "");
01894 }
01895 else {
01896
01897 thm.setCachedValue(1);
01898 thm.setFlag();
01899 thm.setLitFlag(false);
01900 bool expand(false);
01901 int scope = thm.getScope();
01902 bool isAssump = thm.isAssump();
01903
01904 IF_DEBUG({
01905 int s = scope;
01906 if(thm.isAbsLiteral()) {
01907 Literal l(newLiteral(thm.getExpr()));
01908 if(l.getValue() == 1) s = l.getScope();
01909 }
01910
01911 if(s > maxScope) splitters.clear();
01912 });
01913
01914 if(thm.isAbsLiteral()) {
01915 Literal l(newLiteral(thm.getExpr()));
01916 bool isTrue(l.getValue()==1);
01917 if(isTrue) scope = l.getScope();
01918 if(!isAssump && (!isTrue || scope == scopeLevel()))
01919 expand=true;
01920 else if(scope > d_bottomScope) {
01921 IF_DEBUG(if(scope >= maxScope) splitters.push_back(thm));
01922 thm.setLitFlag(true);
01923 }
01924 } else {
01925 DebugAssert(scope <= d_bottomScope || !isAssump,
01926 "SearchEngineFast::traceConflict: thm = "
01927 +thm.toString());
01928 if(!isAssump && scope > d_bottomScope)
01929 expand=true;
01930 }
01931
01932 if(scope > maxScope) {
01933 maxScope = scope;
01934 IF_DEBUG(maxScopeLit = newLiteral(thm.getExpr()));
01935 TRACE("impl graph", "traceConflict: maxScope = ", maxScope, "");
01936 }
01937
01938 if(expand) {
01939 DebugAssert(!thm.isAssump(),
01940 "traceConflict: thm = "+thm.toString());
01941 thm.setExpandFlag(true);
01942 const Assumptions& assump = thm.getAssumptionsRef();
01943 for(Assumptions::iterator i=assump.begin(),iend=assump.end();
01944 i!=iend; ++i) {
01945 TRACE("impl graph", "traceConflict: adding ", *i, "");
01946 stack.push_back(*i);
01947 }
01948 } else
01949 thm.setExpandFlag(false);
01950 }
01951 TRACE_MSG("impl graph", "traceConflict: end of while() }");
01952 }
01953 IF_DEBUG(if(maxScope != scopeLevel()) conflictThm.printDebug());
01954 DebugAssert(maxScope == scopeLevel(), "maxScope="+int2string(maxScope)
01955 +", scopeLevel()="+int2string(scopeLevel())
01956 +"\n maxScopeLit = "+maxScopeLit.toString());
01957 IF_DEBUG(
01958 if(!(maxScope == d_bottomScope || splitters.size() == 1)) {
01959 conflictThm.printDebug();
01960 ostream& os = debugger.getOS();
01961 os << "\n\nsplitters = [";
01962 for(size_t i=0; i<splitters.size(); ++i)
01963 os << splitters[i] << "\n";
01964 os << "]" << endl;
01965 }
01966 );
01967 DebugAssert(maxScope == d_bottomScope || splitters.size() == 1,
01968 "Wrong number of splitters found at maxScope="
01969 +int2string(maxScope)
01970 +": "+int2string(splitters.size())+" splitters.");
01971 d_lastConflictScope = maxScope;
01972 analyzeUIPs(conflictThm, maxScope);
01973 TRACE_MSG("impl graph", "traceConflict => }");
01974 }