00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #define _CVC3_TRUSTED_
00025
00026
00027 #include "common_theorem_producer.h"
00028
00029
00030 using namespace CVC3;
00031 using namespace std;
00032
00033
00034
00035 CommonProofRules* TheoremManager::createProofRules() {
00036 return new CommonTheoremProducer(this);
00037 }
00038
00039
00040 CommonTheoremProducer::CommonTheoremProducer(TheoremManager* tm)
00041 : TheoremProducer(tm),
00042 d_skolemized_thms(tm->getCM()->getCurrentContext()),
00043 d_skolemVars(tm->getCM()->getCurrentContext())
00044 {}
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 Theorem3
00055 CommonTheoremProducer::queryTCC(const Theorem& phi, const Theorem& D_phi) {
00056 Proof pf;
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 Assumptions a = phi.getAssumptionsRef();
00067 a.add(D_phi);
00068 if(withProof()) {
00069 vector<Expr> args;
00070 vector<Proof> pfs;
00071 args.push_back(phi.getExpr());
00072 args.push_back(D_phi.getExpr());
00073 pfs.push_back(phi.getProof());
00074 pfs.push_back(D_phi.getProof());
00075 pf = newPf("queryTCC", args, pfs);
00076 }
00077 return newTheorem3(phi.getExpr(), a, pf);
00078 }
00079
00080
00081
00082
00083
00084 Theorem3
00085 CommonTheoremProducer::implIntro3(const Theorem3& phi,
00086 const std::vector<Expr>& assump,
00087 const vector<Theorem>& tccs) {
00088 bool checkProofs(CHECK_PROOFS);
00089
00090 if(checkProofs) {
00091 CHECK_SOUND(withAssumptions(),
00092 "implIntro3: called while running without assumptions");
00093 }
00094
00095 const Assumptions& phiAssump = phi.getAssumptionsRef();
00096
00097 if(checkProofs) {
00098 CHECK_SOUND(assump.size() == tccs.size(),
00099 "implIntro3: number of assumptions ("
00100 +int2string(assump.size())+") and number of TCCs ("
00101 +int2string(tccs.size())
00102 +") does not match");
00103 for(size_t i=0; i<assump.size(); i++) {
00104 const Theorem& thm = phiAssump[assump[i]];
00105 CHECK_SOUND(!thm.isNull() && thm.isAssump(),
00106 "implIntro3: this is not an assumption of phi:\n\n"
00107 " a["+int2string(i)+"] = "+assump[i].toString()
00108 +"\n\n phi = "+phi.getExpr().toString());
00109
00110
00111
00112
00113
00114
00115
00116 }
00117 }
00118
00119
00120 if(assump.size() == 0) return phi;
00121
00122 Assumptions a(phiAssump - assump);
00123 Assumptions b(tccs);
00124 a.add(b);
00125 Proof pf;
00126 if(withProof()) {
00127 vector<Proof> u;
00128 for(vector<Expr>::const_iterator i=assump.begin(), iend=assump.end();
00129 i!=iend; ++i) {
00130 const Theorem& t = phiAssump[*i];
00131 u.push_back(t.getProof());
00132 }
00133
00134
00135
00136 vector<Expr> args;
00137 vector<Proof> pfs;
00138 args.push_back(phi.getExpr());
00139 args.insert(args.end(), assump.begin(), assump.end());
00140 for(vector<Theorem>::const_iterator i=tccs.begin(), iend=tccs.end();
00141 i!=iend; ++i) {
00142 args.push_back(i->getExpr());
00143 pfs.push_back(i->getProof());
00144 }
00145
00146 pfs.push_back(newPf(u, assump, phi.getProof()));
00147 pf = newPf("impl_intro_3", args, pfs);
00148 }
00149 Expr conj(andExpr(assump));
00150 return newTheorem3(conj.impExpr(phi.getExpr()), a, pf);
00151 }
00152
00153
00154 Theorem CommonTheoremProducer::assumpRule(const Expr& e, int scope) {
00155
00156 Proof pf;
00157 if(withProof()) pf = newLabel(e);
00158 return newAssumption(e, pf, scope);
00159 }
00160
00161
00162 Theorem CommonTheoremProducer::reflexivityRule(const Expr& a) {
00163 return newReflTheorem(a);
00164 }
00165
00166
00167
00168 Theorem CommonTheoremProducer::rewriteReflexivity(const Expr& t) {
00169 if(CHECK_PROOFS)
00170 CHECK_SOUND((t.isEq() || t.isIff()) && t[0] == t[1],
00171 "rewriteReflexivity: wrong expression: "
00172 + t.toString());
00173 Proof pf;
00174 if(withProof()) {
00175 if(t.isEq()) {
00176 DebugAssert(!t[0].getType().isNull(),
00177 "rewriteReflexivity: t[0] has no type: "
00178 + t[0].toString());
00179 pf = newPf("rewrite_eq_refl", t[0].getType().getExpr(), t[0]);
00180 } else
00181 pf = newPf("rewrite_iff_refl", t[0]);
00182 }
00183 return newRWTheorem(t, d_em->trueExpr(), Assumptions::emptyAssump(), pf);
00184 }
00185
00186
00187 Theorem CommonTheoremProducer::symmetryRule(const Theorem& a1_eq_a2) {
00188 if(CHECK_PROOFS)
00189 CHECK_SOUND(a1_eq_a2.isRewrite(),
00190 ("CVC3::CommonTheoremProducer: "
00191 "theorem is not an equality or iff:\n "
00192 + a1_eq_a2.getExpr().toString()).c_str());
00193 const Expr& a1 = a1_eq_a2.getLHS();
00194 const Expr& a2 = a1_eq_a2.getRHS();
00195
00196 Proof pf;
00197
00198
00199
00200
00201 if(a1 == a2) return reflexivityRule(a1);
00202
00203 if(withProof()) {
00204 Type t = a1.getType();
00205
00206 IF_DEBUG(a1_eq_a2.getExpr().getType();)
00207 bool isEquality = !t.isBool();
00208 if(isEquality) {
00209 vector<Expr> args;
00210 args.push_back(t.getExpr());
00211 args.push_back(a1);
00212 args.push_back(a2);
00213 pf = newPf("eq_symm", args, a1_eq_a2.getProof());
00214 } else
00215 pf = newPf("iff_symm", a1, a2, a1_eq_a2.getProof());
00216 }
00217 return newRWTheorem(a2, a1, Assumptions(a1_eq_a2), pf);
00218 }
00219
00220
00221 Theorem CommonTheoremProducer::rewriteUsingSymmetry(const Expr& a1_eq_a2) {
00222 bool isIff = a1_eq_a2.isIff();
00223 if(CHECK_PROOFS)
00224 CHECK_SOUND(a1_eq_a2.isEq() || isIff, "rewriteUsingSymmetry precondition violated");
00225 const Expr& a1 = a1_eq_a2[0];
00226 const Expr& a2 = a1_eq_a2[1];
00227
00228 if(a1 == a2) return reflexivityRule(a1_eq_a2);
00229
00230 Proof pf;
00231 if(withProof()) {
00232 Type t = a1.getType();
00233 DebugAssert(!t.isNull(),
00234 "rewriteUsingSymmetry: a1 has no type: " + a1.toString());
00235 if(isIff)
00236 pf = newPf("rewrite_iff_symm", a1, a2);
00237 else {
00238 pf = newPf("rewrite_eq_symm", t.getExpr(), a1, a2);
00239 }
00240 }
00241 return newRWTheorem(a1_eq_a2, isIff ? a2.iffExpr(a1) : a2.eqExpr(a1), Assumptions::emptyAssump(), pf);
00242 }
00243
00244
00245 Theorem CommonTheoremProducer::transitivityRule(const Theorem& a1_eq_a2,
00246 const Theorem& a2_eq_a3) {
00247 DebugAssert(!a1_eq_a2.isNull(), "transitivityRule()");
00248 DebugAssert(!a2_eq_a3.isNull(), "transitivityRule()");
00249 if(CHECK_PROOFS) {
00250 CHECK_SOUND(a1_eq_a2.isRewrite() && a2_eq_a3.isRewrite(),
00251 "CVC3::CommonTheoremProducer::transitivityRule:\n "
00252 "Wrong premises: first = "
00253 + a1_eq_a2.getExpr().toString() + ", second = "
00254 + a2_eq_a3.getExpr().toString());
00255 CHECK_SOUND(a1_eq_a2.getRHS() == a2_eq_a3.getLHS(),
00256 "CVC3::CommonTheoremProducer::transitivityRule:\n "
00257 "Wrong premises: first = "
00258 + a1_eq_a2.getExpr().toString() + ", second = "
00259 + a2_eq_a3.getExpr().toString());
00260 }
00261 const Expr& a1 = a1_eq_a2.getLHS();
00262 const Expr& a2 = a1_eq_a2.getRHS();
00263 const Expr& a3 = a2_eq_a3.getRHS();
00264
00265
00266
00267
00268
00269 if(a1 == a3) return reflexivityRule(a1);
00270
00271 if(a1 == a2) return a2_eq_a3;
00272 if(a2 == a3) return a1_eq_a2;
00273
00274
00275
00276
00277
00278 Proof pf;
00279 Assumptions a(a1_eq_a2, a2_eq_a3);
00280
00281 if(withProof()) {
00282 Type t = a1.getType();
00283 bool isEquality = (!t.isBool());
00284 string name((isEquality)? "eq_trans" : "iff_trans");
00285 vector<Expr> args;
00286 vector<Proof> pfs;
00287 DebugAssert(!t.isNull(), "transitivityRule: "
00288 "Type is not computed for a1: " + a1.toString());
00289
00290 if(isEquality) args.push_back(t.getExpr());
00291 args.push_back(a1);
00292 args.push_back(a2);
00293 args.push_back(a3);
00294 pfs.push_back(a1_eq_a2.getProof());
00295 pfs.push_back(a2_eq_a3.getProof());
00296 pf = newPf(name, args, pfs);
00297 }
00298 return newRWTheorem(a1, a3, a, pf);
00299 }
00300
00301
00302 Theorem CommonTheoremProducer::substitutivityRule(const Expr& e,
00303 const Theorem& thm) {
00304 IF_DEBUG
00305 (static DebugTimer
00306 accum0(debugger.timer("substitutivityRule0 time"));
00307 static DebugTimer tmpTimer(debugger.newTimer());
00308 static DebugCounter count(debugger.counter("substitutivityRule0 calls"));
00309 debugger.setCurrentTime(tmpTimer);
00310 count++;)
00311
00312
00313 if(CHECK_PROOFS) {
00314 CHECK_SOUND(e.arity() == 1 && e[0] == thm.getLHS(),
00315 "Unexpected use of substitutivityRule0");
00316 CHECK_SOUND(thm.isRewrite(),
00317 "CVC3::CommonTheoremProducer::substitutivityRule0:\n "
00318 "premis is not an equality or IFF: "
00319 + thm.getExpr().toString()
00320 + "\n expr = " + e.toString());
00321 }
00322 Expr e2(e.getOp(), thm.getRHS());
00323 Proof pf;
00324 if(withProof())
00325 pf = newPf("basic_subst_op0",e, e2,thm.getProof());
00326 Theorem res = newRWTheorem(e, e2, Assumptions(thm), pf);
00327 if (!res.isRefl()) res.setSubst();
00328 return res;
00329 }
00330
00331
00332 Theorem CommonTheoremProducer::substitutivityRule(const Expr& e,
00333 const Theorem& thm1,
00334 const Theorem& thm2) {
00335 IF_DEBUG
00336 (static DebugTimer
00337 accum0(debugger.timer("substitutivityRule1 time"));
00338 static DebugTimer tmpTimer(debugger.newTimer());
00339 static DebugCounter count(debugger.counter("substitutivityRule1 calls"));
00340 debugger.setCurrentTime(tmpTimer);
00341 count++;)
00342
00343
00344 if(CHECK_PROOFS) {
00345 CHECK_SOUND(e.arity() == 2 && e[0] == thm1.getLHS() &&
00346 e[1] == thm2.getLHS(),
00347 "Unexpected use of substitutivityRule1");
00348 CHECK_SOUND(thm1.isRewrite(),
00349 "CVC3::CommonTheoremProducer::substitutivityRule1:\n "
00350 "premis is not an equality or IFF: "
00351 + thm1.getExpr().toString()
00352 + "\n expr = " + e.toString());
00353 CHECK_SOUND(thm2.isRewrite(),
00354 "CVC3::CommonTheoremProducer::substitutivityRule1:\n "
00355 "premis is not an equality or IFF: "
00356 + thm2.getExpr().toString()
00357 + "\n expr = " + e.toString());
00358 }
00359 Expr e2(e.getOp(), thm1.getRHS(), thm2.getRHS());
00360 Proof pf;
00361 if(withProof()) {
00362 vector<Proof> pfs;
00363 pfs.push_back(thm1.getProof());
00364 pfs.push_back(thm2.getProof());
00365 pf = newPf("basic_subst_op1", e, e2, pfs);
00366 }
00367 Theorem res = newRWTheorem(e, e2, Assumptions(thm1, thm2), pf);
00368 if (!res.isRefl()) res.setSubst();
00369 return res;
00370 }
00371
00372
00373 Theorem CommonTheoremProducer::substitutivityRule(const Op& op,
00374 const vector<Theorem>& thms) {
00375 IF_DEBUG
00376 (static DebugTimer
00377 accum0(debugger.timer("substitutivityRule time"));
00378 static DebugTimer tmpTimer(debugger.newTimer());
00379 static DebugCounter count(debugger.counter("substitutivityRule calls"));
00380 debugger.setCurrentTime(tmpTimer);
00381 count++;)
00382
00383 unsigned size(thms.size());
00384 if(size == 0)
00385 return reflexivityRule(d_tm->getEM()->newLeafExpr(op));
00386
00387
00388 vector<Expr> c, d;
00389 vector<Proof> pfs;
00390
00391
00392 c.reserve(size); d.reserve(size);
00393 for(vector<Theorem>::const_iterator i = thms.begin(), iend = thms.end();
00394 i != iend; ++i) {
00395
00396 if(CHECK_PROOFS)
00397 CHECK_SOUND(i->isRewrite(),
00398 "CVC3::CommonTheoremProducer::substitutivityRule:\n "
00399 "premis is not an equality or IFF: "
00400 + i->getExpr().toString()
00401 + "\n op = " + op.toString());
00402
00403 c.push_back(i->getLHS());
00404 d.push_back(i->getRHS());
00405 if(withProof()) pfs.push_back(i->getProof());
00406 }
00407 Expr e1(op, c), e2(op, d);
00408
00409 if(e1 == e2) return reflexivityRule(e1);
00410
00411 Assumptions a(thms);
00412 Proof pf;
00413 if(withProof())
00414
00415 pf = newPf("basic_subst_op",e1,e2,pfs);
00416 Theorem res = newRWTheorem(e1, e2, a, pf);
00417 IF_DEBUG(debugger.setElapsed(tmpTimer);
00418 accum0 += tmpTimer;)
00419 res.setSubst();
00420 return res;
00421 }
00422
00423
00424 Theorem CommonTheoremProducer::substitutivityRule(const Expr& e,
00425 const vector<unsigned>& changed,
00426 const vector<Theorem>& thms) {
00427 IF_DEBUG
00428 (static DebugTimer
00429 accum0(debugger.timer("substitutivityRule2 time"));
00430 static DebugTimer tmpTimer(debugger.newTimer());
00431 static DebugCounter count(debugger.counter("substitutivityRule2 calls"));
00432 debugger.setCurrentTime(tmpTimer);
00433 count++;)
00434 DebugAssert(changed.size() > 0, "substitutivityRule2 should not be called");
00435 DebugAssert(changed.size() == thms.size(), "substitutivityRule2: wrong args");
00436
00437
00438
00439 unsigned size = e.arity();
00440 if (size == 1) return substitutivityRule(e, thms.back());
00441 unsigned csize = changed.size();
00442 if (size == 2) {
00443 if (csize == 2) return substitutivityRule(e, thms[0], thms[1]);
00444 if (changed[0] == 0) {
00445 return substitutivityRule(e, thms[0], reflexivityRule(e[1]));
00446 }
00447 else {
00448 return substitutivityRule(e, reflexivityRule(e[0]), thms[0]);
00449 }
00450 }
00451 DebugAssert(size >= csize, "Bad call to substitutivityRule2");
00452
00453 vector<Expr> c;
00454 bool checkProofs(CHECK_PROOFS);
00455 for(unsigned j = 0, k = 0; k < size; ++k) {
00456 if (j == csize || changed[j] != k) {
00457 c.push_back(e[k]);
00458 continue;
00459 }
00460
00461 if(checkProofs)
00462 CHECK_SOUND(thms[j].isRewrite() && thms[j].getLHS() == e[k],
00463 "CVC3::CommonTheoremProducer::substitutivityRule:\n "
00464 "premis is not an equality or IFF: "
00465 + thms[j].getExpr().toString()
00466 + "\n e = " + e.toString());
00467
00468 c.push_back(thms[j].getRHS());
00469 ++j;
00470 }
00471 Expr e2(e.getOp(), c);
00472 IF_DEBUG(if(e == e2) {
00473 ostream& os = debugger.getOS();
00474 os << "substitutivityRule2: e = " << e << "\n e2 = " << e2
00475 << "\n changed kids: [\n";
00476 for(unsigned j=0; j<changed.size(); j++)
00477 os << " (" << changed[j] << ") " << thms[j] << "\n";
00478 os << "]\n";
00479 })
00480 DebugAssert(e != e2,
00481 "substitutivityRule2 should not be called in this case:\n"
00482 "e = "+e.toString());
00483
00484 Proof pf;
00485 Assumptions a(thms);
00486 if(withProof()) {
00487 vector<Proof> pfs;
00488 for(vector<Theorem>::const_iterator i = thms.begin(), iend = thms.end();
00489 i != iend; ++i) {
00490
00491 if(CHECK_PROOFS)
00492 CHECK_SOUND(i->isRewrite(),
00493 "CVC3::CommonTheoremProducer::substitutivityRule:\n "
00494 "premis is not an equality or IFF: "
00495 + i->getExpr().toString());
00496
00497 pfs.push_back(i->getProof());
00498 }
00499 pf = newPf("optimized_subst_op",e,e2,pfs);
00500 }
00501 Theorem res = newRWTheorem(e, e2, a, pf);
00502 IF_DEBUG(debugger.setElapsed(tmpTimer);
00503 accum0 += tmpTimer;)
00504 if (!res.isRefl()) res.setSubst();
00505 return res;
00506 }
00507
00508
00509 Theorem CommonTheoremProducer::substitutivityRule(const Expr& e,
00510 const int changed,
00511 const Theorem& thm)
00512 {
00513
00514 int size = e.arity();
00515
00516
00517 DebugAssert(size >= changed, "Bad call to substitutivityRule");
00518
00519
00520 if(CHECK_PROOFS)
00521 CHECK_SOUND(thm.isRewrite() && thm.getLHS() == e[changed], "CVC3::CommonTheoremProducer::substitutivityRule:\n "
00522 "premise is not an equality or IFF: " + thm.getExpr().toString() + "\n" +
00523 "e = " + e.toString());
00524
00525
00526 vector<Expr> c;
00527 for(int k = 0; k < size; ++ k)
00528 if (k != changed) c.push_back(e[k]);
00529 else c.push_back(thm.getRHS());
00530
00531
00532 Expr e2(e.getOp(), c);
00533
00534
00535 IF_DEBUG(if(e == e2) {
00536 ostream& os = debugger.getOS();
00537 os << "substitutivityRule: e = " << e << "\n e2 = " << e2 << endl;
00538 })
00539
00540
00541 DebugAssert(e != e2, "substitutivityRule should not be called in this case:\ne = "+e.toString());
00542
00543
00544 Proof pf;
00545 Assumptions a(thm);
00546 if(withProof()) {
00547
00548 if(CHECK_PROOFS)
00549 CHECK_SOUND(thm.isRewrite(), "CVC3::CommonTheoremProducer::substitutivityRule:\npremise is not an equality or IFF: " + thm.getExpr().toString());
00550 pf = newPf("optimized_subst_op2",e,e2,thm.getProof());
00551 }
00552
00553
00554 Theorem res = newRWTheorem(e, e2, a, pf);;
00555 res.setSubst();
00556 return res;
00557 }
00558
00559
00560
00561 Theorem CommonTheoremProducer::contradictionRule(const Theorem& e,
00562 const Theorem& not_e) {
00563 Proof pf;
00564 if(CHECK_PROOFS)
00565 CHECK_SOUND(!e.getExpr() == not_e.getExpr(),
00566 "CommonTheoremProducer::contraditionRule: "
00567 "theorems don't match:\n e = "+e.toString()
00568 +"\n not_e = "+not_e.toString());
00569 Assumptions a(e, not_e);
00570 if(withProof()) {
00571 vector<Proof> pfs;
00572 pfs.push_back(e.getProof());
00573 pfs.push_back(not_e.getProof());
00574 pf = newPf("contradition", e.getExpr(), pfs);
00575 }
00576 return newTheorem(d_em->falseExpr(), a, pf);
00577 }
00578
00579
00580 Theorem CommonTheoremProducer::excludedMiddle(const Expr& e)
00581 {
00582 Proof pf;
00583 if (withProof()) {
00584 pf = newPf("excludedMiddle", e);
00585 }
00586 return newTheorem(e.orExpr(!e), Assumptions::emptyAssump(), pf);
00587 }
00588
00589
00590
00591 Theorem CommonTheoremProducer::iffTrue(const Theorem& e)
00592 {
00593 Proof pf;
00594 if(withProof()) {
00595 pf = newPf("iff_true", e.getExpr(), e.getProof());
00596 }
00597 return newRWTheorem(e.getExpr(), d_em->trueExpr(), Assumptions(e), pf);
00598 }
00599
00600
00601
00602 Theorem CommonTheoremProducer::iffNotFalse(const Theorem& e) {
00603 Proof pf;
00604 if(withProof()) {
00605 pf = newPf("iff_not_false", e.getExpr(), e.getProof());
00606 }
00607 return newRWTheorem(!e.getExpr(), d_em->falseExpr(), Assumptions(e), pf);
00608 }
00609
00610
00611
00612 Theorem CommonTheoremProducer::iffTrueElim(const Theorem& e) {
00613 if(CHECK_PROOFS)
00614 CHECK_SOUND(e.isRewrite() && e.getRHS().isTrue(),
00615 "CommonTheoremProducer::iffTrueElim: "
00616 "theorem is not e<=>TRUE: "+ e.toString());
00617 Proof pf;
00618 if(withProof()) {
00619 pf = newPf("iff_true_elim", e.getLHS(), e.getProof());
00620 }
00621 return newTheorem(e.getLHS(), Assumptions(e), pf);
00622 }
00623
00624
00625
00626 Theorem CommonTheoremProducer::iffFalseElim(const Theorem& e) {
00627 if(CHECK_PROOFS)
00628 CHECK_SOUND(e.isRewrite() && e.getRHS().isFalse(),
00629 "CommonTheoremProducer::iffFalseElim: "
00630 "theorem is not e<=>FALSE: "+ e.toString());
00631 const Expr& lhs = e.getLHS();
00632 Proof pf;
00633 if(withProof()) {
00634 pf = newPf("iff_false_elim", lhs, e.getProof());
00635 }
00636 return newTheorem(!lhs, Assumptions(e), pf);
00637 }
00638
00639
00640
00641 Theorem CommonTheoremProducer::iffContrapositive(const Theorem& e) {
00642 if(CHECK_PROOFS)
00643 CHECK_SOUND(e.isRewrite() && e.getRHS().getType().isBool(),
00644 "CommonTheoremProducer::iffContrapositive: "
00645 "theorem is not e1<=>e2: "+ e.toString());
00646 Proof pf;
00647 if(withProof()) {
00648 pf = newPf("iff_contrapositive", e.getExpr(), e.getProof());
00649 }
00650 return newRWTheorem(e.getLHS().negate(),e.getRHS().negate(), Assumptions(e), pf);
00651 }
00652
00653
00654
00655 Theorem CommonTheoremProducer::notNotElim(const Theorem& not_not_e) {
00656 if(CHECK_PROOFS)
00657 CHECK_SOUND(not_not_e.getExpr().isNot() && not_not_e.getExpr()[0].isNot(),
00658 "CommonTheoremProducer::notNotElim: bad theorem: !!e = "
00659 + not_not_e.toString());
00660 Proof pf;
00661 if(withProof())
00662 pf = newPf("not_not_elim", not_not_e.getExpr(), not_not_e.getProof());
00663 return newTheorem(not_not_e.getExpr()[0][0], Assumptions(not_not_e), pf);
00664 }
00665
00666
00667 Theorem CommonTheoremProducer::iffMP(const Theorem& e1, const Theorem& e1_iff_e2)
00668 {
00669 if(CHECK_PROOFS) {
00670 CHECK_SOUND(e1_iff_e2.isRewrite(),
00671 "iffMP: not IFF: "+e1_iff_e2.toString());
00672 CHECK_SOUND(e1.getExpr() == (e1_iff_e2.getLHS()),
00673 "iffMP: theorems don't match:\n e1 = " + e1.toString()
00674 + ", e1_iff_e2 = " + e1_iff_e2.toString());
00675 }
00676 const Expr& e2(e1_iff_e2.getRHS());
00677
00678 if (e1_iff_e2.getLHS() == e2) return e1;
00679 Proof pf;
00680 Assumptions a(e1, e1_iff_e2);
00681 if(withProof()) {
00682 vector<Proof> pfs;
00683 pfs.push_back(e1.getProof());
00684 pfs.push_back(e1_iff_e2.getProof());
00685 pf = newPf("iff_mp", e1.getExpr(), e2, pfs);
00686 }
00687 return newTheorem(e2, a, pf);
00688 }
00689
00690
00691
00692 Theorem CommonTheoremProducer::implMP(const Theorem& e1,
00693 const Theorem& e1_impl_e2) {
00694 const Expr& impl = e1_impl_e2.getExpr();
00695 if(CHECK_PROOFS) {
00696 CHECK_SOUND(impl.isImpl() && impl.arity()==2,
00697 "implMP: not IMPLIES: "+impl.toString());
00698 CHECK_SOUND(e1.getExpr() == impl[0],
00699 "implMP: theorems don't match:\n e1 = " + e1.toString()
00700 + ", e1_impl_e2 = " + impl.toString());
00701 }
00702 const Expr& e2 = impl[1];
00703
00704
00705 Proof pf;
00706 Assumptions a(e1, e1_impl_e2);
00707 if(withProof()) {
00708 vector<Proof> pfs;
00709 pfs.push_back(e1.getProof());
00710 pfs.push_back(e1_impl_e2.getProof());
00711 pf = newPf("impl_mp", e1.getExpr(), e2, pfs);
00712 }
00713 return newTheorem(e2, a, pf);
00714 }
00715
00716
00717
00718 Theorem CommonTheoremProducer::andElim(const Theorem& e, int i) {
00719 if(CHECK_PROOFS) {
00720 CHECK_SOUND(e.getExpr().isAnd(), "andElim: not an AND: " + e.toString());
00721 CHECK_SOUND(i < e.getExpr().arity(), "andElim: i = " + int2string(i)
00722 + " >= arity = " + int2string(e.getExpr().arity())
00723 + " in " + e.toString());
00724 }
00725 Proof pf;
00726 if(withProof())
00727 pf = newPf("andE", d_em->newRatExpr(i), e.getExpr(), e.getProof());
00728 return newTheorem(e.getExpr()[i], Assumptions(e), pf);
00729 }
00730
00731
00732
00733 Theorem CommonTheoremProducer::andIntro(const Theorem& e1, const Theorem& e2) {
00734 vector<Theorem> thms;
00735 thms.push_back(e1);
00736 thms.push_back(e2);
00737 return andIntro(thms);
00738 }
00739
00740
00741 Theorem CommonTheoremProducer::andIntro(const vector<Theorem>& es) {
00742 Proof pf;
00743 if(CHECK_PROOFS)
00744 CHECK_SOUND(es.size() > 1,
00745 "andIntro(vector<Theorem>): vector must have more than 1 element");
00746 Assumptions a(es);
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 vector<Expr> kids;
00757 for(vector<Theorem>::const_iterator i=es.begin(), iend=es.end();
00758 i!=iend; ++i)
00759 kids.push_back(i->getExpr());
00760
00761 if(withProof()) {
00762 vector<Proof> pfs;
00763 for(vector<Theorem>::const_iterator i=es.begin(), iend=es.end();
00764 i!=iend; ++i)
00765 pfs.push_back(i->getProof());
00766 pf = newPf("andI", andExpr(kids), pfs);
00767 }
00768 return newTheorem(andExpr(kids), a, pf);
00769 }
00770
00771
00772
00773
00774
00775 Theorem CommonTheoremProducer::implIntro(const Theorem& phi,
00776 const std::vector<Expr>& assump) {
00777 bool checkProofs(CHECK_PROOFS);
00778
00779 if(checkProofs) {
00780 CHECK_SOUND(withAssumptions(),
00781 "implIntro: called while running without assumptions");
00782 }
00783
00784 const Assumptions& phiAssump = phi.getAssumptionsRef();
00785
00786 if(checkProofs) {
00787 for(size_t i=0; i<assump.size(); i++) {
00788 const Theorem& thm = phiAssump[assump[i]];
00789 CHECK_SOUND(!thm.isNull() && thm.isAssump(),
00790 "implIntro: this is not an assumption of phi:\n\n"
00791 " a["+int2string(i)+"] = "+assump[i].toString()
00792 +"\n\n phi = "+phi.getExpr().toString());
00793 }
00794 }
00795
00796
00797 if(assump.size() == 0) return phi;
00798
00799 Assumptions a(phiAssump - assump);
00800 Proof pf;
00801 if(withProof()) {
00802 vector<Proof> u;
00803 for(vector<Expr>::const_iterator i=assump.begin(), iend=assump.end();
00804 i!=iend; ++i) {
00805 const Theorem& t = phiAssump[*i];
00806 u.push_back(t.getProof());
00807 }
00808
00809
00810
00811 vector<Expr> args;
00812 vector<Proof> pfs;
00813 args.push_back(phi.getExpr());
00814 args.insert(args.end(), assump.begin(), assump.end());
00815
00816 pfs.push_back(newPf(u, assump, phi.getProof()));
00817 pf = newPf("impl_intro", args, pfs);
00818 }
00819 Expr conj(andExpr(assump));
00820 return newTheorem(conj.impExpr(phi.getExpr()), a, pf);
00821 }
00822
00823
00824
00825 Theorem CommonTheoremProducer::implContrapositive(const Theorem& thm) {
00826 const Expr& impl = thm.getExpr();
00827 if(CHECK_PROOFS) {
00828 CHECK_SOUND(impl.isImpl() && impl.arity()==2,
00829 "CommonTheoremProducer::implContrapositive: thm="
00830 +impl.toString());
00831 }
00832 Proof pf;
00833 if(withProof())
00834 pf = newPf("impl_contrapositive", impl, thm.getProof());
00835 return newTheorem(impl[1].negate().impExpr(impl[0].negate()), Assumptions(thm), pf);
00836 }
00837
00838
00839
00840 Theorem
00841 CommonTheoremProducer::rewriteIteTrue(const Expr& e) {
00842 Proof pf;
00843 if(CHECK_PROOFS)
00844 CHECK_SOUND(e.isITE() && e[0].isTrue(),
00845 "rewriteIteTrue precondition violated");
00846 if(withProof()) {
00847 Type t = e[1].getType();
00848 DebugAssert(!t.isNull(), "rewriteIteTrue: e1 has no type: "
00849 + e[1].toString());
00850 bool useIff = t.isBool();
00851 if(useIff)
00852 pf = newPf("rewrite_ite_true_iff", e[1], e[2]);
00853 else {
00854 pf = newPf("rewrite_ite_true", t.getExpr(), e[1], e[2]);
00855 }
00856 }
00857 return newRWTheorem(e, e[1], Assumptions::emptyAssump(), pf);
00858 }
00859
00860
00861
00862 Theorem
00863 CommonTheoremProducer::rewriteIteFalse(const Expr& e) {
00864 Proof pf;
00865 if(CHECK_PROOFS)
00866 CHECK_SOUND(e.isITE() && e[0].isFalse(),
00867 "rewriteIteFalse precondition violated");
00868 if(withProof()) {
00869 Type t = e[1].getType();
00870 DebugAssert(!t.isNull(), "rewriteIteFalse: e1 has no type: "
00871 + e[1].toString());
00872 bool useIff = t.isBool();
00873 if(useIff)
00874 pf = newPf("rewrite_ite_false_iff", e[1], e[2]);
00875 else {
00876 pf = newPf("rewrite_ite_false", t.getExpr(), e[1], e[2]);
00877 }
00878 }
00879 return newRWTheorem(e, e[2], Assumptions::emptyAssump(), pf);
00880 }
00881
00882
00883
00884 Theorem
00885 CommonTheoremProducer::rewriteIteSame(const Expr& e) {
00886 Proof pf;
00887 if(CHECK_PROOFS)
00888 CHECK_SOUND(e.isITE() && e[1] == e[2],
00889 "rewriteIteSame precondition violated");
00890 if(withProof()) {
00891 Type t = e[1].getType();
00892 DebugAssert(!t.isNull(), "rewriteIteSame: e[1] has no type: "
00893 + e[1].toString());
00894 bool useIff = t.isBool();
00895 if(useIff)
00896 pf = newPf("rewrite_ite_same_iff", e[0], e[1]);
00897 else {
00898 pf = newPf("rewrite_ite_same", t.getExpr(), e[0], e[1]);
00899 }
00900 }
00901 return newRWTheorem(e, e[1], Assumptions::emptyAssump(), pf);
00902 }
00903
00904
00905
00906 Theorem CommonTheoremProducer::notToIff(const Theorem& not_e)
00907 {
00908 if(CHECK_PROOFS)
00909 CHECK_SOUND(not_e.getExpr().isNot(),
00910 "notToIff: not NOT: "+not_e.toString());
00911
00912
00913 Expr e(not_e.getExpr()[0]);
00914 Proof pf;
00915 if(withProof())
00916 pf=newPf("not_to_iff", e, not_e.getProof());
00917 return newRWTheorem(e, d_em->falseExpr(), Assumptions(not_e), pf);
00918 }
00919
00920
00921
00922 Theorem CommonTheoremProducer::xorToIff(const Expr& e)
00923 {
00924 if(CHECK_PROOFS) {
00925 CHECK_SOUND(e.isXor(), "xorToIff precondition violated");
00926 CHECK_SOUND(e.arity() >= 2, "Expected XOR of arity >= 2");
00927 }
00928 Expr res = e[e.arity()-1];
00929 for (int i = e.arity()-2; i >=0; --i) {
00930 res = (!e[i]).iffExpr(res);
00931 }
00932 Proof pf;
00933 if(withProof()) {
00934 pf = newPf("xorToIff");
00935 }
00936 return newRWTheorem(e, res, Assumptions::emptyAssump(), pf);
00937 }
00938
00939
00940
00941 Theorem CommonTheoremProducer::rewriteIff(const Expr& e) {
00942 Proof pf;
00943 if(CHECK_PROOFS)
00944 CHECK_SOUND(e.isIff(), "rewriteIff precondition violated");
00945 if(withProof()) {
00946 pf = newPf("rewrite_iff", e[0], e[1]);
00947 }
00948
00949 if(e[0] == e[1]) return rewriteReflexivity(e);
00950
00951 switch(e[0].getKind()) {
00952 case TRUE_EXPR:
00953 return newRWTheorem(e, e[1], Assumptions::emptyAssump(), pf);
00954 case FALSE_EXPR:
00955 return newRWTheorem(e, !e[1], Assumptions::emptyAssump() ,pf);
00956 case NOT:
00957 if(e[0][0]==e[1])
00958 return newRWTheorem(e, d_em->falseExpr(), Assumptions::emptyAssump(), pf);
00959 break;
00960 default: break;
00961 }
00962
00963 switch(e[1].getKind()) {
00964 case TRUE_EXPR:
00965 return newRWTheorem(e, e[0], Assumptions::emptyAssump(), pf);
00966 case FALSE_EXPR:
00967 return newRWTheorem(e, !e[0], Assumptions::emptyAssump(), pf);
00968 case NOT:
00969 if(e[0]==e[1][0])
00970 return newRWTheorem(e, d_em->falseExpr(), Assumptions::emptyAssump(), pf);
00971 break;
00972 default:
00973 break;
00974 }
00975
00976 if(e[0] < e[1])
00977 return rewriteUsingSymmetry(e);
00978 else
00979 return reflexivityRule(e);
00980 }
00981
00982
00983
00984
00985
00986
00987
00988
00989 Theorem CommonTheoremProducer::rewriteAnd(const Expr& e) {
00990 if(CHECK_PROOFS)
00991 CHECK_SOUND(e.isAnd(), "rewriteAnd: bad Expr: " + e.toString());
00992 Proof pf;
00993 ExprMap<bool> newKids;
00994 bool isFalse (false);
00995 for (Expr::iterator k=e.begin(), kend=e.end(); !isFalse && k != kend; ++k) {
00996 const Expr& ek = *k;
00997 if (ek.isFalse()) { isFalse=true; break; }
00998 if (ek.isAnd() && ek.arity() < 10) {
00999 for(Expr::iterator j=ek.begin(), jend=ek.end(); j!=jend; ++j) {
01000 if(newKids.count(j->negate()) > 0) { isFalse=true; break; }
01001 newKids[*j]=true;
01002 }
01003 } else if(!ek.isTrue()) {
01004 if(newKids.count(ek.negate()) > 0) { isFalse=true; break; }
01005 newKids[ek]=true;
01006 }
01007 }
01008 Expr res;
01009 if (isFalse) res = d_em->falseExpr();
01010 else if (newKids.size() == 0) res = d_em->trueExpr();
01011 else if (newKids.size() == 1)
01012 res = newKids.begin()->first;
01013 else {
01014 vector<Expr> v;
01015 for(ExprMap<bool>::iterator i=newKids.begin(), iend=newKids.end();
01016 i!=iend; ++i)
01017 v.push_back(i->first);
01018 res = andExpr(v);
01019 }
01020 if(withProof()) {
01021 pf = newPf("rewrite_and", e,res);
01022 }
01023 return newRWTheorem(e, res, Assumptions::emptyAssump(), pf);
01024 }
01025
01026
01027
01028 Theorem CommonTheoremProducer::rewriteOr(const Expr& e) {
01029 if(CHECK_PROOFS)
01030 CHECK_SOUND(e.isOr(), "rewriteOr: bad Expr: " + e.toString());
01031 Proof pf;
01032 ExprMap<bool> newKids;
01033 bool isTrue (false);
01034 for (Expr::iterator k=e.begin(), kend=e.end(); !isTrue && k != kend; ++k) {
01035 const Expr& ek = *k;
01036 if (ek.isTrue()) { isTrue=true; break; }
01037 else if (ek.isOr() && ek.arity() < 10) {
01038 for(Expr::iterator j=ek.begin(), jend=ek.end(); j!=jend; ++j) {
01039 if(newKids.count(j->negate()) > 0) { isTrue=true; break; }
01040 newKids[*j]=true;
01041 }
01042 } else if(!ek.isFalse()) {
01043 if(newKids.count(ek.negate()) > 0) { isTrue=true; break; }
01044 newKids[ek]=true;
01045 }
01046 }
01047 Expr res;
01048 if (isTrue) res = d_em->trueExpr();
01049 else if (newKids.size() == 0) res = d_em->falseExpr();
01050 else if (newKids.size() == 1) res = newKids.begin()->first;
01051 else {
01052 vector<Expr> v;
01053 for(ExprMap<bool>::iterator i=newKids.begin(), iend=newKids.end();
01054 i!=iend; ++i)
01055 v.push_back(i->first);
01056 res = orExpr(v);
01057 }
01058 if(withProof()) {
01059 pf = newPf("rewrite_or", e, res);
01060 }
01061 return newRWTheorem(e, res, Assumptions::emptyAssump(), pf);
01062 }
01063
01064
01065
01066 Theorem CommonTheoremProducer::rewriteNotTrue(const Expr& e) {
01067 Proof pf;
01068 if(CHECK_PROOFS)
01069 CHECK_SOUND(e.isNot() && e[0].isTrue(),
01070 "rewriteNotTrue precondition violated");
01071 if(withProof())
01072 pf = newPf("rewrite_not_true");
01073 return newRWTheorem(e, d_em->falseExpr(), Assumptions::emptyAssump(), pf);
01074 }
01075
01076
01077
01078 Theorem CommonTheoremProducer::rewriteNotFalse(const Expr& e) {
01079 Proof pf;
01080 if(CHECK_PROOFS)
01081 CHECK_SOUND(e.isNot() && e[0].isFalse(),
01082 "rewriteNotFalse precondition violated");
01083 if(withProof())
01084 pf = newPf("rewrite_not_false");
01085 return newRWTheorem(e, d_em->trueExpr(), Assumptions::emptyAssump(), pf);
01086 }
01087
01088
01089
01090 Theorem CommonTheoremProducer::rewriteNotNot(const Expr& e) {
01091 Proof pf;
01092 if(CHECK_PROOFS)
01093 CHECK_SOUND(e.isNot() && e[0].isNot(),
01094 "rewriteNotNot precondition violated");
01095 if(withProof())
01096 pf = newPf("rewrite_not_not", e[0][0]);
01097 return newRWTheorem(e, e[0][0], Assumptions::emptyAssump(), pf);
01098 }
01099
01100
01101
01102 Theorem CommonTheoremProducer::rewriteNotForall(const Expr& e) {
01103 if(CHECK_PROOFS) {
01104 CHECK_SOUND(e.isNot() && e[0].isForall(),
01105 "rewriteNotForall: expr must be NOT FORALL:\n"
01106 +e.toString());
01107 }
01108 Proof pf;
01109 if(withProof())
01110 pf = newPf("rewrite_not_forall", e);
01111 return newRWTheorem(e, d_em->newClosureExpr(EXISTS, e[0].getVars(),
01112 !e[0].getBody()), Assumptions::emptyAssump(), pf);
01113 }
01114
01115
01116
01117 Theorem CommonTheoremProducer::rewriteNotExists(const Expr& e) {
01118 if(CHECK_PROOFS) {
01119 CHECK_SOUND(e.isNot() && e[0].isExists(),
01120 "rewriteNotExists: expr must be NOT FORALL:\n"
01121 +e.toString());
01122 }
01123 Proof pf;
01124 if(withProof())
01125 pf = newPf("rewrite_not_exists", e);
01126 return newRWTheorem(e, d_em->newClosureExpr(FORALL, e[0].getVars(),
01127 !e[0].getBody()), Assumptions::emptyAssump(), pf);
01128 }
01129
01130
01131 Expr CommonTheoremProducer::skolemize(const Expr& e)
01132 {
01133 vector<Expr> vars;
01134 const vector<Expr>& boundVars = e.getVars();
01135 for(unsigned int i=0; i<boundVars.size(); i++) {
01136 Expr skolV(e.skolemExpr(i));
01137 Type tp(e.getVars()[i].getType());
01138 skolV.setType(tp);
01139 vars.push_back(skolV);
01140 }
01141 return(e.getBody().substExpr(boundVars, vars));
01142 }
01143
01144
01145 Theorem CommonTheoremProducer::skolemizeRewrite(const Expr& e)
01146 {
01147 Proof pf;
01148 if(CHECK_PROOFS) {
01149 CHECK_SOUND(e.isExists(), "skolemize rewrite called on non-existential: "
01150 + e.toString());
01151 }
01152 Expr skol = skolemize(e);
01153 if(withProof()) {
01154 Expr rw(e.iffExpr(skol));
01155 pf = newLabel(rw);
01156 }
01157 TRACE("quantlevel", "skolemize ", skol, "");
01158 TRACE("quantlevel sko", "skolemize ", skol, "");
01159 TRACE("quantlevel sko", "skolemize from org ", e, "");
01160 return newRWTheorem(e, skol, Assumptions::emptyAssump(), pf);
01161
01162 }
01163
01164
01165 Theorem CommonTheoremProducer::skolemizeRewriteVar(const Expr& e)
01166 {
01167 Proof pf;
01168 if(CHECK_PROOFS) {
01169 CHECK_SOUND(e.isExists(), "skolemizeRewriteVar("
01170 +e.toString()+")");
01171 }
01172
01173 const vector<Expr>& boundVars = e.getVars();
01174 const Expr& body = e.getBody();
01175
01176 if(CHECK_PROOFS) {
01177 CHECK_SOUND(boundVars.size()==1, "skolemizeRewriteVar("
01178 +e.toString()+")");
01179 CHECK_SOUND(body.isEq() || body.isIff(), "skolemizeRewriteVar("
01180 +e.toString()+")");
01181 const Expr& v = boundVars[0];
01182 CHECK_SOUND(body[1] == v, "skolemizeRewriteVar("
01183 +e.toString()+")");
01184 CHECK_SOUND(!(v.subExprOf(body[0])), "skolemizeRewriteVar("
01185 +e.toString()+")");
01186 }
01187
01188 Expr skolV(e.skolemExpr(0));
01189 Type tp(e.getVars()[0].getType());
01190 skolV.setType(tp);
01191
01192 Expr skol = Expr(body.getOp(), body[0], skolV);
01193
01194 if(withProof()) {
01195 Expr rw(e.iffExpr(skol));
01196 pf = newLabel(rw);
01197 }
01198 return newRWTheorem(e, skol, Assumptions::emptyAssump(), pf);
01199 }
01200
01201
01202 Theorem CommonTheoremProducer::varIntroRule(const Expr& phi) {
01203
01204 Proof pf;
01205 const Expr boundVar = d_em->newBoundVarExpr(phi.getType());
01206
01207 Expr body;
01208 if(phi.getType().isBool())
01209 body = phi.iffExpr(boundVar);
01210 else
01211 body = phi.eqExpr(boundVar);
01212
01213 std::vector<Expr> v;
01214 v.push_back(boundVar);
01215 const Expr result = d_em->newClosureExpr(EXISTS, v, body);
01216
01217 if(withProof())
01218 pf = newPf("var_intro", phi, boundVar);
01219 return newTheorem(result, Assumptions::emptyAssump(), pf);
01220 }
01221
01222
01223 Theorem CommonTheoremProducer::skolemize(const Theorem& thm) {
01224 const Expr& e = thm.getExpr();
01225 if(e.isExists()) {
01226 TRACE("skolem", "Skolemizing existential:", "", "{");
01227 CDMap<Expr, Theorem>::iterator i=d_skolemized_thms.find(e),
01228 iend=d_skolemized_thms.end();
01229 if(i!=iend) {
01230 TRACE("skolem", "Skolemized theorem found in map: ", (*i).second, "}");
01231 return iffMP(thm, (*i).second);
01232 }
01233 Theorem skol = skolemizeRewrite(e);
01234 for(unsigned int i=0; i<e.getVars().size(); i++) {
01235 Expr skolV(e.skolemExpr(i));
01236 Type tp(e.getVars()[i].getType());
01237 skolV.setType(tp);
01238 }
01239 d_skolem_axioms.push_back(skol);
01240 d_skolemized_thms.insert(e, skol, 0);
01241 skol = iffMP(thm, skol);
01242
01243 TRACE("skolem", "skolemized new theorem: ", skol, "}");
01244 return skol;
01245 }
01246 return thm;
01247 }
01248
01249
01250 Theorem CommonTheoremProducer::varIntroSkolem(const Expr& e) {
01251
01252 CDMap<Expr, Theorem>::iterator i=d_skolemVars.find(e),
01253 iend=d_skolemVars.end();
01254 if(i!=iend) return (*i).second;
01255
01256 Theorem thm = varIntroRule(e);
01257 const Expr& e2 = thm.getExpr();
01258 DebugAssert(e2.isExists() && e2.getVars().size()==1, "varIntroSkolem: e2 = "
01259 +e2.toString());
01260 Theorem skolThm;
01261
01262 CDMap<Expr, Theorem>::iterator j=d_skolemized_thms.find(e2),
01263 jend=d_skolemized_thms.end();
01264 if(j!=jend) {
01265 skolThm = (*i).second;
01266 } else {
01267 skolThm = skolemizeRewriteVar(e2);
01268 d_skolem_axioms.push_back(skolThm);
01269 d_skolemized_thms.insert(e2, skolThm, 0);
01270 }
01271 thm = iffMP(thm, skolThm);
01272 d_skolemVars.insert(e, thm, 0);
01273 return thm;
01274 }
01275
01276
01277
01278
01279
01280 Theorem CommonTheoremProducer::trueTheorem()
01281 {
01282 return iffTrueElim(reflexivityRule(d_em->trueExpr()));
01283 }
01284
01285
01286 Theorem CommonTheoremProducer::rewriteAnd(const Theorem& e)
01287 {
01288 return iffMP(e, rewriteAnd(e.getExpr()));
01289 }
01290
01291
01292 Theorem CommonTheoremProducer::rewriteOr(const Theorem& e)
01293 {
01294 return iffMP(e, rewriteOr(e.getExpr()));
01295 }
01296
01297
01298 Theorem CommonTheoremProducer::ackermann(const Expr& e1, const Expr& e2)
01299 {
01300 Proof pf;
01301 if(CHECK_PROOFS)
01302 CHECK_SOUND(e1.isApply() && e2.isApply() && e1.getOp() == e2.getOp(),
01303 "ackermann precondition violated");
01304 Expr hyp;
01305 int ar = e1.arity();
01306 if (ar == 1) {
01307 hyp = Expr(e1[0].eqExpr(e2[0]));
01308 }
01309 else {
01310 vector<Expr> vec;
01311 for (int i = 0; i != ar; ++i) {
01312 vec.push_back(e1[i].eqExpr(e2[i]));
01313 }
01314 hyp = Expr(AND, vec);
01315 }
01316 if(withProof())
01317 pf = newPf("ackermann", e1, e2);
01318 return newTheorem(hyp.impExpr(e1.eqExpr(e2)), Assumptions::emptyAssump(), pf);
01319 }
01320
01321
01322 void CommonTheoremProducer::findITE(const Expr& e, Expr& condition, Expr& thenpart, Expr& elsepart)
01323 {
01324 if (!e.getType().isBool() && e.isITE()) {
01325 condition = e[0];
01326 if (!condition.containsTermITE()) {
01327 thenpart = e[1];
01328 elsepart = e[2];
01329 return;
01330 }
01331 }
01332
01333 vector<Expr> kids;
01334 int i = 0;
01335 for (; i < e.arity(); ++i) {
01336 if (e[i].containsTermITE()) break;
01337 kids.push_back(e[i]);
01338 }
01339
01340 if(CHECK_PROOFS) {
01341 CHECK_SOUND(i < e.arity(), "could not find ITE");
01342 }
01343
01344 Expr t2, e2;
01345 findITE(e[i], condition, t2, e2);
01346
01347 kids.push_back(t2);
01348 for(int k = i+1; k < e.arity(); ++k) {
01349 kids.push_back(e[k]);
01350 }
01351
01352 thenpart = Expr(e.getOp(), kids);
01353
01354 kids[i] = e2;
01355 elsepart = Expr(e.getOp(), kids);
01356 }
01357
01358
01359 Theorem CommonTheoremProducer::liftOneITE(const Expr& e) {
01360
01361 if(CHECK_PROOFS) {
01362 CHECK_SOUND(e.containsTermITE(), "CommonTheoremProducer::liftOneITE: bad input" + e.toString());
01363 }
01364
01365 Expr cond, thenpart, elsepart;
01366
01367 findITE(e, cond, thenpart, elsepart);
01368
01369 Proof pf;
01370 if(withProof())
01371 pf = newPf("lift_one_ite", e);
01372
01373 return newRWTheorem(e, cond.iteExpr(thenpart, elsepart), Assumptions::emptyAssump(), pf);
01374 }