CVC3
|
00001 /*****************************************************************************/ 00002 /*! 00003 * \file theorem.cpp 00004 * 00005 * Author: Sergey Berezin 00006 * 00007 * Created: Dec 10 00:37:49 GMT 2002 00008 * 00009 * <hr> 00010 * 00011 * License to use, copy, modify, sell and/or distribute this software 00012 * and its documentation for any purpose is hereby granted without 00013 * royalty, subject to the terms and conditions defined in the \ref 00014 * LICENSE file provided with this distribution. 00015 * 00016 * <hr> 00017 * 00018 */ 00019 /*****************************************************************************/ 00020 // CLASS: Theorem 00021 // 00022 // AUTHOR: Sergey Berezin, 07/05/02 00023 // 00024 // See theorem.h file for more information. 00025 /////////////////////////////////////////////////////////////////////////////// 00026 00027 #include "theorem.h" 00028 #include "theorem_value.h" 00029 #include "command_line_flags.h" 00030 00031 namespace CVC3 { 00032 using namespace std; 00033 00034 //! Compare Theorems by their expressions. Return -1, 0, or 1. 00035 /*! 00036 * This is an arbitrary total ordering on Theorems. For 00037 * simplicity, we define rewrite theorems (e1 = e2 or e1 <=> e2) to 00038 * be smaller than other theorems. 00039 */ 00040 /* 00041 int compare(const Theorem& t1, const Theorem& t2) { 00042 return compare(t1.getExpr(), t2.getExpr()); 00043 } 00044 */ 00045 int compare(const Theorem& t1, const Theorem& t2) { 00046 if(t1.d_thm == t2.d_thm) return 0; 00047 if(t1.isNull()) return -1; // Null Theorem is less than other theorems 00048 if(t2.isNull()) return 1; 00049 00050 bool rw1(t1.isRewrite()), rw2(t2.isRewrite()); 00051 00052 if(!rw2) return compare(t1, t2.getExpr()); 00053 else if(!rw1) return -compare(t2, t1.getExpr()); 00054 else { 00055 int res(compare(t1.getLHS(), t2.getLHS())); 00056 if(res==0) res = compare(t1.getRHS(), t2.getRHS()); 00057 return res; 00058 } 00059 } 00060 /* 00061 int compare(const Theorem& t1, const Expr& e2) { 00062 return compare(t1.getExpr(), e2); 00063 } 00064 */ 00065 int compare(const Theorem& t1, const Expr& e2) { 00066 bool rw1(t1.isRewrite()), rw2(e2.isEq() || e2.isIff()); 00067 if(!rw1) { 00068 const Expr& e1 = t1.getExpr(); 00069 rw1 = (e1.isEq() || e1.isIff()); 00070 } 00071 if(rw1) { 00072 if(rw2) { 00073 int res(compare(t1.getLHS(), e2[0])); 00074 if(res==0) res = compare(t1.getRHS(), e2[1]); 00075 return res; 00076 } else return -1; 00077 } else { 00078 if(rw2) return 1; 00079 else return compare(t1.getExpr(), e2); 00080 } 00081 } 00082 00083 int compareByPtr(const Theorem& t1, const Theorem& t2) { 00084 if(t1.d_thm == t2.d_thm) return 0; 00085 else if(t1.d_thm < t2.d_thm) return -1; 00086 else return 1; 00087 } 00088 00089 00090 // Assignment operator 00091 Theorem& Theorem::operator=(const Theorem& th) { 00092 // Handle self-assignment 00093 if(this == &th) return *this; 00094 if(d_thm == th.d_thm) return *this; 00095 00096 long tmp = th.d_thm; 00097 00098 // Increase the refcount on th 00099 if (tmp & 0x1) { 00100 TheoremValue* tv = (TheoremValue*) (tmp & (~(0x1))); 00101 DebugAssert(tv->d_refcount > 0, 00102 "Theorem::operator=: invariant violated"); 00103 ++(tv->d_refcount); 00104 } 00105 else if (tmp != 0) { 00106 th.exprValue()->incRefcount(); 00107 } 00108 00109 // Decrease the refcount on this 00110 if (d_thm & 0x1) { 00111 TheoremValue* tv = thm(); 00112 DebugAssert(tv->d_refcount > 0, 00113 "Theorem::operator=: invariant violated"); 00114 if(--(tv->d_refcount) == 0) { 00115 MemoryManager* mm = tv->getMM(); 00116 delete tv; 00117 mm->deleteData(tv); 00118 } 00119 } 00120 else if (d_thm != 0) { 00121 exprValue()->decRefcount(); 00122 } 00123 00124 d_thm = tmp; 00125 00126 return *this; 00127 } 00128 00129 00130 // Constructors 00131 Theorem::Theorem(TheoremManager* tm, const Expr &thm, 00132 const Assumptions& assump, const Proof& pf, 00133 bool isAssump, int scope) { 00134 TheoremValue* tv; 00135 if (thm.isEq() || thm.isIff()) { 00136 if (thm[0] == thm[1]) { 00137 d_expr = thm[0].d_expr; 00138 d_expr->incRefcount(); 00139 return; 00140 } 00141 tv = new(tm->getRWMM()) RWTheoremValue(tm, thm, assump, pf, isAssump, scope); 00142 } 00143 else 00144 tv = new(tm->getMM()) RegTheoremValue(tm, thm, assump, pf, isAssump, scope); 00145 tv->d_refcount++; 00146 d_thm = ((intptr_t)tv)|0x1; 00147 // TRACE("theorem", "Theorem(e) => ", *this, ""); 00148 DebugAssert(!withProof() || !pf.isNull(), 00149 "Null proof in theorem:\n"+toString()); 00150 } 00151 00152 Theorem::Theorem(TheoremManager* tm, const Expr& lhs, const Expr& rhs, 00153 const Assumptions& assump, const Proof& pf, bool isAssump, 00154 int scope) { 00155 if (lhs == rhs) { 00156 d_expr = lhs.d_expr; 00157 d_expr->incRefcount(); 00158 return; 00159 } 00160 TheoremValue* tv = new(tm->getRWMM()) 00161 RWTheoremValue(tm, lhs, rhs, assump, pf, isAssump, scope); 00162 tv->d_refcount++; 00163 d_thm = ((long)tv)|0x1; 00164 DebugAssert(!withProof() || !pf.isNull(), 00165 "Null proof in theorem:\n"+toString()); 00166 } 00167 00168 00169 // Copy constructor 00170 Theorem::Theorem(const Theorem &th) : d_thm(th.d_thm) { 00171 if (d_thm & 0x1) { 00172 DebugAssert(thm()->d_refcount > 0, 00173 "Theorem(const Theorem&): refcount = " 00174 + int2string(thm()->d_refcount)); 00175 thm()->d_refcount++; 00176 // TRACE("theorem", "Theorem(Theorem&) => ", *this, ""); 00177 } else if (d_thm != 0) { 00178 exprValue()->incRefcount(); 00179 } 00180 } 00181 00182 Theorem::Theorem(const Expr& e) : d_expr(e.d_expr) 00183 { 00184 d_expr->incRefcount(); 00185 } 00186 00187 // Destructor 00188 Theorem::~Theorem() { 00189 if (d_thm & 0x1) { 00190 TheoremValue* tv = thm(); 00191 // TRACE("theorem", "~Theorem(", *this, ") {"); 00192 IF_DEBUG(FatalAssert(tv->d_refcount > 0, 00193 "~Theorem(): refcount = " 00194 + int2string(tv->d_refcount));) 00195 if((--tv->d_refcount) == 0) { 00196 // TRACE_MSG("theorem", "~Theorem(): deleting"); 00197 MemoryManager* mm = tv->getMM(); 00198 delete tv; 00199 mm->deleteData(tv); 00200 } 00201 } 00202 else if (d_thm != 0) { 00203 exprValue()->decRefcount(); 00204 } 00205 } 00206 00207 void Theorem::printx() const { getExpr().print(); } 00208 void Theorem::printxnodag() const { getExpr().printnodag(); } 00209 void Theorem::pprintx() const { getExpr().pprint(); } 00210 void Theorem::pprintxnodag() const { getExpr().pprintnodag(); } 00211 void Theorem::print() const { cout << toString() << endl; } 00212 00213 // Test if we are running in a proof production mode and with assumptions 00214 bool Theorem::withProof() const { 00215 if (isRefl()) return exprValue()->d_em->getTM()->withProof(); 00216 return thm()->d_tm->withProof(); 00217 } 00218 00219 bool Theorem::withAssumptions() const { 00220 if (isRefl()) return exprValue()->d_em->getTM()->withAssumptions(); 00221 return thm()->d_tm->withAssumptions(); 00222 } 00223 00224 bool Theorem::isRewrite() const { 00225 DebugAssert(!isNull(), "CVC3::Theorem::isRewrite(): we are Null"); 00226 return isRefl() || thm()->isRewrite(); 00227 } 00228 00229 // Return the theorem value as an Expr 00230 Expr Theorem::getExpr() const { 00231 DebugAssert(!isNull(), "CVC3::Theorem::getExpr(): we are Null"); 00232 if (isRefl()) { 00233 Expr e(exprValue()); 00234 if (e.isTerm()) return e.eqExpr(e); 00235 else return e.iffExpr(e); 00236 } 00237 else return thm()->getExpr(); 00238 } 00239 00240 const Expr& Theorem::getLHS() const { 00241 DebugAssert(!isNull(), "CVC3::Theorem::getLHS: we are Null"); 00242 if (isRefl()) return *((Expr*)(&d_expr)); 00243 else return thm()->getLHS(); 00244 } 00245 00246 const Expr& Theorem::getRHS() const { 00247 DebugAssert(!isNull(), "CVC3::Theorem::getRHS: we are Null"); 00248 if (isRefl()) return *((Expr*)(&d_expr)); 00249 else return thm()->getRHS(); 00250 } 00251 00252 // Return the assumptions. 00253 // void Theorem::getAssumptions(Assumptions& a) const 00254 // { 00255 // a = getAssumptionsRef(); 00256 // } 00257 00258 00259 void Theorem::getAssumptionsRec(set<Expr>& assumptions) const 00260 { 00261 if (isRefl() || isFlagged()) return; 00262 setFlag(); 00263 if(isAssump()) { 00264 assumptions.insert(getExpr()); 00265 } 00266 else { 00267 const Assumptions& a = getAssumptionsRef(); 00268 for(Assumptions::iterator i=a.begin(), iend=a.end(); i!=iend; ++i) 00269 (*i).getAssumptionsRec(assumptions); 00270 } 00271 } 00272 00273 00274 void Theorem::getLeafAssumptions(vector<Expr>& assumptions, 00275 bool negate) const 00276 { 00277 if (isNull() || isRefl()) return; 00278 set<Expr> assumpSet; 00279 clearAllFlags(); 00280 getAssumptionsRec(assumpSet); 00281 // Order assumptions by their creation time 00282 for(set<Expr>::iterator i=assumpSet.begin(), iend=assumpSet.end(); 00283 i!=iend; ++i) 00284 assumptions.push_back(negate ? (*i).negate() : *i); 00285 } 00286 00287 00288 void Theorem::GetSatAssumptionsRec(vector<Theorem>& assumptions) const 00289 { 00290 DebugAssert(!isRefl() && !isFlagged(), "Invariant violated"); 00291 setFlag(); 00292 Expr e = getExpr(); 00293 if (e.isAbsLiteral()) { 00294 if (isAssump() || 00295 e.isRegisteredAtom() || 00296 (e.isNot() && e[0].isRegisteredAtom())) { 00297 assumptions.push_back(*this); 00298 return; 00299 } 00300 } 00301 const Assumptions& a = getAssumptionsRef(); 00302 for (Assumptions::iterator i = a.begin(); i != a.end(); i++) { 00303 if ((*i).isRefl() || (*i).isFlagged()) continue; 00304 (*i).GetSatAssumptionsRec(assumptions); 00305 } 00306 } 00307 00308 00309 void Theorem::GetSatAssumptions(vector<Theorem>& assumptions) const { 00310 DebugAssert(!isRefl() && !isFlagged(), "Invariant violated"); 00311 setFlag(); 00312 const Assumptions& a = getAssumptionsRef(); 00313 for (Assumptions::iterator i = a.begin(); i != a.end(); i++) { 00314 if ((*i).isRefl() || (*i).isFlagged()) continue; 00315 (*i).GetSatAssumptionsRec(assumptions); 00316 } 00317 } 00318 00319 00320 void Theorem::getAssumptionsAndCongRec(set<Expr>& assumptions, 00321 vector<Expr>& congruences) const 00322 { 00323 if (isRefl() || isFlagged()) return; 00324 setFlag(); 00325 if(isAssump()) { 00326 assumptions.insert(getExpr()); 00327 } 00328 else { 00329 const Assumptions& a = getAssumptionsRef(); 00330 if (isSubst() && a.size() == 1) { 00331 vector<Expr> hyp; 00332 const Theorem& thm = *(a.begin()); 00333 thm.getAssumptionsAndCongRec(assumptions, congruences); 00334 if (thm.isRewrite() && thm.getLHS().isTerm() 00335 && thm.getLHS().isAtomic() && thm.getRHS().isAtomic() && 00336 !thm.isRefl()) { 00337 hyp.push_back(!thm.getExpr()); 00338 } 00339 else return; 00340 const Expr& e = getExpr(); 00341 if (e.isAtomicFormula()) { 00342 if (e[0] < e[1]) { 00343 hyp.push_back(e[1].eqExpr(e[0])); 00344 } 00345 else { 00346 hyp.push_back(e); 00347 } 00348 congruences.push_back(Expr(OR, hyp)); 00349 } 00350 else if (e[0].isAtomicFormula() && !e[0].isEq()) { 00351 hyp.push_back(!e[0]); 00352 hyp.push_back(e[1]); 00353 congruences.push_back(Expr(OR, hyp)); 00354 hyp.pop_back(); 00355 hyp.pop_back(); 00356 hyp.push_back(e[0]); 00357 hyp.push_back(!e[1]); 00358 congruences.push_back(Expr(OR, hyp)); 00359 } 00360 } 00361 else { 00362 Assumptions::iterator i=a.begin(), iend=a.end(); 00363 for(; i!=iend; ++i) 00364 (*i).getAssumptionsAndCongRec(assumptions, congruences); 00365 } 00366 } 00367 } 00368 00369 00370 void Theorem::getAssumptionsAndCong(vector<Expr>& assumptions, 00371 vector<Expr>& congruences, 00372 bool negate) const 00373 { 00374 if (isNull() || isRefl()) return; 00375 set<Expr> assumpSet; 00376 clearAllFlags(); 00377 getAssumptionsAndCongRec(assumpSet, congruences); 00378 // Order assumptions by their creation time 00379 for(set<Expr>::iterator i=assumpSet.begin(), iend=assumpSet.end(); 00380 i!=iend; ++i) 00381 assumptions.push_back(negate ? (*i).negate() : *i); 00382 } 00383 00384 00385 const Assumptions& Theorem::getAssumptionsRef() const 00386 { 00387 DebugAssert(!isNull(), "CVC3::Theorem::getAssumptionsRef: we are Null"); 00388 if (!isRefl()) { 00389 return thm()->getAssumptionsRef(); 00390 } 00391 else return Assumptions::emptyAssump(); 00392 } 00393 00394 00395 bool Theorem::isAssump() const { 00396 DebugAssert(!isNull(), "CVC3::Theorem::isAssump: we are Null"); 00397 return isRefl() ? false : thm()->isAssump(); 00398 } 00399 00400 // Return the proof of the theorem. If running without proofs, 00401 // return the Null proof. 00402 Proof Theorem::getProof() const { 00403 static Proof null; 00404 DebugAssert(!isNull(), "CVC3::Theorem::getProof: we are Null"); 00405 if (isRefl()) { 00406 return Proof(Expr(PF_APPLY, 00407 exprValue()->d_em->newVarExpr("refl"), 00408 Expr(exprValue()))); 00409 } 00410 else if (withProof() == true) 00411 return thm()->getProof(); 00412 else 00413 return null; 00414 } 00415 00416 bool Theorem::isFlagged() const { 00417 DebugAssert(!isNull(), "CVC3::Theorem::isFlagged: we are Null"); 00418 if (isRefl()) return exprValue()->d_em->getTM()->isFlagged((long)d_expr); 00419 else return thm()->isFlagged(); 00420 } 00421 00422 void Theorem::clearAllFlags() const { 00423 DebugAssert(!isNull(), "CVC3::Theorem::clearAllFlags: we are Null"); 00424 if (isRefl()) { 00425 exprValue()->d_em->getTM()->clearAllFlags(); 00426 } else thm()->clearAllFlags(); 00427 } 00428 00429 void Theorem::setFlag() const { 00430 DebugAssert(!isNull(), "CVC3::Theorem::setFlag: we are Null"); 00431 if (isRefl()) exprValue()->d_em->getTM()->setFlag((long)d_expr); 00432 else thm()->setFlag(); 00433 } 00434 00435 void Theorem::setCachedValue(int value) const { 00436 DebugAssert(!isNull(), "CVC3::Theorem::setCachedValue: we are Null"); 00437 if (isRefl()) exprValue()->d_em->getTM()->setCachedValue((long)d_expr, value); 00438 else thm()->setCachedValue(value); 00439 } 00440 00441 int Theorem::getCachedValue() const { 00442 DebugAssert(!isNull(), "CVC3::Theorem::getCachedValue: we are Null"); 00443 if (isRefl()) return exprValue()->d_em->getTM()->getCachedValue((long)d_expr); 00444 return thm()->getCachedValue(); 00445 } 00446 00447 void Theorem::setSubst() const { 00448 DebugAssert(!isNull() && !isRefl(), "CVC3::Theorem::setSubst: invalid thm"); 00449 thm()->setSubst(); 00450 } 00451 00452 bool Theorem::isSubst() const { 00453 DebugAssert(!isNull(), "CVC3::Theorem::isSubst: we are Null"); 00454 if (isRefl()) return false; 00455 return thm()->isSubst(); 00456 } 00457 00458 void Theorem::setExpandFlag(bool val) const { 00459 DebugAssert(!isNull(), "CVC3::Theorem::setExpandFlag: we are Null"); 00460 if (isRefl()) exprValue()->d_em->getTM()->setExpandFlag((long)d_expr, val); 00461 thm()->setExpandFlag(val); 00462 } 00463 00464 bool Theorem::getExpandFlag() const { 00465 DebugAssert(!isNull(), "CVC3::Theorem::getExpandFlag: we are Null"); 00466 if (isRefl()) return exprValue()->d_em->getTM()->getExpandFlag((long)d_expr); 00467 return thm()->getExpandFlag(); 00468 } 00469 00470 void Theorem::setLitFlag(bool val) const { 00471 DebugAssert(!isNull(), "CVC3::Theorem::setLitFlag: we are Null"); 00472 if (isRefl()) exprValue()->d_em->getTM()->setLitFlag((long)d_expr, val); 00473 thm()->setLitFlag(val); 00474 } 00475 00476 bool Theorem::getLitFlag() const { 00477 DebugAssert(!isNull(), "CVC3::Theorem::getLitFlag: we are Null"); 00478 if (isRefl()) return exprValue()->d_em->getTM()->getLitFlag((long)d_expr); 00479 return thm()->getLitFlag(); 00480 } 00481 00482 bool Theorem::isAbsLiteral() const { 00483 return getExpr().isAbsLiteral(); 00484 } 00485 00486 int Theorem::getScope() const { 00487 DebugAssert(!isNull(), "CVC3::Theorem::getScope: we are Null"); 00488 return isRefl() ? 0 : thm()->getScope(); 00489 } 00490 00491 unsigned Theorem::getQuantLevel() const { 00492 DebugAssert(!isNull(), "CVC3::Theorem::getQuantLevel: we are Null"); 00493 TRACE("quant-level", "isRefl? ", isRefl(), ""); 00494 return isRefl() ? 0 : thm()->getQuantLevel(); 00495 } 00496 00497 unsigned Theorem::getQuantLevelDebug() const { 00498 DebugAssert(!isNull(), "CVC3::Theorem::getQuantLevel: we are Null"); 00499 TRACE("quant-level", "isRefl? ", isRefl(), ""); 00500 return isRefl() ? 0 : thm()->getQuantLevelDebug(); 00501 } 00502 00503 00504 void Theorem::setQuantLevel(unsigned level) { 00505 DebugAssert(!isNull(), "CVC3::Theorem::setQuantLevel: we are Null"); 00506 // DebugAssert(!isRefl(), "CVC3::Theorem::setQuantLevel: we are Refl"); 00507 if (isRefl()) return; 00508 thm()->setQuantLevel(level); 00509 } 00510 00511 size_t Theorem::hash() const { 00512 static std::hash<long int> h; 00513 return h(d_thm); 00514 } 00515 00516 void Theorem::recursivePrint(int& i) const { 00517 const Assumptions::iterator iend = getAssumptionsRef().end(); 00518 Assumptions::iterator it = getAssumptionsRef().begin(); 00519 if (!isAssump()) { 00520 for (; it != iend; ++it) { 00521 if (it->isFlagged()) continue; 00522 it->recursivePrint(i); 00523 it->setFlag(); 00524 } 00525 } 00526 00527 setCachedValue(i++); 00528 cout << "[" << getCachedValue() 00529 << "]@" << getScope() << "\tTheorem: {"; 00530 00531 if (isAssump()) { 00532 cout << "assump"; 00533 } 00534 else if (getAssumptionsRef().empty()) { 00535 cout << "empty"; 00536 } 00537 else { 00538 for (it = getAssumptionsRef().begin(); it != iend; ++it) { 00539 if (it != getAssumptionsRef().begin()) cout << ", "; 00540 cout << "[" << it->getCachedValue() << "]" ; 00541 } 00542 } 00543 cout << "}" << endl << "\t\t|- " << getExpr(); 00544 if (isSubst()) cout << " [[Subst]]"; 00545 cout << endl; 00546 } 00547 00548 00549 // Return the scope level at which this theorem was created 00550 // int Theorem::getScope() const { 00551 // DebugAssert(!isNull(), "CVC3::Theorem::getScope: we are Null"); 00552 // return thm()->getScope(); 00553 // } 00554 00555 // Assumptions Theorem::getUserAssumptions() const { 00556 // ExprMap<Theorem> em; 00557 // Assumptions a = getAssumptionsCopy(); 00558 00559 // collectAssumptions(a, em); 00560 00561 // return a; 00562 // } 00563 00564 // void collectAssumptions(Assumptions &a, ExprMap<Theorem> em ) const { 00565 // if (isAssump()) { 00566 // // cache? 00567 // return; 00568 // } 00569 00570 // const Assumptions a2 = thm()->getAssumptions(); 00571 // a.add(a2); 00572 // Assumptions::iterator a2begin = a2.begin(); 00573 // const Assumptions::iterator a2end = a2.end(); 00574 00575 00576 // } 00577 00578 00579 // Printing Theorem 00580 ostream& Theorem::print(ostream& os, const string& name) const { 00581 if(isNull()) return os << name << "(Null)"; 00582 ExprManager *em = getExpr().getEM(); 00583 if (isRefl()) os << getExpr(); 00584 else if (withAssumptions()) { 00585 em->incIndent(name.size()+2); 00586 os << name << "([" << thm() << "#" << thm()->d_refcount << "]@" 00587 << getScope() << "\n["; 00588 if(isAssump()) os << "Assump"; 00589 else { 00590 if(thm()->d_tm->getFlags()["print-assump"].getBool() 00591 && em->isActive()) 00592 os << getAssumptionsRef(); 00593 else 00594 os << "<assumptions>"; 00595 } 00596 os << "]\n |--- "; 00597 em->indent(7); 00598 if(em->isActive()) os << getExpr(); 00599 else os << "(being destructed)"; 00600 if(withProof()) 00601 os << "\n Proof = " << getProof(); 00602 return os << ")"; 00603 } 00604 else { 00605 em->incIndent(name.size()+1); 00606 os << name << "("; 00607 if(em->isActive()) os << getExpr(); 00608 else os << "being destructed"; 00609 return os << ")"; 00610 } 00611 return os; 00612 } 00613 00614 00615 } // end of namespace CVC3