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