CVC3
|
00001 /*****************************************************************************/ 00002 /*! 00003 *\file common_theorem_producer.cpp 00004 *\brief Implementation of common proof rules 00005 * 00006 * Author: Clark Barrett 00007 * 00008 * Created: Wed Jan 11 16:10:15 2006 00009 * 00010 * <hr> 00011 * 00012 * License to use, copy, modify, sell and/or distribute this software 00013 * and its documentation for any purpose is hereby granted without 00014 * royalty, subject to the terms and conditions defined in the \ref 00015 * LICENSE file provided with this distribution. 00016 * 00017 * <hr> 00018 * 00019 */ 00020 /*****************************************************************************/ 00021 00022 00023 // This code is trusted 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 // The trusted method of TheoremManager which creates this theorem producer 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 // TCC rules (3-valued logic) 00049 //////////////////////////////////////////////////////////////////////// 00050 00051 // G1 |- phi G2 |- D_phi 00052 // ------------------------- 00053 // G1,G2 |-_3 phi 00054 Theorem3 00055 CommonTheoremProducer::queryTCC(const Theorem& phi, const Theorem& D_phi) { 00056 Proof pf; 00057 // if(CHECK_PROOFS) 00058 // CHECK_SOUND(D_phi.getExpr() == d_core->getTCC(phi.getExpr()), 00059 // "CoreTheoremProducer::queryTCC: " 00060 // "bad TCC for a formula:\n\n " 00061 // +phi.getExpr().toString() 00062 // +"\n\n TCC must be the following:\n\n " 00063 // +d_core->getTCC(phi.getExpr()).toString() 00064 // +"\n\nBut given this as a TCC:\n\n " 00065 // +D_phi.getExpr().toString()); 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 // G0,a1,...,an |-_3 phi G1 |- D_a1 ... Gn |- D_an 00082 // ------------------------------------------------- 00083 // G0,G1,...,Gn |-_3 (a1 & ... & an) -> phi 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 // This rule only makes sense when runnnig with assumptions 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 // CHECK_SOUND(tccs[i].getExpr() == d_core->getTCC(assump[i]), 00110 // "implIntro3: Assumption does not match its TCC:\n\n" 00111 // " a["+int2string(i)+"] = "+assump[i].toString() 00112 // +" TCC(a["+int2string(i)+"]) = " 00113 // +d_core->getTCC(assump[i]).toString() 00114 // +"\n\n tccs["+int2string(i)+"] = " 00115 // +tccs[i].getExpr().toString()); 00116 } 00117 } 00118 00119 // Proof compaction: trivial derivation 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; // Proof labels for assumptions 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 // Arguments to the proof rule: 00134 // impl_intro_3(phi, a1,...,an,tcc1,...tccn,pf_tcc1,...pf_tccn, 00135 // [lambda(a1,...,an): pf_phi]) 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 // Lambda-abstraction of pf_phi 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 // TRACE("assump", "assumpRule(", e, ")"); 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 // ==> (a == a) IFF TRUE 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 //// Proof compaction 00199 ///////////////////////////////////////////////////////////////////////// 00200 // If a1 == a2, use reflexivity 00201 if(a1 == a2) return reflexivityRule(a1); 00202 // Otherwise, do the work 00203 if(withProof()) { 00204 Type t = a1.getType(); 00205 // Check the types 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 // Proof compaction: if a1 == a2, use reflexivity 00228 if(a1 == a2) return reflexivityRule(a1_eq_a2); 00229 // Otherwise, do the work 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 //// Proof compaction 00267 ///////////////////////////////////////////////////////////////////////// 00268 // if a1 == a3, use reflexivity (and lose all assumptions) 00269 if(a1 == a3) return reflexivityRule(a1); 00270 // if a1 == a2, or if a2 == a3, use only the non-trivial part 00271 if(a1 == a2) return a2_eq_a3; 00272 if(a2 == a3) return a1_eq_a2; 00273 00274 //////////////////////////////////////////////////////////////////////// 00275 //// No shortcuts. Do the work. 00276 //////////////////////////////////////////////////////////////////////// 00277 00278 Proof pf; 00279 Assumptions a(a1_eq_a2, a2_eq_a3); 00280 // Build the proof 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 // Type argument is needed only for equality 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 // Check that t is c == d or c IFF d 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 // Check that t is c == d or c IFF d 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 // Check for trivial case: no theorems, return (op == op) 00383 unsigned size(thms.size()); 00384 if(size == 0) 00385 return reflexivityRule(d_tm->getEM()->newLeafExpr(op)); 00386 // Check that theorems are of the form c_i == d_i and collect 00387 // vectors of c_i's and d_i's and the vector of proofs 00388 vector<Expr> c, d; 00389 vector<Proof> pfs; 00390 // Reserve memory for argument vectors. Do not reserve memory for 00391 // pfs, they are rarely used and slow anyway. 00392 c.reserve(size); d.reserve(size); 00393 for(vector<Theorem>::const_iterator i = thms.begin(), iend = thms.end(); 00394 i != iend; ++i) { 00395 // Check that t is c == d or c IFF d 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 // Collect the pieces 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 // Proof compaction: if e1 == e2, use reflexivity 00409 if(e1 == e2) return reflexivityRule(e1); 00410 // Otherwise, do the work 00411 Assumptions a(thms); 00412 Proof pf; 00413 if(withProof()) 00414 // FIXME: this rule is not directly expressible in flea 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 // Check that theorems are of the form c_i == d_i and collect 00438 // vectors of c_i's and d_i's and the vector of proofs 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 // Check that t is c == d or c IFF d 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 // Collect the pieces 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 // Check that t is c == d or c IFF d 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 // + "\n op = " + ((Op) e.getOp).toString()); 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 // Get the arity of the expression 00514 int size = e.arity(); 00515 00516 // The changed must be within the arity 00517 DebugAssert(size >= changed, "Bad call to substitutivityRule"); 00518 00519 // Check that t is c == d or c IFF d 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 // Collect the new sub-expressions 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 // Construct the new expression 00532 Expr e2(e.getOp(), c); 00533 00534 // Check if they are the same 00535 IF_DEBUG(if(e == e2) { 00536 ostream& os = debugger.getOS(); 00537 os << "substitutivityRule: e = " << e << "\n e2 = " << e2 << endl; 00538 }) 00539 00540 // The new expressions must not be equal 00541 DebugAssert(e != e2, "substitutivityRule should not be called in this case:\ne = "+e.toString()); 00542 00543 // Construct the proof object 00544 Proof pf; 00545 Assumptions a(thm); 00546 if(withProof()) { 00547 // Check that t is c == d or c IFF d 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 // Return the resulting theorem 00554 Theorem res = newRWTheorem(e, e2, a, pf);; 00555 res.setSubst(); 00556 return res; 00557 } 00558 00559 00560 // |- e, |- !e ==> |- FALSE 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 // e ==> e IFF TRUE 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 // e ==> !e IFF FALSE 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 // e IFF TRUE ==> e 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 // e IFF FALSE ==> !e 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 // e1 <=> e2 ==> ~e1 <=> ~e2 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 // !!e ==> e 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 // Avoid e1.getExpr(), it may cause unneeded Expr creation 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 // e1 AND (e1 IMPLIES e2) ==> e2 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 // Avoid e1.getExpr(), it may cause unneeded Expr creation 00704 // if (impl[0] == e2) return e1; // this line commented by yeting because of proof translation 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 // AND(e_0,...e_{n-1}) ==> e_i 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 //! e1, e2 ==> AND(e1, e2) 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 if(withProof()) { 00749 vector<Proof> pfs; 00750 for(vector<Theorem>::const_iterator i=es.begin(), iend=es.end(); 00751 i!=iend; ++i) 00752 pfs.push_back(i->getProof()); 00753 // pf = newPf("andI", andExpr(kids), pfs); 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 // G,a1,...,an |- phi 00773 // ------------------------------------------------- 00774 // G |- (a1 & ... & an) -> phi 00775 Theorem CommonTheoremProducer::implIntro(const Theorem& phi, 00776 const std::vector<Expr>& assump) { 00777 bool checkProofs(CHECK_PROOFS); 00778 // This rule only makes sense when runnnig with assumptions 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 // Proof compaction: trivial derivation 00797 if(assump.size() == 0) return phi; 00798 00799 Assumptions a(phiAssump - assump); 00800 Proof pf; 00801 if(withProof()) { 00802 vector<Proof> u; // Proof labels for assumptions 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 // Arguments to the proof rule: 00809 // impl_intro_3(phi, a1,...,an,tcc1,...tccn,pf_tcc1,...pf_tccn, 00810 // [lambda(a1,...,an): pf_phi]) 00811 vector<Expr> args; 00812 vector<Proof> pfs; 00813 args.push_back(phi.getExpr()); 00814 args.insert(args.end(), assump.begin(), assump.end()); 00815 // Lambda-abstraction of pf_phi 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 // e1 => e2 ==> ~e2 => ~e1 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 // ==> ITE(TRUE, e1, e2) == e1 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 // ==> ITE(FALSE, e1, e2) == e2 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 // ==> ITE(c, e, e) == e 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 // NOT e ==> e IFF FALSE 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 // Make it an atomic rule (more efficient) 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 // e1 XOR e2 ==> e1 IFF (NOT e2) 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 // ==> IFF(e1,e2) IFF <simplified expr> 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 // ==> AND(e_1,...,e_n) IFF <simplified expr> 00984 // 1) if e_i = FALSE then return FALSE 00985 // 2) if e_i = TRUE, remove it from children 00986 // 3) if e_i = AND(f_1,...,f_m) then AND(e_1,...,e_{i-1},f_1,...,f_m,e_{i+1},...,e_n) 00987 // 4) if n=0 return TRUE 00988 // 5) if n=1 return e_1 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(); // All newKids were TRUE 01011 else if (newKids.size() == 1) 01012 res = newKids.begin()->first; // The only child 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 // ==> OR(e1,e2) IFF <simplified expr> 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(); // All kids were FALSE 01050 else if (newKids.size() == 1) res = newKids.begin()->first; // The only child 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 // ==> NOT TRUE IFF FALSE 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 // ==> NOT FALSE IFF TRUE 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 // ==> (NOT NOT e) IFF e, takes !!e 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 //! ==> NOT FORALL (vars): e IFF EXISTS (vars) NOT e 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 //! ==> NOT EXISTS (vars): e IFF FORALL (vars) NOT e 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 // Create the Skolem constant appropriately 01188 Expr skolV(e.skolemExpr(0)); 01189 Type tp(e.getVars()[0].getType()); 01190 skolV.setType(tp); 01191 // Skolemized expression 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 // This rule is sound for all expressions phi 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);//d_coreSatAPI->getBottomScope()); 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 // First, look up the cache 01252 CDMap<Expr, Theorem>::iterator i=d_skolemVars.find(e), 01253 iend=d_skolemVars.end(); 01254 if(i!=iend) return (*i).second; 01255 // Not in cache; create a new one 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 // Check if we have a corresponding skolemized version already 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); //d_coreSatAPI->getBottomScope()); 01270 } 01271 thm = iffMP(thm, skolThm); 01272 d_skolemVars.insert(e, thm, 0); //d_coreSatAPI->getBottomScope()); 01273 return thm; 01274 } 01275 01276 01277 // Derived Rules 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 }