00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "search_impl_base.h"
00023 #include "theory.h"
00024 #include "eval_exception.h"
00025 #include "search_rules.h"
00026 #include "variable.h"
00027 #include "command_line_flags.h"
00028 #include "statistics.h"
00029 #include "theorem_manager.h"
00030 #include "expr_transform.h"
00031 #include "assumptions.h"
00032
00033
00034 using namespace std;
00035
00036
00037 namespace CVC3 {
00038
00039
00040 class CoreSatAPI_implBase :public TheoryCore::CoreSatAPI {
00041 SearchImplBase* d_se;
00042 public:
00043 CoreSatAPI_implBase(SearchImplBase* se) : d_se(se) {}
00044 virtual ~CoreSatAPI_implBase() {}
00045 virtual void addLemma(const Theorem& thm, int priority, bool atBottomScope)
00046 { d_se->addFact(thm); }
00047 virtual Theorem addAssumption(const Expr& assump)
00048 { return d_se->newIntAssumption(assump); }
00049 virtual void addSplitter(const Expr& e, int priority)
00050 { d_se->addSplitter(e, priority); }
00051 virtual bool check(const Expr& e);
00052 };
00053
00054 bool CoreSatAPI_implBase::check(const Expr& e)
00055 {
00056 Theorem thm;
00057 int scope = d_se->theoryCore()->getCM()->scopeLevel();
00058 d_se->theoryCore()->getCM()->push();
00059 QueryResult res = d_se->checkValid(e, thm);
00060 d_se->theoryCore()->getCM()->popto(scope);
00061 return res == VALID;
00062 }
00063
00064
00065
00066 }
00067
00068
00069 using namespace CVC3;
00070
00071
00072
00073
00074
00075 SearchImplBase::Splitter::Splitter(const Literal& lit): d_lit(lit) {
00076 d_lit.count()++;
00077 TRACE("Splitter", "Splitter(", d_lit, ")");
00078 }
00079
00080
00081 SearchImplBase::Splitter::Splitter(const SearchImplBase::Splitter& s)
00082 : d_lit(s.d_lit) {
00083 d_lit.count()++;
00084 TRACE("Splitter", "Splitter[copy](", d_lit, ")");
00085 }
00086
00087
00088 SearchImplBase::Splitter&
00089 SearchImplBase::Splitter::operator=(const SearchImplBase::Splitter& s) {
00090 if(this == &s) return *this;
00091 d_lit.count()--;
00092 d_lit = s.d_lit;
00093 d_lit.count()++;
00094 TRACE("Splitter", "Splitter[assign](", d_lit, ")");
00095 return *this;
00096 }
00097
00098
00099 SearchImplBase::Splitter::~Splitter() {
00100 d_lit.count()--;
00101 TRACE("Splitter", "~Splitter(", d_lit, ")");
00102 }
00103
00104
00105
00106
00107 SearchImplBase::SearchImplBase(TheoryCore* core)
00108 : SearchEngine(core),
00109 d_bottomScope(core->getCM()->getCurrentContext()),
00110 d_dpSplitters(core->getCM()->getCurrentContext()),
00111 d_lastValid(d_commonRules->trueTheorem()),
00112 d_assumptions(core->getCM()->getCurrentContext()),
00113 d_cnfCache(core->getCM()->getCurrentContext()),
00114 d_cnfVars(core->getCM()->getCurrentContext()),
00115 d_cnfOption(&(core->getFlags()["cnf"].getBool())),
00116 d_ifLiftOption(&(core->getFlags()["iflift"].getBool())),
00117 d_ignoreCnfVarsOption(&(core->getFlags()["ignore-cnf-vars"].getBool())),
00118 d_origFormulaOption(&(core->getFlags()["orig-formula"].getBool())),
00119 d_enqueueCNFCache(core->getCM()->getCurrentContext()),
00120 d_applyCNFRulesCache(core->getCM()->getCurrentContext()),
00121 d_replaceITECache(core->getCM()->getCurrentContext())
00122 {
00123 d_vm = new VariableManager(core->getCM(), d_rules,
00124 core->getFlags()["mm"].getString());
00125 IF_DEBUG(d_assumptions.setName("CDList[SearchImplBase::d_assumptions]");)
00126 d_coreSatAPI_implBase = new CoreSatAPI_implBase(this);
00127 core->registerCoreSatAPI(d_coreSatAPI_implBase);
00128 }
00129
00130
00131
00132 SearchImplBase::~SearchImplBase()
00133 {
00134 delete d_coreSatAPI_implBase;
00135 delete d_vm;
00136 }
00137
00138
00139
00140
00141 Theorem SearchImplBase::newUserAssumption(const Expr& e) {
00142 Theorem thm;
00143 CDMap<Expr,Theorem>::iterator i(d_assumptions.find(e));
00144 IF_DEBUG(if(debugger.trace("search verbose")) {
00145 ostream& os(debugger.getOS());
00146 os << "d_assumptions = [";
00147 for(CDMap<Expr,Theorem>::iterator i=d_assumptions.begin(),
00148 iend=d_assumptions.end(); i!=iend; ++i) {
00149 debugger.getOS() << "(" << (*i).first << " => " << (*i).second << "), ";
00150 }
00151 os << "]" << endl;
00152 })
00153 if(i!=d_assumptions.end()) {
00154 TRACE("search verbose", "newUserAssumption(", e,
00155 "): assumption already exists");
00156 } else {
00157 thm = d_commonRules->assumpRule(e);
00158 d_assumptions[e] = thm;
00159 e.setUserAssumption();
00160 TRACE("search verbose", "newUserAssumption(", thm,
00161 "): created new assumption");
00162 }
00163 if (!thm.isNull()) d_core->addFact(d_core->getExprTrans()->preprocess(thm));
00164 return thm;
00165 }
00166
00167
00168
00169
00170 Theorem SearchImplBase::newIntAssumption(const Expr& e) {
00171 Theorem thm = d_commonRules->assumpRule(e);
00172 Expr atom = e.isNot() ? e[0] : e;
00173 thm.setQuantLevel(theoryCore()->getQuantLevelForTerm(atom));
00174 newIntAssumption(thm);
00175 return thm;
00176 }
00177
00178
00179 void SearchImplBase::newIntAssumption(const Theorem& thm) {
00180 DebugAssert(!d_assumptions.count(thm.getExpr()),
00181 "newIntAssumption: repeated assertion: "+thm.getExpr().toString());
00182 d_assumptions[thm.getExpr()] = thm;
00183 thm.getExpr().setIntAssumption();
00184 TRACE("search verbose", "newIntAssumption(", thm,
00185 "): new assumption");
00186 }
00187
00188
00189 void SearchImplBase::getUserAssumptions(vector<Expr>& assumptions)
00190 {
00191 for(CDMap<Expr,Theorem>::orderedIterator i=d_assumptions.orderedBegin(),
00192 iend=d_assumptions.orderedEnd(); i!=iend; ++i)
00193 if ((*i).first.isUserAssumption()) assumptions.push_back((*i).first);
00194 }
00195
00196
00197 void SearchImplBase::getInternalAssumptions(std::vector<Expr>& assumptions)
00198 {
00199 for(CDMap<Expr,Theorem>::orderedIterator i=d_assumptions.orderedBegin(),
00200 iend=d_assumptions.orderedEnd(); i!=iend; ++i)
00201 if ((*i).first.isIntAssumption()) assumptions.push_back((*i).first);
00202 }
00203
00204
00205 void SearchImplBase::getAssumptions(std::vector<Expr>& assumptions)
00206 {
00207 for(CDMap<Expr,Theorem>::orderedIterator i=d_assumptions.orderedBegin(),
00208 iend=d_assumptions.orderedEnd(); i!=iend; ++i)
00209 assumptions.push_back((*i).first);
00210 }
00211
00212
00213 bool SearchImplBase::isAssumption(const Expr& e) {
00214 return d_assumptions.count(e) > 0;
00215 }
00216
00217
00218 void SearchImplBase::addCNFFact(const Theorem& thm, bool fromCore) {
00219 TRACE("addCNFFact", "addCNFFact(", thm.getExpr(), ") {");
00220 if(thm.isAbsLiteral()) {
00221 addLiteralFact(thm);
00222
00223 if(!fromCore) d_core->enqueueFact(thm);
00224 } else {
00225 addNonLiteralFact(thm);
00226 }
00227 TRACE_MSG("addCNFFact", "addCNFFact => }");
00228 }
00229
00230
00231 void SearchImplBase::addFact(const Theorem& thm) {
00232 TRACE("search addFact", "SearchImplBase::addFact(", thm.getExpr(), ") {");
00233 if(*d_cnfOption)
00234 enqueueCNF(thm);
00235 else
00236 addCNFFact(thm, true);
00237 TRACE_MSG("search addFact", "SearchImplBase::addFact => }");
00238 }
00239
00240
00241 void SearchImplBase::addSplitter(const Expr& e, int priority) {
00242 DebugAssert(e.isAbsLiteral(), "SearchImplBase::addSplitter("+e.toString()+")");
00243 d_dpSplitters.push_back(Splitter(newLiteral(e)));
00244 }
00245
00246
00247 void SearchImplBase::getCounterExample(vector<Expr>& assertions, bool inOrder)
00248 {
00249 if(!d_core->getTM()->withAssumptions())
00250 throw EvalException
00251 ("Method getCounterExample() (or command COUNTEREXAMPLE) cannot be used\n"
00252 " without assumptions activated");
00253 if(!d_lastValid.isNull())
00254 throw EvalException
00255 ("Method getCounterExample() (or command COUNTEREXAMPLE)\n"
00256 " must be called only after failed QUERY");
00257 getInternalAssumptions(assertions);
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 }
00279
00280
00281 Proof
00282 SearchImplBase::getProof()
00283 {
00284 if(!d_core->getTM()->withProof())
00285 throw EvalException
00286 ("DUMP_PROOF cannot be used without proofs activated");
00287 if(d_lastValid.isNull())
00288 throw EvalException
00289 ("DUMP_PROOF must be called only after successful QUERY");
00290
00291 if(d_lastValid.isNull()) return Proof();
00292 return d_lastValid.getProof();
00293 }
00294
00295
00296 const Assumptions&
00297 SearchImplBase::getAssumptionsUsed()
00298 {
00299 if(!d_core->getTM()->withAssumptions())
00300 throw EvalException
00301 ("DUMP_ASSUMPTIONS cannot be used without assumptions activated");
00302 if(d_lastValid.isNull())
00303 throw EvalException
00304 ("DUMP_ASSUMPTIONS must be called only after successful QUERY");
00305
00306 if(d_lastValid.isNull()) return Assumptions::emptyAssump();
00307 return d_lastValid.getAssumptionsRef();
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317 void SearchImplBase::processResult(const Theorem& res, const Expr& e)
00318 {
00319
00320 DebugAssert(res.isNull() || res.getExpr().isFalse(),
00321 "processResult: bad input"
00322 + res.toString());
00323 if(res.isNull()) {
00324
00325
00326
00327 d_lastValid = Theorem();
00328
00329 d_lastCounterExample.erase(!e);
00330 if (e.isNot()) d_lastCounterExample.erase(e[0]);
00331 } else {
00332
00333 Theorem res2 =
00334 d_rules->eliminateSkolemAxioms(res, d_commonRules->getSkolemAxioms());
00335 if(e.isNot())
00336 d_lastValid = d_rules->negIntro(e, res2);
00337 else
00338 d_lastValid = d_rules->proofByContradiction(e, res2);
00339 d_lastCounterExample.clear();
00340 }
00341 }
00342
00343
00344 QueryResult SearchImplBase::checkValid(const Expr& e, Theorem& result) {
00345 d_commonRules->clearSkolemAxioms();
00346 QueryResult qres = checkValidInternal(e);
00347 result = d_lastValid;
00348 return qres;
00349 }
00350
00351
00352 QueryResult SearchImplBase::restart(const Expr& e, Theorem& result) {
00353 QueryResult qres = restartInternal(e);
00354 result = d_lastValid;
00355 return qres;
00356 }
00357
00358
00359 void
00360 SearchImplBase::enqueueCNF(const Theorem& beta) {
00361 TRACE("mycnf", "enqueueCNF(", beta, ") {");
00362 if(*d_origFormulaOption)
00363 addCNFFact(beta);
00364
00365 enqueueCNFrec(beta);
00366 TRACE_MSG("mycnf", "enqueueCNF => }");
00367 }
00368
00369
00370 void
00371 SearchImplBase::enqueueCNFrec(const Theorem& beta) {
00372 Theorem theta = beta;
00373
00374 TRACE("mycnf","enqueueCNFrec(", theta.getExpr(), ") { ");
00375 TRACE("cnf-clauses", "enqueueCNF call", theta.getExpr(), "");
00376
00377 DebugAssert(theta.getScope() <= scopeLevel(),
00378 "\n theta.getScope()="+int2string(theta.getScope())
00379 +"\n scopeLevel="+int2string(scopeLevel())
00380 +"\n e = "+theta.getExpr().toString());
00381
00382 Expr thetaExpr = theta.getExpr();
00383
00384 if(d_enqueueCNFCache.count(thetaExpr) > 0) {
00385 TRACE_MSG("mycnf", "enqueueCNFrec[cached] => }");
00386 return;
00387 }
00388
00389 d_enqueueCNFCache[thetaExpr] = true;
00390
00391
00392 while(thetaExpr.isNot() && thetaExpr[0].isNot()) {
00393 theta = d_commonRules->notNotElim(theta);
00394 thetaExpr = theta.getExpr();
00395
00396 d_enqueueCNFCache[thetaExpr] = true;
00397 }
00398
00399
00400 if(thetaExpr.isPropLiteral()) {
00401 theta = d_commonRules->iffMP(theta, replaceITE(thetaExpr));
00402 DebugAssert(!*d_ifLiftOption || theta.isAbsLiteral(),
00403 "Must be a literal: theta = "
00404 +theta.getExpr().toString());
00405 addCNFFact(theta);
00406 TRACE_MSG("mycnf", "enqueueCNFrec[literal] => }");
00407 TRACE("cnf-clauses", "literal with proofs(", theta.getExpr(), ")");
00408 return;
00409 }
00410
00411 thetaExpr = theta.getExpr();
00412
00413 switch(thetaExpr.getKind()) {
00414 case AND:
00415
00416 for(int i=0; i<thetaExpr.arity(); i++)
00417 enqueueCNFrec(d_commonRules->andElim(theta, i));
00418 TRACE_MSG("mycnf", "enqueueCNFrec[AND] => }");
00419 return;
00420 case OR: {
00421
00422
00423 bool cnf(true);
00424 TRACE("bv mycnf", "enqueueCNFrec[OR] ( ", theta.getExpr().toString(), ")");
00425 for(Expr::iterator i=thetaExpr.begin(),iend=thetaExpr.end();
00426 i!=iend && cnf; i++) {
00427 if(!(*i).isPropLiteral())
00428 cnf = false;
00429 }
00430 if(cnf) {
00431 vector<Theorem> thms;
00432 vector<unsigned int> changed;
00433 unsigned int cc=0;
00434 for(Expr::iterator i=thetaExpr.begin(),iend=thetaExpr.end();
00435 i!=iend; i++,cc++) {
00436 Theorem thm = replaceITE(*i);
00437 if(thm.getLHS() != thm.getRHS()) {
00438 thms.push_back(thm);
00439 changed.push_back(cc);
00440 }
00441 }
00442 if(changed.size() > 0) {
00443 Theorem rewrite =
00444 d_commonRules->substitutivityRule(theta.getExpr(), changed, thms);
00445 theta = d_commonRules->iffMP(theta, rewrite);
00446 }
00447 addCNFFact(theta);
00448 TRACE_MSG("mycnf", "enqueueCNFrec[cnf] => }");
00449 return;
00450 }
00451 break;
00452 }
00453 case IFF: {
00454 const Expr& t0 = thetaExpr[0];
00455 const Expr& t1 = thetaExpr[1];
00456 if(t1.isPropLiteral()) {
00457 if(!t1.isAbsLiteral())
00458 theta = d_commonRules->transitivityRule(theta, replaceITE(t1));
00459 applyCNFRules(theta);
00460 return;
00461 } else if(thetaExpr[0].isPropLiteral()) {
00462 theta = d_commonRules->symmetryRule(theta);
00463 if(!t0.isAbsLiteral())
00464 theta = d_commonRules->transitivityRule(theta, replaceITE(t0));
00465 applyCNFRules(theta);
00466 return;
00467 }
00468 break;
00469 }
00470 case ITE:
00471 if(thetaExpr[0].isPropLiteral() && thetaExpr[1].isPropLiteral()
00472 && thetaExpr[2].isPropLiteral()) {
00473
00474 vector<Theorem> thms;
00475 vector<unsigned int> changed;
00476 for(int c=0, cend=thetaExpr.arity(); c<cend; ++c) {
00477 Theorem thm = replaceITE(thetaExpr[c]);
00478 if(thm.getLHS() != thm.getRHS()) {
00479 DebugAssert(!*d_ifLiftOption || thm.getRHS().isAbsLiteral(),
00480 "thm = "+thm.getExpr().toString());
00481 thms.push_back(thm);
00482 changed.push_back(c);
00483 }
00484 }
00485 if(changed.size() > 0) {
00486 Theorem rewrite =
00487 d_commonRules->substitutivityRule(theta.getExpr(), changed, thms);
00488 theta = d_commonRules->iffMP(theta, rewrite);
00489 }
00490
00491 Theorem thm = d_rules->iteToClauses(theta);
00492 DebugAssert(thm.getExpr().isAnd() && thm.getExpr().arity()==2,
00493 "enqueueCNFrec [ITE over literals]\n thm = "
00494 +thm.getExpr().toString());
00495 addCNFFact(d_commonRules->andElim(thm, 0));
00496 addCNFFact(d_commonRules->andElim(thm, 1));
00497 return;
00498 }
00499 break;
00500 default:
00501 break;
00502 }
00503
00504
00505 Theorem res = findInCNFCache(theta.getExpr());
00506 if(!res.isNull()) {
00507 Theorem thm = d_commonRules->iffMP(theta, res);
00508 DebugAssert(thm.isAbsLiteral(), "thm = "+thm.getExpr().toString());
00509 addCNFFact(thm);
00510 TRACE("cnf-clauses", "enqueueCNFrec call[cache hit]:(",
00511 thm.getExpr(), ")");
00512 applyCNFRules(res);
00513 TRACE_MSG("mycnf", "enqueueCNFrec[cached] => }");
00514 return;
00515 }
00516
00517
00518 Theorem result;
00519
00520 result = d_commonRules->varIntroSkolem(theta.getExpr());
00521
00522 TRACE("mycnf", "enqueueCNFrec: varIntroSkolem => ", result.getExpr(),
00523 " @ "+int2string(result.getScope())
00524 +" (current="+int2string(scopeLevel())+")");
00525
00526
00527
00528 TRACE("mycnf", "enqueueCNFrec: skolemize => ", result.getExpr(),
00529 " @ "+int2string(result.getScope())
00530 +" (current="+int2string(scopeLevel())+")");
00531 DebugAssert(result.isRewrite(),
00532 "SearchImplBase::CNF(): result = "+result.toString());
00533 DebugAssert(!result.getLHS().isPropLiteral() &&
00534 result.getRHS().isPropLiteral(),
00535 "SearchImplBase::CNF(): result = "+result.toString());
00536 DebugAssert(result.getLHS() == theta.getExpr(),
00537 "SearchImplBase::CNF(): result = "+result.toString()
00538 +"\n theta = "+theta.toString());
00539
00540
00541 Theorem var(d_commonRules->iffMP(theta, result));
00542
00543 d_cnfVars[var.getExpr()] = true;
00544 TRACE("mycnf", "enqueueCNFrec: theta = ", theta.getExpr(),
00545 " @ "+int2string(theta.getScope())
00546 +" (current="+int2string(scopeLevel())+")");
00547 TRACE("mycnf", "enqueueCNFrec: var = ", var.getExpr(),
00548 " @ "+int2string(var.getScope())
00549 +" (current="+int2string(scopeLevel())+")");
00550 DebugAssert(var.isAbsLiteral(), "var = "+var.getExpr().toString());
00551 addCNFFact(var);
00552
00553 addToCNFCache(result);
00554 applyCNFRules(result);
00555 TRACE_MSG("mycnf", "enqueueCNFrec => }");
00556 }
00557
00558
00559
00560
00561
00562 void
00563 SearchImplBase::applyCNFRules(const Theorem& thm) {
00564 TRACE("mycnf", "applyCNFRules(", thm.getExpr(), ") { ");
00565
00566 Theorem result = thm;
00567 DebugAssert(result.isRewrite(),
00568 "SearchImplBase::applyCNFRules: input must be an iff: " +
00569 result.getExpr().toString());
00570 Expr lhs = result.getLHS();
00571 Expr rhs = result.getRHS();
00572 DebugAssert(rhs.isAbsLiteral(),
00573 "SearchImplBase::applyCNFRules: rhs of input must be literal: " +
00574 result.getExpr().toString());
00575
00576
00577 while(result.getLHS().isNot())
00578 result = d_commonRules->iffContrapositive(result);
00579 lhs = result.getLHS();
00580 rhs = result.getRHS();
00581
00582 CDMap<Expr,bool>::iterator it = d_applyCNFRulesCache.find(lhs);
00583 if(it == d_applyCNFRulesCache.end())
00584 d_applyCNFRulesCache[lhs] = true;
00585 else {
00586 TRACE_MSG("mycnf","applyCNFRules[temp cache] => }");
00587 return;
00588 }
00589
00590
00591 if(lhs.isPropLiteral()) {
00592 if(!lhs.isAbsLiteral()) {
00593 Theorem replaced = d_commonRules->symmetryRule(replaceITE(lhs));
00594 result = d_commonRules->transitivityRule(replaced, result);
00595 lhs = result.getLHS();
00596 DebugAssert(rhs == result.getRHS(),
00597 "applyCNFRules [literal lhs]\n result = "
00598 +result.getExpr().toString()
00599 +"\n rhs = "+rhs.toString());
00600 }
00601 Theorem thm = d_rules->iffToClauses(result);
00602 DebugAssert(thm.getExpr().isAnd() && thm.getExpr().arity()==2,
00603 "applyCNFRules [literal lhs]\n thm = "
00604 +thm.getExpr().toString());
00605 addCNFFact(d_commonRules->andElim(thm, 0));
00606 addCNFFact(d_commonRules->andElim(thm, 1));
00607 return;
00608 }
00609
00610
00611 vector<unsigned> changed;
00612 vector<Theorem> substitutions;
00613 int c=0;
00614 for(Expr::iterator j = lhs.begin(), jend = lhs.end(); j!=jend; ++c,++j) {
00615 const Expr& phi = *j;
00616 if(!phi.isPropLiteral()) {
00617 Theorem phiIffVar = findInCNFCache(phi);
00618 if(phiIffVar.isNull()) {
00619
00620 phiIffVar = d_commonRules->varIntroSkolem(phi);
00621 addToCNFCache(phiIffVar);
00622 }
00623 DebugAssert(phiIffVar.isRewrite(),
00624 "SearchImplBase::applyCNFRules: result = " +
00625 result.toString());
00626 DebugAssert(phi == phiIffVar.getLHS(),
00627 "SearchImplBase::applyCNFRules:\n phi = " +
00628 phi.toString()
00629 + "\n\n phiIffVar = " + phiIffVar.toString());
00630 DebugAssert(phiIffVar.getRHS().isAbsLiteral(),
00631 "SearchImplBase::applyCNFRules: phiIffVar = " +
00632 phiIffVar.toString());
00633 changed.push_back(c);
00634 substitutions.push_back(phiIffVar);
00635 applyCNFRules(phiIffVar);
00636 }
00637 }
00638 if(changed.size() > 0) {
00639 Theorem subst =
00640 d_commonRules->substitutivityRule(lhs, changed, substitutions);
00641 subst = d_commonRules->symmetryRule(subst);
00642 result = d_commonRules->transitivityRule(subst, result);
00643 }
00644
00645 switch(result.getLHS().getKind()) {
00646 case AND:
00647 result = d_rules->andCNFRule(result);
00648 break;
00649 case OR:
00650 result = d_rules->orCNFRule(result);
00651 break;
00652 case IFF:
00653 result = d_rules->iffCNFRule(result);
00654 break;
00655 case IMPLIES:
00656 result = d_rules->impCNFRule(result);
00657 break;
00658 case ITE:
00659 result = d_rules->iteCNFRule(result);
00660 break;
00661 default:
00662 DebugAssert(false,
00663 "SearchImplBase::applyCNFRules: "
00664 "the input operator must be and|or|iff|imp|ite\n result = " +
00665 result.getLHS().toString());
00666 break;
00667 }
00668
00669
00670 Theorem clauses(result);
00671
00672
00673 DebugAssert(!clauses.isNull(), "Oops!..");
00674 DebugAssert(clauses.getExpr().isAnd(), "clauses = "
00675 +clauses.getExpr().toString());
00676
00677
00678
00679 for(int i=0, iend=clauses.getExpr().arity(); i<iend; ++i) {
00680 Theorem clause(d_commonRules->andElim(clauses,i));
00681 addCNFFact(clause);
00682 }
00683 TRACE_MSG("mycnf","applyCNFRules => }");
00684 }
00685
00686
00687 bool SearchImplBase::isClause(const Expr& e) {
00688 if(e.isAbsLiteral()) return true;
00689 if(!e.isOr()) return false;
00690
00691 bool cnf(true);
00692 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend && cnf; ++i)
00693 cnf = (*i).isAbsLiteral();
00694 return cnf;
00695 }
00696
00697
00698 bool
00699 SearchImplBase::isPropClause(const Expr& e) {
00700 if(e.isPropLiteral()) return true;
00701 if(!e.isOr()) return false;
00702
00703 bool cnf(true);
00704 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend && cnf; ++i)
00705 cnf = (*i).isPropLiteral();
00706 return cnf;
00707 }
00708
00709
00710 bool
00711 SearchImplBase::isGoodSplitter(const Expr& e) {
00712 if(!*d_ignoreCnfVarsOption) return true;
00713 TRACE("isGoodSplitter", "isGoodSplitter(", e, ") {");
00714
00715 const Expr& var = e.isNot()? e[0] : e;
00716 bool res(!isCNFVar(var));
00717 TRACE("isGoodSplitter", "isGoodSplitter => ", res? "true" : "false", " }");
00718 return res;
00719 }
00720
00721
00722 void
00723 SearchImplBase::addToCNFCache(const Theorem& thm) {
00724 TRACE("mycnf", "addToCNFCache(", thm.getExpr(), ")");
00725
00726 d_core->getStatistics().counter("CNF New Vars")++;
00727
00728 Theorem result = thm;
00729 DebugAssert(result.isRewrite(),
00730 "SearchImplBase::addToCNFCache: input must be an iff: " +
00731 result.getExpr().toString());
00732
00733 d_cnfVars[thm.getRHS()] = true;
00734
00735 Theorem t(thm);
00736 Expr phi = thm.getLHS();
00737 while(phi.isNot()) {
00738 t = d_commonRules->iffContrapositive(thm);
00739 phi = phi[0];
00740 }
00741 DebugAssert(d_cnfCache.count(phi) == 0,
00742 "thm = "+thm.getExpr().toString() +
00743 "\n t = "+ t.getExpr().toString());
00744
00745 d_cnfCache.insert(phi, t, d_bottomScope);
00746 }
00747
00748
00749 Theorem
00750 SearchImplBase::findInCNFCache(const Expr& e) {
00751 TRACE("mycnf", "findInCNFCache(", e, ") { ");
00752 Expr phi(e);
00753
00754 int numNegs(0);
00755
00756 while(phi.isNot()) {
00757 phi = phi[0]; numNegs++;
00758 }
00759 CDMap<Expr,Theorem>::iterator it = d_cnfCache.find(phi);
00760 if(it != d_cnfCache.end()) {
00761
00762 d_core->getStatistics().counter("CNF cache hits")++;
00763 Theorem thm = (*it).second;
00764
00765 DebugAssert(thm.isRewrite() && thm.getLHS() == phi,
00766 "SearchImplBase::findInCNFCache: thm must be an iff: " +
00767 thm.getExpr().toString());
00768
00769
00770
00771
00772 if(numNegs % 2 != 0) {
00773 thm = d_commonRules->iffContrapositive(thm);
00774 numNegs--;
00775 }
00776 for(; numNegs > 0; numNegs-=2) {
00777 Theorem t = d_commonRules->rewriteNotNot(!!(thm.getLHS()));
00778 thm = d_commonRules->transitivityRule(t,thm);
00779 }
00780
00781 DebugAssert(numNegs == 0, "numNegs = "+int2string(numNegs));
00782 TRACE("mycnf", "findInCNFCache => ", thm.getExpr(), " }");
00783 return thm;
00784 }
00785 TRACE_MSG("mycnf", "findInCNFCache => null }");
00786 return Theorem();
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 Theorem
00804 SearchImplBase::replaceITE(const Expr& e) {
00805 TRACE("replaceITE","replaceITE(", e, ") { ");
00806 Theorem res;
00807
00808 CDMap<Expr,Theorem>::iterator i=d_replaceITECache.find(e),
00809 iend=d_replaceITECache.end();
00810 if(i!=iend) {
00811 TRACE("replaceITE", "replaceITE[cached] => ", (*i).second, " }");
00812 return (*i).second;
00813 }
00814
00815 if(e.isAbsLiteral())
00816 res = d_core->rewriteLiteral(e);
00817 else
00818 res = d_commonRules->reflexivityRule(e);
00819
00820
00821
00822
00823
00824 if(!res.getRHS().isPropLiteral()) {
00825 Theorem varThm(findInCNFCache(res.getRHS()));
00826 if(varThm.isNull()) {
00827 varThm = d_commonRules->varIntroSkolem(res.getRHS());
00828 Theorem var;
00829 if(res.isRewrite())
00830 var = d_commonRules->transitivityRule(res,varThm);
00831 else
00832 var = d_commonRules->iffMP(res,varThm);
00833
00834
00835 addToCNFCache(varThm);
00836 }
00837 applyCNFRules(varThm);
00838
00839 res = d_commonRules->transitivityRule(res, varThm);
00840 }
00841
00842 d_replaceITECache[e] = res;
00843
00844 TRACE("replaceITE", "replaceITE => ", res, " }");
00845 return res;
00846 }