CVC3
|
00001 /*****************************************************************************/ 00002 /*! 00003 * \file theory_core.cpp 00004 * 00005 * Author: Clark Barrett, Vijay Ganesh (CNF converter) 00006 * 00007 * Created: Thu Jan 30 16:57:52 2003 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 00021 #include <locale> 00022 #include <cctype> 00023 #include <ctime> 00024 #include "command_line_flags.h" 00025 #include "expr.h" 00026 #include "notifylist.h" 00027 #include "pretty_printer.h" 00028 #include "common_proof_rules.h" 00029 #include "parser_exception.h" 00030 #include "typecheck_exception.h" 00031 #include "smtlib_exception.h" 00032 #include "eval_exception.h" 00033 #include "theory_core.h" 00034 #include "expr_transform.h" 00035 #include "core_proof_rules.h" 00036 #include "theorem_manager.h" 00037 #include "translator.h" 00038 #include "theory_arith.h" // for isReal() tester 00039 00040 using namespace std; 00041 00042 00043 namespace CVC3 { 00044 00045 00046 //! Implementation of PrettyPrinter class 00047 /*! \ingroup PrettyPrinting */ 00048 class PrettyPrinterCore: public PrettyPrinter { 00049 private: 00050 TheoryCore *d_core; 00051 //! Disable the default constructor 00052 PrettyPrinterCore() { } 00053 public: 00054 //! Constructor 00055 PrettyPrinterCore(TheoryCore* core): d_core(core) { } 00056 ExprStream& print(ExprStream& os, const Expr& e) 00057 { 00058 if(e.isString()) 00059 return e.print(os); 00060 else if (e.isApply()) 00061 return d_core->theoryOf(e)->print(os, e); 00062 else if(d_core->hasTheory(e.getKind())) 00063 return d_core->theoryOf(e.getKind())->print(os, e); 00064 else 00065 return e.print(os); 00066 } 00067 }; 00068 00069 00070 class TypeComputerCore: public ExprManager::TypeComputer { 00071 TheoryCore *d_core; 00072 public: 00073 TypeComputerCore(TheoryCore* core): d_core(core) { } 00074 void computeType(const Expr& e) 00075 { 00076 DebugAssert(!e.isVar(), "Variables should have a type: "+e.toString()); 00077 Theory* i = d_core->theoryOf(e.getKind()); 00078 if (e.isApply()) i = d_core->theoryOf(e); 00079 i->computeType(e); 00080 DebugAssert(!e.lookupType().getExpr().isNull(), "Type not set by computeType"); 00081 } 00082 void checkType(const Expr& e) 00083 { 00084 if (!e.isType()) throw Exception 00085 ("Tried to use non-type as a type: "+e.toString()); 00086 d_core->theoryOf(e)->checkType(e); 00087 e.setValidType(); 00088 } 00089 Cardinality finiteTypeInfo(Expr& e, Unsigned& n, 00090 bool enumerate, bool computeSize) 00091 { 00092 DebugAssert(e.isType(), "finiteTypeInfo called on non-type"); 00093 return d_core->theoryOf(e)->finiteTypeInfo(e, n, enumerate, computeSize); 00094 } 00095 }; 00096 00097 00098 ostream& operator<<(ostream& os, const NotifyList& l) 00099 { 00100 os << "NotifyList(\n"; 00101 for(size_t i=0,iend=l.size(); i<iend; ++i) { 00102 os << "[" << l.getTheory(i)->getName() << ", " << l.getExpr(i) << "]\n"; 00103 } 00104 return os << ")"; 00105 } 00106 00107 00108 } 00109 00110 00111 using namespace CVC3; 00112 00113 00114 /*****************************************************************************/ 00115 /* 00116 * Private helper functions 00117 */ 00118 /*****************************************************************************/ 00119 00120 00121 bool TheoryCore::processFactQueue(EffortLevel effort) 00122 { 00123 Theorem thm; 00124 vector<Theory*>::iterator i, iend = d_theories.end(); 00125 bool lemmasAdded = false; 00126 do { 00127 processUpdates(); 00128 while (!d_queue.empty() && !d_inconsistent && !timeLimitReached()) { 00129 thm = d_queue.front(); 00130 d_queue.pop(); 00131 assertFactCore(thm); 00132 processUpdates(); 00133 }; 00134 00135 if (d_inconsistent) break; 00136 00137 while (!d_queueSE.empty() && !timeLimitReached()) { 00138 // Copy a Theorem by value, to guarantee valid reference down 00139 // the call chain 00140 lemmasAdded = true; 00141 Theorem thm(d_queueSE.back()); 00142 d_queueSE.pop_back(); 00143 d_coreSatAPI->addLemma(thm); 00144 } 00145 00146 if (effort > LOW) { 00147 for(i = d_theories.begin(); d_update_thms.empty() && d_queue.empty() && i != iend && !d_inconsistent && !timeLimitReached(); ++i) { 00148 (*i)->checkSat(effort == FULL && !lemmasAdded); 00149 } 00150 } 00151 } while ((!d_queue.empty() || !d_update_thms.empty()) && !d_inconsistent && !timeLimitReached()); 00152 00153 if (d_inconsistent) { 00154 d_update_thms.clear(); 00155 d_update_data.clear(); 00156 while(d_queue.size()) d_queue.pop(); 00157 d_queueSE.clear(); 00158 return false; 00159 } 00160 00161 if (timeLimitReached()) { 00162 // clear all work queues to satisfy invariants 00163 d_update_thms.clear(); 00164 d_update_data.clear(); 00165 while (!d_queue.empty()) d_queue.pop(); 00166 d_queueSE.clear(); 00167 } 00168 00169 return lemmasAdded; 00170 } 00171 00172 00173 void TheoryCore::processNotify(const Theorem& e, NotifyList *L) 00174 { 00175 ++d_inUpdate; 00176 DebugAssert(L, "Expected non-NULL notify list"); 00177 for(unsigned k = 0; k < L->size() && !d_inconsistent; ++k) { 00178 L->getTheory(k)->update(e, L->getExpr(k)); 00179 } 00180 --d_inUpdate; 00181 } 00182 00183 00184 Theorem TheoryCore::simplify(const Expr& e) 00185 { 00186 DebugAssert(d_simpStack.count(e) == 0, "TheoryCore::simplify: loop detected over e =\n" 00187 +e.toString()); 00188 DebugAssert(d_simpStack.size() < 10000, 00189 "TheoryCore::simplify: too deep recursion depth"); 00190 IF_DEBUG(d_simpStack[e] = true;) 00191 00192 // Normally, if an expr has a find, we don't need to simplify, just return the find. 00193 // However, if we are in the middle of an update, the find may not yet be updated, so 00194 // we should do a full simplify. The exception is expressions like 00195 // uninterp. functions or reads that use a congruence closure algorithm that 00196 // relies on not simplifying inside of expressions that have finds. 00197 if (e.hasFind()) { 00198 DebugAssert((find(e).getRHS().hasFind() && find(e).getRHS().isTerm()) 00199 || find(e).getRHS().isTrue() 00200 || find(e).getRHS().isFalse(), "Unexpected find pointer"); 00201 if (d_inUpdate) { 00202 if (e.usesCC()) { 00203 Theorem thm = find(e); 00204 if (!thm.isRefl()) { 00205 thm = transitivityRule(thm, simplify(thm.getRHS())); 00206 } 00207 IF_DEBUG(d_simpStack.erase(e);) 00208 return thm; 00209 } 00210 } 00211 else { 00212 IF_DEBUG(d_simpStack.erase(e);) 00213 return find(e); 00214 } 00215 } 00216 00217 if(e.validSimpCache()) { 00218 IF_DEBUG(d_simpStack.erase(e);) 00219 return e.getSimpCache(); 00220 } 00221 00222 Theorem thm; 00223 if (e.isVar()) { 00224 thm = rewriteCore(e); 00225 } 00226 else { 00227 thm = rewriteCore(theoryOf(e.getOpKind())->simplifyOp(e)); 00228 } 00229 00230 const Expr& e2 = thm.getRHS(); 00231 #ifdef _CVC3_DEBUG_MODE 00232 if (!e2.usesCC()) { //2.isTerm() || !e2.hasFind()) { 00233 // The rewriter should guarantee that all of its children are simplified. 00234 for (int k=0; k<e2.arity(); ++k) { 00235 Expr simplified(simplify(e2[k]).getRHS()); 00236 DebugAssert(e2[k]==simplified,"Simplify Error 1:\n e2[k="+int2string(k) 00237 +"] = " 00238 +e2[k].toString() + "\nSimplified = " 00239 +simplified.toString() 00240 +"\ne2 = "+e2.toString()); 00241 } 00242 } 00243 Expr rewritten(rewriteCore(e2).getRHS()); 00244 DebugAssert(e2==rewritten,"Simplify Error 2: e2 = \n" 00245 +e2.toString() + "\nSimplified rewritten = \n" 00246 +rewritten.toString()); 00247 #endif 00248 e.setSimpCache(thm); 00249 if (e != e2 && !e2.hasFind()) { 00250 e2.setSimpCache(reflexivityRule(e2)); 00251 } 00252 IF_DEBUG(d_simpStack.erase(e);) 00253 return thm; 00254 } 00255 00256 00257 Theorem TheoryCore::rewriteCore(const Theorem& e) 00258 { 00259 DebugAssert(e.isRewrite(), 00260 "rewriteCore(thm): not equality or iff:\n " + e.toString()); 00261 return transitivityRule(e, rewriteCore(e.getRHS())); 00262 } 00263 00264 00265 /* Recurse through s looking for atomic formulas (or terms in the case of 00266 * then/else branches of ite's) and use the notifylist mechanism to indicate 00267 * that the atomic formula e depends on these atomic formulas and terms. Used 00268 * by registerAtom. */ 00269 void TheoryCore::setupSubFormulas(const Expr& s, const Expr& e, 00270 const Theorem& thm) 00271 { 00272 if (s.isAtomic()) { 00273 setupTerm(s, theoryOf(s), thm); 00274 s.addToNotify(this, e); 00275 } 00276 else if (s.isAbsAtomicFormula()) { 00277 setupTerm(s, theoryOf(s), thm); 00278 for (int i = 0; i < s.arity(); ++i) { 00279 s[i].addToNotify(this, e); 00280 } 00281 if (s != e) s.addToNotify(this, e); 00282 } 00283 else { 00284 for (int i = 0; i < s.arity(); ++i) { 00285 setupSubFormulas(s[i], e, thm); 00286 } 00287 } 00288 } 00289 00290 00291 void TheoryCore::processUpdates() 00292 { 00293 Theorem e; 00294 Expr d; 00295 DebugAssert(d_update_thms.size() == d_update_data.size(), 00296 "Expected same size"); 00297 while (!d_inconsistent && !d_update_thms.empty()) { 00298 e = d_update_thms.back(); 00299 d_update_thms.pop_back(); 00300 d = d_update_data.back(); 00301 d_update_data.pop_back(); 00302 00303 DebugAssert(d.isAbsAtomicFormula(), "Expected atomic formula"); 00304 Theorem thm = simplify(d); 00305 if (thm.getRHS().isTrue()) { 00306 setFindLiteral(d_commonRules->iffTrueElim(thm)); 00307 } 00308 else if (thm.getRHS().isFalse()) { 00309 setFindLiteral(d_commonRules->iffFalseElim(thm)); 00310 } 00311 else { 00312 DebugAssert(e.isRewrite(), "Unexpected theorem in TheoryCore::update"); 00313 if (e.getRHS().getType().isBool()) continue; 00314 find(e.getRHS()).getRHS().addToNotify(this, d); 00315 if (thm.getRHS().isAbsAtomicFormula()) thm.getRHS().addToNotify(this, d); 00316 } 00317 } 00318 } 00319 00320 00321 void TheoryCore::assertFactCore(const Theorem& e) 00322 { 00323 IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');) 00324 TRACE("assertFactCore", indentStr, "AssertFactCore: ", e.getExpr().toString(PRESENTATION_LANG)); 00325 00326 Theorem estarThm(e); 00327 Expr estar = e.getExpr(); 00328 IF_DEBUG(Expr e2 = estar;) 00329 Theorem equiv = simplify(estar); 00330 if (!equiv.isRefl()) { 00331 estarThm = iffMP(e, equiv); 00332 // Make sure originally asserted atomic formulas have a find pointer 00333 if (!estar.isTrue() && estar.isAbsLiteral()) { 00334 setFindLiteral(e); 00335 } 00336 estar = estarThm.getExpr(); 00337 } 00338 if (estar.isAbsLiteral()) { 00339 if (estar.isEq()) { 00340 Theorem solvedThm(solve(estarThm)); 00341 if(estar != solvedThm.getExpr()) setFindLiteral(estarThm); 00342 if (!solvedThm.getExpr().isTrue()) 00343 assertEqualities(solvedThm); 00344 } 00345 else if (estar.isFalse()) { 00346 IF_DEBUG(debugger.counter("conflicts from simplifier")++;) 00347 setInconsistent(estarThm); 00348 } 00349 else if (!estar.isTrue()) { 00350 assertFormula(estarThm); 00351 } 00352 else { 00353 // estar is true, nothing will be done 00354 // Make sure equivalence classes of equations between two terms with finds get merged 00355 // We skip this check for now because unsolvable nonlinear equations bring up this kind of 00356 // problems, i.e. x^2 + y^2 = z^2 is not solved, it is true, but the find of LHS and RHS are 00357 // different 00358 if (!incomplete() && e.isRewrite() && 00359 e.getLHS().hasFind() && e.getRHS().hasFind() && 00360 find(e.getLHS()).getRHS() != find(e.getRHS()).getRHS()) { 00361 TRACE("assertFactCore", "Problem (LHS of): ", e.getExpr(), ""); 00362 TRACE("assertFactCore", find(e.getLHS()).getRHS(), " vs ", find(e.getRHS()).getRHS()); 00363 IF_DEBUG(cerr << "Warning: Equivalence classes didn't get merged" << endl;) 00364 } 00365 } 00366 } else if (estar.isAnd()) { 00367 for(int i=0,iend=estar.arity(); i<iend && !d_inconsistent; ++i) 00368 assertFactCore(d_commonRules->andElim(estarThm, i)); 00369 return; 00370 } 00371 else { 00372 // Notify the search engine 00373 enqueueSE(estarThm); 00374 } 00375 00376 DebugAssert(!e2.isAbsLiteral() || e2.hasFind() 00377 || (e2.isNot() && e2[0].hasFind()), 00378 "assertFactCore: e2 = "+e2.toString()); 00379 DebugAssert(!estar.isAbsLiteral() || estar.hasFind() 00380 || (estar.isNot() && estar[0].hasFind()), 00381 "assertFactCore: estar = "+estar.toString()); 00382 } 00383 00384 00385 void TheoryCore::assertFormula(const Theorem& thm) 00386 { 00387 const Expr& e = thm.getExpr(); 00388 DebugAssert(e.isAbsLiteral(),"assertFormula: nonliteral asserted:\n " 00389 +thm.toString()); 00390 IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');) 00391 TRACE("assertFormula",indentStr,"AssertFormula: ", e.toString(PRESENTATION_LANG)); 00392 00393 Theory* i = theoryOf(e); 00394 Theory* i2 = i; 00395 00396 // Recursively set up terms in this formula 00397 setupTerm(e,i,thm); 00398 00399 // Use find to force af to rewrite to TRUE and NOT af to rewrite to FALSE, 00400 // where af is an atomic formula. If af is an equality, make sure its lhs 00401 // is greater than its rhs so the simplifier will be able to use the find. 00402 DebugAssert(!e.isNot() || (!e.hasFind() && !e[0].hasFind()), 00403 "Expected negated argument to assertFormula to not have find"); 00404 setFindLiteral(thm); 00405 00406 // Special processing for existentials, equalities, disequalities 00407 switch (e.getKind()) { 00408 case EXISTS: 00409 // Do not send existential quantifiers to DPs; instead, skolemize them 00410 enqueueFact(d_commonRules->skolemize(thm)); 00411 return; 00412 case NOT: 00413 if (e[0].isEq()) { 00414 00415 // Save the disequality for later processing 00416 e[0][0].addToNotify(this, e); 00417 e[0][1].addToNotify(this, e); 00418 i2 = theoryOf(getBaseType(e[0][0])); 00419 DebugAssert(e[0][0] > e[0][1], "Expected lhs of diseq to be greater"); 00420 // if(e[0][0] < e[0][1]) { 00421 // Expr e2 = e[0][1].eqExpr(e[0][0]); 00422 // DebugAssert(!e2.hasFind(), "already has find"); 00423 // thm2 = transitivityRule(d_commonRules->rewriteUsingSymmetry(e2), 00424 // d_commonRules->notToIff(thm)); 00425 // setFindLiteral(d_commonRules->iffFalseElim(thm2)); 00426 // } 00427 } 00428 break; 00429 case EQ: 00430 i2 = theoryOf(getBaseType(e[0])); 00431 if (e[0] < e[1]) { 00432 // this can happen because of the solver 00433 Expr e2 = e[1].eqExpr(e[0]); 00434 if (!e2.hasFind()) { 00435 Theorem thm2 = 00436 transitivityRule(d_commonRules->rewriteUsingSymmetry(e2), 00437 d_commonRules->iffTrue(thm)); 00438 setFindLiteral(d_commonRules->iffTrueElim(thm2)); 00439 } 00440 } 00441 break; 00442 default: 00443 break; 00444 } 00445 00446 // Send formula to the appropriate DP 00447 i->assertFact(thm); 00448 00449 // Equalities and disequalities are also asserted to the theories of 00450 // their types 00451 if (i != i2) i2->assertFact(thm); 00452 } 00453 00454 00455 Theorem CVC3::TheoryCore::rewriteCore(const Expr& e) 00456 { 00457 // Normally, if an expr has a find, we don't need to rewrite, just return the find. 00458 // However, if we are in the middle of an update, the find may not yet be updated, so 00459 // we should simplify the result. 00460 if (e.hasFind()) { 00461 Theorem thm = find(e); 00462 if (d_inUpdate && !thm.isRefl()) { 00463 thm = transitivityRule(thm, simplify(thm.getRHS())); 00464 } 00465 return thm; 00466 } 00467 00468 if (e.isRewriteNormal()) { 00469 IF_DEBUG( 00470 // Check that the RewriteNormal flag is set properly. Note that we 00471 // assume theory-specific rewrites are idempotent 00472 e.clearRewriteNormal(); 00473 Expr rewritten(rewriteCore(e).getRHS()); 00474 e.setRewriteNormal(); // Restore the flag 00475 DebugAssert(rewritten == e, 00476 "Expected no change: e = " + e.toString() 00477 +"\n rewriteCore(e) = "+rewritten.toString()); 00478 ) 00479 return reflexivityRule(e); 00480 } 00481 switch (e.getKind()) { 00482 case EQ: 00483 if (e[0] < e[1]) 00484 return rewriteCore(d_commonRules->rewriteUsingSymmetry(e)); 00485 else if (e[0] == e[1]) 00486 return d_commonRules->rewriteReflexivity(e); 00487 break; 00488 case NOT: 00489 if (e[0].isNot()) 00490 return rewriteCore(d_commonRules->rewriteNotNot(e)); 00491 break; 00492 default: 00493 break; 00494 } 00495 Theorem thm = theoryOf(e)->rewrite(e); 00496 const Expr& e2 = thm.getRHS(); 00497 00498 // Theory-specific rewrites for equality should ensure that lhs >= rhs, or 00499 // there is danger of an infinite loop. 00500 DebugAssert(!e2.isEq() || e2[0] >= e2[1], 00501 "theory-specific rewrites for equality should ensure lhs >= rhs"); 00502 if (e != e2) { 00503 thm = rewriteCore(thm); 00504 } 00505 return thm; 00506 } 00507 00508 00509 void TheoryCore::setFindLiteral(const Theorem& thm) 00510 { 00511 const Expr& e = thm.getExpr(); 00512 NotifyList* L; 00513 if (e.isNot()) { 00514 const Expr& e0 = e[0]; 00515 if (!e0.hasFind()) { 00516 IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');) 00517 TRACE("setFindLiteral", indentStr, "SFL: ", e.toString(PRESENTATION_LANG)); 00518 Theorem findThm = d_commonRules->notToIff(thm); 00519 e0.setFind(findThm); 00520 if (e0.isRegisteredAtom()) { 00521 DebugAssert(!e.isImpliedLiteral(), "Should be new implied lit"); 00522 e.setImpliedLiteral(); 00523 d_impliedLiterals.push_back(thm); 00524 } 00525 d_em->invalidateSimpCache(); 00526 L = e0.getNotify(); 00527 if (L) processNotify(findThm, L); 00528 } 00529 else { 00530 Theorem findThm = find(e0); 00531 if (findThm.getRHS().isTrue()) { 00532 setInconsistent(iffMP(d_commonRules->iffTrueElim(findThm), 00533 d_commonRules->notToIff(thm))); 00534 } 00535 } 00536 } 00537 else if (!e.hasFind()) { 00538 IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');) 00539 TRACE("setFindLiteral", indentStr, "SFL: ", e.toString(PRESENTATION_LANG)); 00540 Theorem findThm = d_commonRules->iffTrue(thm); 00541 e.setFind(findThm); 00542 if (e.isRegisteredAtom()) { 00543 DebugAssert(!e.isImpliedLiteral(), "Should be new implied lit"); 00544 e.setImpliedLiteral(); 00545 d_impliedLiterals.push_back(thm); 00546 } 00547 d_em->invalidateSimpCache(); 00548 L = e.getNotify(); 00549 if (L) processNotify(findThm, L); 00550 } 00551 else { 00552 Theorem findThm = find(e); 00553 if (findThm.getRHS().isFalse()) { 00554 setInconsistent(iffMP(thm, findThm)); 00555 } 00556 } 00557 } 00558 00559 00560 Theorem TheoryCore::rewriteLitCore(const Expr& e) 00561 { 00562 switch (e.getKind()) { 00563 case EQ: 00564 if (e[0] == e[1]) 00565 return d_commonRules->rewriteReflexivity(e); 00566 else if (e[0] < e[1]) 00567 return d_commonRules->rewriteUsingSymmetry(e); 00568 break; 00569 case NOT: 00570 if (e[0].isTrue()) 00571 return d_commonRules->rewriteNotTrue(e); 00572 else if (e[0].isFalse()) 00573 return d_commonRules->rewriteNotFalse(e); 00574 else if (e[0].isNot()) 00575 return d_commonRules->rewriteNotNot(e); 00576 break; 00577 default: 00578 DebugAssert(false, 00579 "TheoryCore::rewriteLitCore(" 00580 + e.toString() 00581 + "): Not implemented"); 00582 break; 00583 } 00584 return reflexivityRule(e); 00585 } 00586 00587 00588 void TheoryCore::enqueueSE(const Theorem& thm) 00589 { 00590 DebugAssert(okToEnqueue(), "enqueueSE()"); 00591 d_queueSE.push_back(thm); 00592 } 00593 00594 00595 Theorem TheoryCore::getModelValue(const Expr& e) 00596 { 00597 ExprHashMap<Theorem>::iterator i=d_varAssignments.find(e), 00598 iend=d_varAssignments.end(); 00599 if(i!=iend) return (*i).second; 00600 else return find(e); 00601 } 00602 00603 00604 //! An auxiliary recursive function to process COND expressions into ITE 00605 Expr TheoryCore::processCond(const Expr& e, int i) 00606 { 00607 DebugAssert(i < e.arity()-1, "e = "+e.toString()+", i = "+int2string(i)); 00608 if(i == e.arity()-2) { 00609 if(e[i].getKind() == RAW_LIST && e[i].arity() == 2 00610 && e[i+1].getKind() == RAW_LIST && e[i+1].arity() == 2 00611 && e[i+1][0].getKind() == ID && e[i+1][0][0].getString() == "_ELSE") { 00612 Expr c(parseExpr(e[i][0])); 00613 Expr e1(parseExpr(e[i][1])); 00614 Expr e2(parseExpr(e[i+1][1])); 00615 return c.iteExpr(e1,e2); 00616 } 00617 } else { 00618 if(e[i].getKind() == RAW_LIST && e[i].arity() == 2 00619 && e[i+1].getKind() == RAW_LIST && e[i+1].arity() == 2) { 00620 Expr c(parseExpr(e[i][0])); 00621 Expr e1(parseExpr(e[i][1])); 00622 Expr e2(processCond(e, i+1)); 00623 return c.iteExpr(e1,e2); 00624 } 00625 } 00626 throw ParserException("Parse Error: bad COND expression: "+e.toString()); 00627 } 00628 00629 00630 bool TheoryCore::isBasicKind(int kind) 00631 { 00632 switch (kind) { 00633 case VARDECLS: 00634 case LETDECLS: 00635 case HELP: 00636 case GET_VALUE: 00637 case GET_ASSIGNMENT: 00638 case DUMP_PROOF: 00639 case DUMP_ASSUMPTIONS: 00640 case DUMP_SIG: 00641 case DUMP_TCC: 00642 case DUMP_TCC_ASSUMPTIONS: 00643 case DUMP_TCC_PROOF: 00644 case DUMP_CLOSURE: 00645 case DUMP_CLOSURE_PROOF: 00646 case WHERE: 00647 case ASSERTIONS: 00648 case ASSUMPTIONS: 00649 case COUNTEREXAMPLE: 00650 case COUNTERMODEL: 00651 case ASSERT: 00652 case PRINT: 00653 case QUERY: 00654 case CHECKSAT: 00655 case CONTINUE: 00656 case RESTART: 00657 case TRACE: 00658 case ECHO: 00659 case UNTRACE: 00660 case VARLIST: 00661 case FORGET: 00662 case GET_TYPE: 00663 case IFF: 00664 case IMPLIES: 00665 case TYPEDEF: 00666 case OPTION: 00667 case AND: 00668 case OR: 00669 case XOR: 00670 case NOT: 00671 case DISTINCT: 00672 case CALL: 00673 case TRANSFORM: 00674 case CHECK_TYPE: 00675 case VARDECL: 00676 case GET_CHILD: 00677 case SUBSTITUTE: 00678 case SEQ: 00679 case DBG: 00680 case PUSH: 00681 case POP: 00682 case POPTO: 00683 case PUSH_SCOPE: 00684 case POP_SCOPE: 00685 case POPTO_SCOPE: 00686 case RESET: 00687 case LETDECL: 00688 case ELSE: 00689 case CONTEXT: 00690 return true; 00691 default: 00692 break; 00693 } 00694 return false; 00695 } 00696 00697 00698 TheoryCore::TheoryCore(ContextManager* cm, 00699 ExprManager* em, 00700 TheoremManager* tm, 00701 Translator* translator, 00702 const CLFlags& flags, 00703 Statistics& statistics) 00704 : Theory(), d_cm(cm), d_tm(tm), d_flags(flags), d_statistics(statistics), 00705 d_translator(translator), 00706 d_inconsistent(cm->getCurrentContext(), false, 0), 00707 d_incomplete(cm->getCurrentContext()), 00708 d_incThm(cm->getCurrentContext()), 00709 d_terms(cm->getCurrentContext()), 00710 // d_termTheorems(cm->getCurrentContext()), 00711 d_predicates(cm->getCurrentContext()), 00712 d_solver(NULL), 00713 d_simplifyInPlace(false), 00714 d_currentRecursiveSimplifier(NULL), 00715 d_resourceLimit(0), 00716 d_timeBase(0), 00717 d_timeLimit(0), 00718 d_inCheckSATCore(false), d_inAddFact(false), 00719 d_inRegisterAtom(false), d_inPP(false), 00720 d_notifyObj(this, cm->getCurrentContext()), 00721 d_impliedLiterals(cm->getCurrentContext()), 00722 d_impliedLiteralsIdx(cm->getCurrentContext(), 0, 0), 00723 d_notifyEq(cm->getCurrentContext()), 00724 d_inUpdate(0), 00725 d_coreSatAPI(NULL) 00726 { 00727 d_em = em; 00728 // Since we are in the middle of creating TheoryCore, we set the pointer to 00729 // TheoryCore in the Theory base class ourselves. 00730 d_theoryCore = this; 00731 d_commonRules = tm->getRules(); 00732 d_name = "Core"; 00733 d_theoryUsed = false; 00734 00735 d_rules = createProofRules(tm); 00736 d_printer = new PrettyPrinterCore(this); 00737 d_typeComputer = new TypeComputerCore(this); 00738 d_em->registerTypeComputer(d_typeComputer); 00739 d_exprTrans = new ExprTransform(this); 00740 00741 // Register the pretty-printer 00742 d_em->registerPrettyPrinter(*d_printer); 00743 00744 // for (int i = 0; i < LAST_KIND; ++i) d_theoryMap[i] = NULL; 00745 00746 vector<int> kinds; 00747 kinds.push_back(RAW_LIST); 00748 kinds.push_back(BOOLEAN); 00749 kinds.push_back(ANY_TYPE); 00750 kinds.push_back(SUBTYPE); 00751 kinds.push_back(STRING_EXPR); 00752 kinds.push_back(ID); 00753 kinds.push_back(TRUE_EXPR); 00754 kinds.push_back(FALSE_EXPR); 00755 kinds.push_back(UCONST); 00756 kinds.push_back(BOUND_VAR); 00757 kinds.push_back(SKOLEM_VAR); 00758 kinds.push_back(EQ); 00759 kinds.push_back(NEQ); 00760 kinds.push_back(DISTINCT); 00761 kinds.push_back(ECHO); 00762 kinds.push_back(DBG); 00763 kinds.push_back(TRACE); 00764 kinds.push_back(UNTRACE); 00765 kinds.push_back(OPTION); 00766 kinds.push_back(HELP); 00767 kinds.push_back(AND); 00768 kinds.push_back(OR); 00769 kinds.push_back(IFTHEN); 00770 kinds.push_back(IF); 00771 kinds.push_back(ELSE); 00772 kinds.push_back(COND); 00773 kinds.push_back(XOR); 00774 kinds.push_back(NOT); 00775 kinds.push_back(ITE); 00776 kinds.push_back(IFF); 00777 kinds.push_back(IMPLIES); 00778 kinds.push_back(APPLY); 00779 // For printing LET expressions (in DAG printing mode) 00780 kinds.push_back(LET); 00781 kinds.push_back(LETDECLS); 00782 kinds.push_back(LETDECL); 00783 // For printing raw parsed quantifier expressions 00784 kinds.push_back(VARLIST); 00785 kinds.push_back(VARDECLS); 00786 kinds.push_back(VARDECL); 00787 00788 // Type declarations and definitions 00789 kinds.push_back(TYPE); 00790 // For printing type declarations (or definitions) 00791 kinds.push_back(CONST); 00792 00793 kinds.push_back(TYPEDEF); 00794 kinds.push_back(DEFUN); 00795 // Printing proofs 00796 kinds.push_back(PF_APPLY); 00797 kinds.push_back(PF_HOLE); 00798 // Register commands for pretty-printing. Currently, only ASSERT 00799 // needs to be printed. 00800 kinds.push_back(ASSERT); 00801 kinds.push_back(QUERY); 00802 kinds.push_back(PRINT); 00803 00804 kinds.push_back(GET_VALUE); 00805 kinds.push_back(GET_ASSIGNMENT); 00806 kinds.push_back(DUMP_PROOF); 00807 kinds.push_back(DUMP_ASSUMPTIONS); 00808 kinds.push_back(DUMP_SIG); 00809 kinds.push_back(DUMP_TCC); 00810 kinds.push_back(DUMP_TCC_ASSUMPTIONS); 00811 kinds.push_back(DUMP_TCC_PROOF); 00812 kinds.push_back(DUMP_CLOSURE); 00813 kinds.push_back(DUMP_CLOSURE_PROOF); 00814 kinds.push_back(TRANSFORM); 00815 kinds.push_back(CALL); 00816 kinds.push_back(WHERE); 00817 kinds.push_back(ASSERTIONS); 00818 kinds.push_back(ASSUMPTIONS); 00819 kinds.push_back(COUNTEREXAMPLE); 00820 kinds.push_back(COUNTERMODEL); 00821 kinds.push_back(PUSH); 00822 kinds.push_back(POP); 00823 kinds.push_back(POPTO); 00824 kinds.push_back(PUSH_SCOPE); 00825 kinds.push_back(POP_SCOPE); 00826 kinds.push_back(POPTO_SCOPE); 00827 kinds.push_back(RESET); 00828 kinds.push_back(CONTEXT); 00829 kinds.push_back(FORGET); 00830 kinds.push_back(GET_TYPE); 00831 kinds.push_back(CHECK_TYPE); 00832 kinds.push_back(GET_CHILD); 00833 kinds.push_back(SUBSTITUTE); 00834 kinds.push_back(SEQ); 00835 kinds.push_back(ARITH_VAR_ORDER); 00836 kinds.push_back(ANNOTATION); 00837 kinds.push_back(THEOREM_KIND); 00838 00839 kinds.push_back(AND_R); 00840 kinds.push_back(IFF_R); 00841 kinds.push_back(ITE_R); 00842 00843 registerTheory(this, kinds); 00844 } 00845 00846 00847 TheoryCore::~TheoryCore() 00848 { 00849 delete d_exprTrans; 00850 delete d_rules; 00851 delete d_typeComputer; 00852 d_em->unregisterPrettyPrinter(); 00853 delete d_printer; 00854 } 00855 00856 00857 Theorem TheoryCore::callTheoryPreprocess(const Expr& e) 00858 { 00859 Theorem thm = reflexivityRule(e); 00860 for(unsigned i=1; i<d_theories.size(); ++i) { 00861 thm = transitivityRule(thm, d_theories[i]->theoryPreprocess(thm.getRHS())); 00862 } 00863 processFactQueue(LOW); 00864 return thm; 00865 } 00866 00867 00868 Theorem TheoryCore::getTheoremForTerm(const Expr& e){ 00869 00870 // <<<<<<< theory_core_sat.cpp 00871 // // DebugAssert(e.hasFind(), "getTheoremForTerm called on term without find"); 00872 // CDMap<Expr, Theorem>::iterator i = d_termTheorems.find(e); 00873 // if( i == d_termTheorems.end()){ 00874 // TRACE("quantlevel", "getTheoremForTerm: no theorem found: ", e , ""); 00875 // Theorem nul; 00876 // return nul; 00877 // } 00878 // // DebugAssert(i != d_termTheorems.end(), "getTheoremForTerm: no theorem found"); 00879 // ======= 00880 // DebugAssert(e.hasFind() || e.isStoredPredicate(), "getTheoremForTerm called on invalid term"); 00881 00882 hash_map<Expr, Theorem>::iterator i = d_termTheorems.find(e); 00883 // yeting, I think we should use CDMap here, but a static map works better. 00884 // CDMap<Expr, Theorem>::iterator i = d_termTheorems.find(e); 00885 00886 // DebugAssert(i != d_termTheorems.end(), "getTheoremForTerm: no theorem found"); 00887 00888 if(i != d_termTheorems.end()){ 00889 return (*i).second; 00890 } 00891 else{ 00892 TRACE("quantlevel", "getTheoremForTerm: no theorem found: ", e , ""); 00893 Theorem x; 00894 return x; 00895 } 00896 } 00897 00898 #ifdef _CVC3_DEBUG_MODE 00899 int TheoryCore::getCurQuantLevel(){ 00900 return theoryOf(FORALL)->help(1); 00901 } 00902 #endif 00903 00904 unsigned TheoryCore::getQuantLevelForTerm(const Expr& e) 00905 { 00906 00907 00908 /* 00909 if (!e.hasFind() && !e.isStoredPredicate()) { 00910 TRACE("quantlevel", "get 0 ", e , ""); 00911 return 0; 00912 } 00913 */ 00914 TRACE("quantlevel", "trying get level for (" + e.toString() + ") with index ", "", e.getIndex()); 00915 Theorem thm = getTheoremForTerm(e); 00916 if (thm.isNull()) { 00917 if(e.isNot()){ 00918 thm = getTheoremForTerm(e[0]); 00919 } 00920 } 00921 00922 if(thm.isNull()){ 00923 if (e.inUserAssumption()) { 00924 return 0 ; 00925 } 00926 else{ 00927 TRACE("quantlevel", "expr get null :", e.getIndex(), "" ); 00928 if( ! (e.isNot() || e.isIff())){ 00929 TRACE("quantlevel", "cannot find expr: " , e, ""); 00930 } 00931 return 0; 00932 } 00933 } 00934 00935 TRACE("quantlevel", "expr get level:", thm.getQuantLevel(), ""); 00936 00937 /* 00938 if(thm.getQuantLevel() != thm.getQuantLevelDebug()){ 00939 cout << "theorem: " << thm.getExpr().toString() <<endl; 00940 cout << "quant level : " << thm.getQuantLevel()<<endl; 00941 cout << "debug quant level : " << thm.getQuantLevelDebug() <<endl; 00942 cout << "the proof is " << thm.getProof() << endl; 00943 } 00944 */ 00945 00946 return thm.getQuantLevel(); 00947 /* 00948 unsigned ql = thm.getQuantLevel(); 00949 unsigned qld = thm.getQuantLevelDebug(); 00950 return (ql > qld ? ql : qld); 00951 */ 00952 } 00953 00954 00955 /////////////////////////////////////////////////////////////////////////////// 00956 // Theory interface implementaion // 00957 /////////////////////////////////////////////////////////////////////////////// 00958 00959 00960 void TheoryCore::assertFact(const Theorem& e) 00961 { 00962 DebugAssert(e.getExpr().unnegate().getKind() == SKOLEM_VAR || 00963 e.getExpr().unnegate().getKind() == UCONST, 00964 "TheoryCore::assertFact("+e.toString()+")"); 00965 } 00966 00967 00968 Theorem TheoryCore::rewrite(const Expr& e) 00969 { 00970 Theorem thm; 00971 switch (e.getKind()) { 00972 case TRUE_EXPR: 00973 case FALSE_EXPR: 00974 case UCONST: 00975 case BOUND_VAR: 00976 case SKOLEM_VAR: 00977 thm = reflexivityRule(e); 00978 break; // do not rewrite 00979 case LETDECL: 00980 // Replace LETDECL with its definition. The 00981 // typechecker makes sure it's type-safe to do so. 00982 thm = d_rules->rewriteLetDecl(e); 00983 break; 00984 case APPLY: 00985 //TODO: this is a bit of a hack 00986 if (e.getOpKind() == LAMBDA) 00987 thm = theoryOf(LAMBDA)->rewrite(e); 00988 else thm = reflexivityRule(e); 00989 break; 00990 case EQ: 00991 case NOT: 00992 thm = rewriteLitCore(e); 00993 break; 00994 case DISTINCT: { 00995 Theorem thm1 = d_rules->rewriteDistinct(e); 00996 thm = transitivityRule(thm1, simplify(thm1.getRHS())); 00997 break; 00998 } 00999 case IMPLIES: { 01000 thm = d_rules->rewriteImplies(e); 01001 const Expr& rhs = thm.getRHS(); 01002 // rhs = OR(!e1, e2). Rewrite !e1, then top-level OR(). 01003 DebugAssert(rhs.isOr() && rhs.arity() == 2, 01004 "TheoryCore::rewrite[IMPLIES]: rhs = "+rhs.toString()); 01005 Theorem rw = rewriteCore(rhs[0]); 01006 if (!rw.isRefl()) { 01007 vector<unsigned> changed; 01008 vector<Theorem> thms; 01009 changed.push_back(0); 01010 thms.push_back(rw); 01011 rw = substitutivityRule(rhs, changed, thms); 01012 // Simplify to the find pointer of the result 01013 rw = transitivityRule(rw, find(rw.getRHS())); 01014 // Now rw = Theorem(rhs = rhs') 01015 rw = transitivityRule(rw, rewrite(rw.getRHS())); 01016 } else 01017 rw = rewrite(rhs); 01018 thm = transitivityRule(thm, rw); 01019 // thm = transitivityRule(thm, simplify(thm.getRHS())); 01020 break; 01021 } 01022 case XOR: { 01023 thm = d_commonRules->xorToIff(e); 01024 thm = transitivityRule(thm, simplify(thm.getRHS())); 01025 break; 01026 } 01027 case IFF: { 01028 thm = d_commonRules->rewriteIff(e); 01029 Expr e1 = thm.getRHS(); 01030 // The only time we need to rewrite the result (e1) is when 01031 // e==(FALSE<=>e[1]) or (e[1]<=>FALSE), so e1==!e[1]. 01032 if (e != e1 && e1.isNot()) 01033 thm = transitivityRule(thm, rewriteCore(e1)); 01034 break; 01035 } 01036 case ITE: 01037 thm = rewriteIte(e); 01038 if (!thm.isRefl()) break; 01039 else if (getFlags()["un-ite-ify"].getBool()) { 01040 // undo the rewriting of Boolean connectives to ITEs. 01041 // helpful for examples converted from SVC. 01042 // must rewrite again because we might create expressions 01043 // that can be further rewritten, and we must normalize. 01044 if (e[1].isFalse() && e[2].isTrue()) 01045 thm = rewriteCore(d_rules->rewriteIteToNot(e)); 01046 else if (e[1].isTrue()) 01047 thm = rewriteCore(d_rules->rewriteIteToOr(e)); 01048 else if (e[2].isFalse()) 01049 thm = rewriteCore(d_rules->rewriteIteToAnd(e)); 01050 else if (e[2].isTrue()) 01051 thm = rewriteCore(d_rules->rewriteIteToImp(e)); 01052 else if (e[1] == e[2].negate()) 01053 thm = rewriteCore(d_rules->rewriteIteToIff(e)); 01054 else thm = reflexivityRule(e); 01055 } 01056 else if(getFlags()["ite-cond-simp"].getBool()) { 01057 thm = d_rules->rewriteIteCond(e); 01058 if (!thm.isRefl()) { 01059 thm = transitivityRule(thm, simplify(thm.getRHS())); 01060 } 01061 } 01062 else thm = reflexivityRule(e); 01063 break; 01064 case AND: { 01065 thm = rewriteAnd(e); 01066 Expr ee = thm.getRHS(); 01067 break; 01068 } 01069 case OR: { 01070 thm = rewriteOr(e); 01071 Expr ee = thm.getRHS(); 01072 break; 01073 } 01074 // Quantifiers 01075 case FORALL: 01076 case EXISTS: 01077 thm = d_commonRules->reflexivityRule(e); 01078 break; 01079 // don't need to rewrite these 01080 case AND_R: 01081 case IFF_R: 01082 case ITE_R: 01083 thm = reflexivityRule(e); 01084 break; 01085 default: 01086 DebugAssert(false, 01087 "TheoryCore::rewrite(" 01088 + e.toString() + " : " + e.getType().toString() 01089 + "): Not implemented"); 01090 break; 01091 } 01092 01093 DebugAssert(thm.getLHS() == e, "TheoryCore::rewrite("+e.toString() 01094 +") = "+thm.getExpr().toString()); 01095 01096 Expr rhs = thm.getRHS(); 01097 // Advanced Boolean rewrites 01098 switch(rhs.getKind()) { 01099 case AND: 01100 if(getFlags()["simp-and"].getBool()) { 01101 Theorem tmp(reflexivityRule(rhs)); 01102 for(int i=0, iend=rhs.arity(); i<iend; ++i) { 01103 tmp = transitivityRule 01104 (tmp, d_rules->rewriteAndSubterms(tmp.getRHS(), i)); 01105 } 01106 if(tmp.getRHS() != rhs) { // Something changed: simplify recursively 01107 thm = transitivityRule(thm, tmp); 01108 thm = transitivityRule(thm, simplify(thm.getRHS())); 01109 rhs = thm.getRHS(); 01110 } 01111 } 01112 break; 01113 case OR: 01114 if(getFlags()["simp-or"].getBool()) { 01115 Theorem tmp(reflexivityRule(rhs)); 01116 for(int i=0, iend=rhs.arity(); i<iend; ++i) { 01117 tmp = transitivityRule 01118 (tmp, d_rules->rewriteOrSubterms(tmp.getRHS(), i)); 01119 } 01120 if(tmp.getRHS() != rhs) { // Something changed: simplify recursively 01121 thm = transitivityRule(thm, tmp); 01122 thm = transitivityRule(thm, simplify(thm.getRHS())); 01123 rhs = thm.getRHS(); 01124 } 01125 } 01126 break; 01127 default: 01128 break; 01129 } 01130 if (theoryOf(rhs) == this) { 01131 // Core rewrites are idempotent (FIXME: are they, still?) 01132 rhs.setRewriteNormal(); 01133 } 01134 return thm; 01135 } 01136 01137 01138 /*! We use the update method of theory core to track registered atomic 01139 * formulas. Updates are recorded and then processed by calling processUpdates 01140 * once all equalities have been processed. */ 01141 void TheoryCore::update(const Theorem& e, const Expr& d) 01142 { 01143 // Disequalities 01144 if (d.isNot()) { 01145 const Expr& eq = d[0]; 01146 DebugAssert(eq.isEq(), "Expected equality"); 01147 Theorem thm1(find(eq[0])); 01148 Theorem thm2(find(eq[1])); 01149 const Expr& newlhs = thm1.getRHS(); 01150 const Expr& newrhs = thm2.getRHS(); 01151 if (newlhs == newrhs) { 01152 Theorem thm = find(eq); 01153 DebugAssert(thm.getRHS().isFalse(), "Expected disequality"); 01154 Theorem leftEqRight = transitivityRule(thm1, symmetryRule(thm2)); 01155 setInconsistent(iffMP(leftEqRight, thm)); 01156 } 01157 else { 01158 e.getRHS().addToNotify(this, d); 01159 // propagate new disequality 01160 Theorem thm = d_commonRules->substitutivityRule(eq, thm1, thm2); 01161 if (newlhs < newrhs) { 01162 thm = transitivityRule(thm, d_commonRules->rewriteUsingSymmetry(thm.getRHS())); 01163 } 01164 const Expr& newEq = thm.getRHS(); 01165 if (newEq.hasFind()) { 01166 Theorem thm2 = find(newEq); 01167 if (thm2.getRHS().isTrue()) { 01168 thm2 = transitivityRule(thm, thm2); 01169 thm = find(eq); 01170 DebugAssert(thm.getRHS().isFalse(), "Expected disequality"); 01171 thm = transitivityRule(symmetryRule(thm), thm2); 01172 setInconsistent(d_commonRules->iffTrueElim(thm)); 01173 } 01174 // else if thm2.getRHS().isFalse(), nothing to do 01175 } 01176 else { 01177 Theorem thm2 = find(eq); 01178 DebugAssert(thm2.getRHS().isFalse(), "Expected disequality"); 01179 thm2 = transitivityRule(symmetryRule(thm),thm2); 01180 setFindLiteral(d_commonRules->iffFalseElim(thm2)); 01181 } 01182 } 01183 } 01184 // Registered atoms 01185 else { 01186 DebugAssert(d.isRegisteredAtom(), "Expected registered atom"); 01187 if (!d.isImpliedLiteral()) { 01188 d_update_thms.push_back(e); 01189 d_update_data.push_back(d); 01190 } 01191 } 01192 } 01193 01194 01195 void TheoryCore::checkEquation(const Theorem& thm) 01196 { 01197 Expr e2 = thm.getExpr(); 01198 DebugAssert(e2.isEq(), "Expected equation"); 01199 Expr solved; 01200 if (d_solver) { 01201 solved = d_solver->solve(thm).getExpr(); 01202 DebugAssert(solved == e2, "e2 = "+e2.toString() 01203 +"\nsolved = "+solved.toString()); 01204 } 01205 Theory* i = theoryOf(e2); 01206 if (d_solver != i) { 01207 solved = i->solve(thm).getExpr(); 01208 DebugAssert(solved == e2, "e2 = "+e2.toString() 01209 +"\nsolved = "+solved.toString()); 01210 } 01211 Theory* j = theoryOf(e2[0].getType()); 01212 if (d_solver != j && i != j) { 01213 solved = j->solve(thm).getExpr(); 01214 DebugAssert(solved == e2, "e2 = "+e2.toString() 01215 +"\nsolved = "+solved.toString()); 01216 } 01217 } 01218 01219 01220 void TheoryCore::checkSolved(const Theorem& thm) 01221 { 01222 Expr e2 = thm.getExpr(); 01223 if (e2.isAnd()) { 01224 for (int index = 0; index < e2.arity(); ++index) { 01225 checkEquation(d_commonRules->andElim(thm, index)); 01226 } 01227 } 01228 else if (!e2.isBoolConst()) checkEquation(thm); 01229 } 01230 01231 01232 /*****************************************************************************/ 01233 /*! 01234 * Function: TheoryCore::solve 01235 * 01236 * Author: Clark Barrett 01237 * 01238 * Created: Wed Feb 26 16:17:54 2003 01239 * 01240 * This is a generalization of what's in my thesis. The goal is to rewrite e 01241 * into an equisatisfiable conjunction of equations such that the left-hand 01242 * side of each equation is a variable which does not appear as an i-leaf of 01243 * the rhs, where i is the theory of the primary solver. Any solution which 01244 * satisfies this is fine. "Solvers" from other theories can do whatever they 01245 * want as long as we eventually reach this form. 01246 */ 01247 /*****************************************************************************/ 01248 Theorem TheoryCore::solve(const Theorem& eThm) 01249 { 01250 const Expr& e = eThm.getExpr(); 01251 Theorem thm; 01252 Expr e2; 01253 01254 DebugAssert(eThm.isRewrite() && eThm.getLHS().isTerm(), "Expected equation"); 01255 01256 // Invoke the primary solver 01257 if (d_solver) { 01258 thm = d_solver->solve(eThm); 01259 e2 = thm.getExpr(); 01260 if (e2.isBoolConst() || e2.isAnd()) { 01261 // We expect a conjunction of equations, each of which is terminally solved 01262 IF_DEBUG(checkSolved(thm)); 01263 return thm; 01264 } 01265 } 01266 else { 01267 thm = eThm; 01268 e2 = e; 01269 } 01270 01271 // Invoke solver based on owner of equation 01272 DebugAssert(e2.isEq(), "Expected equation"); 01273 Theory* i = theoryOf(e2); 01274 if (d_solver != i) thm = i->solve(thm); 01275 e2 = thm.getExpr(); 01276 if (e2.isBoolConst() || e2.isAnd()) { 01277 // We expect a conjunction of equations, each of which is solved 01278 IF_DEBUG(checkSolved(thm)); 01279 return thm; 01280 } 01281 01282 // Invoke solver based on type of terms in equation 01283 DebugAssert(e2.isEq(), "Expected equation"); 01284 Theory* j = theoryOf(getBaseType(e2[0])); 01285 if (d_solver != j && i != j) thm = j->solve(thm); 01286 01287 IF_DEBUG(checkSolved(thm)); 01288 return thm; 01289 } 01290 01291 01292 Theorem TheoryCore::simplifyOp(const Expr& e) 01293 { 01294 int kind(e.getKind()); 01295 01296 switch(kind) { 01297 case EQ: 01298 case IFF: 01299 if(e[0]==e[1]) { 01300 IF_DEBUG(debugger.counter("simplified x=x")++;) 01301 return d_commonRules->iffTrue(reflexivityRule(e[0])); 01302 } 01303 return Theory::simplifyOp(e); 01304 case AND: 01305 case OR: { 01306 // Stop when a child has this kind 01307 int endKind = (kind==AND)? FALSE_EXPR : TRUE_EXPR; 01308 int ar = e.arity(); 01309 // Optimization: before simplifying anything recursively, check if 01310 // any kid is already TRUE or FALSE, and just return at that point 01311 int l(0); 01312 for(; l<ar && e[l].getKind() != endKind; ++l); 01313 if(l < ar) { // Found TRUE or FALSE: e simplifies to a const 01314 IF_DEBUG(debugger.counter("simplified AND/OR topdown")++;) 01315 if(kind==AND) 01316 return rewriteAnd(e); 01317 else 01318 return rewriteOr(e); 01319 } 01320 vector<Theorem> newChildrenThm; 01321 vector<unsigned> changed; 01322 for(int k = 0; k < ar; ++k) { 01323 // Recursively simplify the kids 01324 Theorem thm = simplify(e[k]); 01325 if (!thm.isRefl()) { 01326 if (thm.getRHS().getKind() == endKind) { 01327 newChildrenThm.clear(); 01328 changed.clear(); 01329 newChildrenThm.push_back(thm); 01330 changed.push_back(k); 01331 thm = substitutivityRule(e, changed, newChildrenThm); 01332 // Simplify to TRUE or FALSE 01333 if(kind==AND) 01334 thm = transitivityRule(thm, rewriteAnd(thm.getRHS())); 01335 else 01336 thm = transitivityRule(thm, rewriteOr(thm.getRHS())); 01337 IF_DEBUG(debugger.counter("simplified AND/OR: skipped kids") 01338 += ar-k-1;) 01339 return thm; 01340 } else { // Child simplified to something else 01341 newChildrenThm.push_back(thm); 01342 changed.push_back(k); 01343 } 01344 } 01345 } 01346 if(changed.size() > 0) 01347 return substitutivityRule(e, changed, newChildrenThm); 01348 break; 01349 } 01350 case ITE: { 01351 DebugAssert(e.arity()==3, "Bad ITE in TheoryCore::simplify(e=" 01352 +e.toString()+")"); 01353 // Optimization: check if the two branches are the same, so we 01354 // don't have to simplify the condition 01355 if(e[1]==e[2]) { 01356 IF_DEBUG(debugger.counter("simplified ITE(c,e,e)")++;) 01357 Theorem res = d_commonRules->rewriteIteSame(e); 01358 return transitivityRule(res, simplify(res.getRHS())); 01359 } 01360 01361 // First, simplify the conditional 01362 vector<Theorem> newChildrenThm; 01363 vector<unsigned> changed; 01364 Theorem thm = simplify(e[0]); 01365 if (!thm.isRefl()) { 01366 newChildrenThm.push_back(thm); 01367 changed.push_back(0); 01368 } 01369 Expr cond = thm.getRHS(); 01370 01371 for(int k=1; k<=2; ++k) { 01372 // If condition value is known, only the appropriate branch 01373 // needs to be simplified 01374 if (cond.isBoolConst()) { 01375 if((k==1 && cond.isFalse()) || (k==2 && cond.isTrue())) { 01376 IF_DEBUG(debugger.counter("simplified ITE: skiped one branch")++;) 01377 continue; 01378 } 01379 } 01380 thm = simplify(e[k]); 01381 if (!thm.isRefl()) { 01382 newChildrenThm.push_back(thm); 01383 changed.push_back(k); 01384 } 01385 } 01386 if(changed.size() > 0) 01387 return substitutivityRule(e, changed, newChildrenThm); 01388 break; 01389 } 01390 case NOT: { 01391 Theorem res = simplify(e[0]); 01392 if (!res.isRefl()) { 01393 return d_commonRules->substitutivityRule(e, res); 01394 } 01395 break; 01396 } 01397 case IMPLIES: { 01398 Theorem res = d_rules->rewriteImplies(e); 01399 return transitivityRule(res, simplifyOp(res.getRHS())); 01400 } 01401 default: 01402 return Theory::simplifyOp(e); 01403 } 01404 return reflexivityRule(e); 01405 } 01406 01407 01408 void TheoryCore::checkType(const Expr& e) 01409 { 01410 switch (e.getKind()) { 01411 case BOOLEAN: 01412 if (e.arity() > 0) { 01413 throw Exception("Ill-formed Boolean type:\n\n"+e.toString()); 01414 } 01415 break; 01416 case SUBTYPE: { 01417 if (e.arity() != 1) 01418 throw Exception("Ill-formed SUBTYPE expression:\n\n"+e.toString()); 01419 Type t = e[0].getType(); 01420 if (!t.isFunction()) 01421 throw Exception 01422 ("Non-function argument to SUBTYPE:\n\n" 01423 +e.toString()); 01424 if (!t[1].isBool()) 01425 throw Exception 01426 ("Non-predicate argument to SUBTYPE:\n\n" 01427 +e.toString()); 01428 } 01429 break; 01430 case ANY_TYPE: { 01431 if (e.arity() != 0) { 01432 throw Exception("Expected no children: "+e.toString()); 01433 } 01434 break; 01435 } 01436 default: 01437 FatalAssert(false, "Unexpected kind in TheoryCore::checkType" 01438 +getEM()->getKindName(e.getKind())); 01439 } 01440 } 01441 01442 01443 Cardinality TheoryCore::finiteTypeInfo(Expr& e, Unsigned& n, 01444 bool enumerate, bool computeSize) 01445 { 01446 Cardinality card = CARD_INFINITE; 01447 switch (e.getKind()) { 01448 case BOOLEAN: 01449 card = CARD_FINITE; 01450 if (enumerate) { 01451 e = (n == 0) ? falseExpr() : (n == 1) ? trueExpr() : Expr(); 01452 } 01453 if (computeSize) { 01454 n = 2; 01455 } 01456 break; 01457 case SUBTYPE: 01458 card = CARD_UNKNOWN; 01459 break; 01460 case ANY_TYPE: 01461 card = CARD_UNKNOWN; 01462 break; 01463 default: 01464 FatalAssert(false, "Unexpected kind in TheoryCore::finiteTypeInfo" 01465 +getEM()->getKindName(e.getKind())); 01466 } 01467 return card; 01468 } 01469 01470 01471 void TheoryCore::computeType(const Expr& e) 01472 { 01473 switch (e.getKind()) { 01474 case ITE: { 01475 Type t1(getBaseType(e[1])), t2(getBaseType(e[2])); 01476 if (e[0].getType() != boolType()) 01477 throw TypecheckException 01478 ("The conditional in IF-THEN-ELSE must be BOOLEAN, but is:\n\n" 01479 +e[0].getType().toString() 01480 +"\n\nIn the expression:\n\n " 01481 +e.toString()); 01482 if(t1 != t2) { 01483 throw TypecheckException 01484 ("The types of the IF-THEN-ELSE branches do not match.\n" 01485 "THEN branch has the type:\n\n " 01486 +e[1].getType().toString() 01487 +"\n\nELSE branch has the type:\n\n " 01488 +e[2].getType().toString() 01489 +"\n\nIn expression:\n\n "+e.toString()); 01490 } 01491 Type res(e[1].getType()); 01492 // If the precise types match in both branches, use it as the 01493 // result type. 01494 if(res == e[2].getType()) { 01495 e.setType(res); 01496 } 01497 else 01498 // Note: setting the base type, since e[1] and e[2] have 01499 // different exact types, and the base type is a conservative 01500 // approximation we can easily compute. 01501 e.setType(t1); 01502 } 01503 break; 01504 case EQ: { 01505 Type t0(getBaseType(e[0])), t1(getBaseType(e[1])); 01506 if (t0.isBool() || t1.isBool()) { 01507 throw TypecheckException 01508 ("Cannot use EQ ('=') for BOOLEAN type; use IFF ('<=>') instead.\n" 01509 "Error in the following expression:\n"+e.toString()); 01510 } 01511 if (t0 != t1) { 01512 throw TypecheckException 01513 ("Type mismatch in equality:\n\n LHS type:\n"+t0.toString() 01514 +"\n\n RHS type: \n"+t1.toString() 01515 +"\n\n in expression: \n"+e.toString()); 01516 } 01517 e.setType(boolType()); 01518 break; 01519 } 01520 case DISTINCT: { 01521 Type t0(getBaseType(e[0])); 01522 for (int i = 1; i < e.arity(); ++i) { 01523 if (t0 != getBaseType(e[i])) { 01524 throw TypecheckException 01525 ("Type mismatch in distinct:\n\n types:\n"+t0.toString() 01526 +"\n\n and type: \n"+getBaseType(e[i]).toString() 01527 +"\n\n in expression: \n"+e.toString()); 01528 } 01529 } 01530 e.setType(boolType()); 01531 break; 01532 } 01533 case NOT: 01534 case AND: 01535 case OR: 01536 case XOR: 01537 case IFF: 01538 case IMPLIES: 01539 01540 case AND_R: 01541 case IFF_R: 01542 case ITE_R: 01543 01544 for (int k = 0; k < e.arity(); ++k) { 01545 if (e[k].getType() != boolType()) { 01546 throw TypecheckException(e.toString()); 01547 } 01548 } 01549 if((e.getKind() == NOT && e.arity() != 1) || 01550 (e.getKind() == IFF && e.arity() != 2) || 01551 (e.getKind() == IMPLIES && e.arity() != 2)) { 01552 throw TypecheckException("Wrong arity ("+int2string(e.arity())+") for operator: "+e.toString()); 01553 } 01554 e.setType(boolType()); 01555 break; 01556 case LETDECL: { 01557 Type varTp(getBaseType(e[0])); 01558 Type valTp(getBaseType(e[1])); 01559 if(valTp != varTp) { 01560 throw TypecheckException("Type mismatch for "+e[0].toString()+":" 01561 +"\n declared: " 01562 + varTp.toString() 01563 +"\n derived: "+ valTp.toString()); 01564 } 01565 e.setType(e[0].getType()); 01566 } 01567 break; 01568 case APPLY: 01569 { 01570 DebugAssert(e.isApply(), "Should be application"); 01571 DebugAssert(e.arity() > 0, "Expected non-zero arity in APPLY"); 01572 Expr funExpr = e.getOpExpr(); 01573 Type funType = funExpr.getType(); 01574 01575 if(!funType.isFunction()) { 01576 throw TypecheckException 01577 ("Expected function type for:\n\n" 01578 + funExpr.toString() + "\n\n but got this: " 01579 +funType.getExpr().toString() 01580 +"\n\n in function application:\n\n"+e.toString()); 01581 } 01582 01583 if(funType.arity() != e.arity()+1) 01584 throw TypecheckException("Type mismatch for expression:\n\n " 01585 + e.toString() 01586 + "\n\nFunction \""+funExpr.toString() 01587 +"\" expects "+int2string(funType.arity()-1) 01588 +" argument" 01589 +string((funType.arity()==2)? "" : "s") 01590 +", but received " 01591 +int2string(e.arity())+"."); 01592 01593 for (int k = 0; k < e.arity(); ++k) { 01594 Type valType(getBaseType(e[k])); 01595 if (funType[k] != Type::anyType(d_em) && !(valType == getBaseType(funType[k]) || valType == Type::anyType(d_em)) ) { 01596 throw TypecheckException("Type mismatch for expression:\n\n " 01597 + e[k].toString() 01598 + "\n\nhas the following type:\n\n " 01599 + e[k].getType().toString() 01600 + "\n\nbut the expected type is:\n\n " 01601 + funType[k].getExpr().toString() 01602 + "\n\nin function application:\n\n " 01603 + e.toString()); 01604 } 01605 } 01606 e.setType(funType[funType.arity()-1]); 01607 break; 01608 } 01609 case RAW_LIST: 01610 throw TypecheckException("computeType called on RAW_LIST"); 01611 break; 01612 default: 01613 DebugAssert(false,"TheoryCore::computeType(" + e.toString() 01614 + "):\nNot implemented"); 01615 break; 01616 } 01617 } 01618 01619 01620 Type TheoryCore::computeBaseType(const Type& tp) 01621 { 01622 const Expr& e = tp.getExpr(); 01623 Type res; 01624 switch(e.getKind()) { 01625 case SUBTYPE: { 01626 DebugAssert(e.arity() == 1, "Expr::computeBaseType(): "+e.toString()); 01627 Type lambdaTp = e[0].getType(); 01628 Type lambdaBaseTp = getBaseType(lambdaTp); 01629 DebugAssert(lambdaBaseTp.isFunction(), 01630 "Expr::computeBaseType(): lambdaBaseTp = " 01631 +lambdaBaseTp.toString()+" in e = "+e.toString()); 01632 res = lambdaBaseTp[0]; 01633 break; 01634 } 01635 case BOOLEAN: 01636 case ANY_TYPE: 01637 res = tp; 01638 break; 01639 case TYPEDEF: // Compute the base type of the definition 01640 res = getBaseType(Type(e[1])); 01641 break; 01642 default: 01643 DebugAssert(false, "TheoryCore::computeBaseType("+tp.toString()+")"); 01644 res = tp; 01645 } 01646 return res; 01647 } 01648 01649 01650 Expr TheoryCore::computeTCC(const Expr& e) 01651 { 01652 Expr res; 01653 switch (e.getKind()) { 01654 case NOT: 01655 res = getTCC(e[0]); 01656 break; 01657 case AND: { 01658 // ( (tcc(e1) & !e1) \/ ... \/ (tcc(en) & !en) \/ (tcc(e1)&...&tcc(en)) 01659 vector<Expr> tccs; 01660 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) 01661 tccs.push_back(getTCC(*i)); 01662 vector<Expr> pairs; 01663 pairs.push_back(rewriteAnd(andExpr(tccs)).getRHS()); 01664 for(size_t i=0, iend=tccs.size(); i<iend; ++i) 01665 pairs.push_back(rewriteAnd(tccs[i].andExpr(e[i].negate())).getRHS()); 01666 res = rewriteOr(orExpr(pairs)).getRHS(); 01667 break; 01668 } 01669 case OR: { 01670 // ( (tcc(e1) & e1) \/ ... \/ (tcc(en) & en) \/ (tcc(e1)&...&tcc(en)) 01671 vector<Expr> tccs; 01672 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) 01673 tccs.push_back(getTCC(*i)); 01674 vector<Expr> pairs; 01675 pairs.push_back(rewriteAnd(andExpr(tccs)).getRHS()); 01676 for(size_t i=0, iend=tccs.size(); i<iend; ++i) 01677 pairs.push_back(rewriteAnd(tccs[i].andExpr(e[i])).getRHS()); 01678 res = rewriteOr(orExpr(pairs)).getRHS(); 01679 break; 01680 } 01681 case ITE: { 01682 Expr tcc1(getTCC(e[1])), tcc2(getTCC(e[2])); 01683 // Optimize: if TCCs on both branches are the same, skip the ITE 01684 Expr tccITE((tcc1 == tcc2)? tcc1 : e[0].iteExpr(tcc1, tcc2)); 01685 res = rewriteAnd(getTCC(e[0]).andExpr(tccITE)).getRHS(); 01686 break; 01687 } 01688 case IMPLIES: 01689 res = getTCC(e[0].negate().orExpr(e[1])); 01690 break; 01691 case APPLY: { 01692 Theory* i = theoryOf(e); 01693 if (i != this) return i->computeTCC(e); 01694 // fall through 01695 } 01696 default: // All the other operators are strict 01697 res = Theory::computeTCC(e); 01698 break; 01699 } 01700 return res; 01701 } 01702 01703 01704 Expr TheoryCore::computeTypePred(const Type& t, const Expr& e) 01705 { 01706 Expr tExpr = t.getExpr(); 01707 switch(tExpr.getKind()) { 01708 case SUBTYPE: { 01709 Expr pred = tExpr[0]; 01710 const Type& argTp = pred.lookupType()[0]; 01711 return Expr(pred.mkOp(), e).andExpr(getTypePred(argTp, e)); 01712 } 01713 case APPLY: { 01714 Theory* i = theoryOf(e); 01715 if (i != this) return i->computeTypePred(t, e); 01716 // fall through 01717 } 01718 default: 01719 return e.getEM()->trueExpr(); 01720 } 01721 } 01722 01723 01724 Expr TheoryCore::parseExprOp(const Expr& e) 01725 { 01726 // If the expression is not a list, it must have been already 01727 // parsed, so just return it as is. 01728 switch(e.getKind()) { 01729 case ID: { 01730 int kind = getEM()->getKind(e[0].getString()); 01731 switch(kind) { 01732 case NULL_KIND: return e; // nothing to do 01733 case TRUE_EXPR: 01734 case FALSE_EXPR: 01735 case TYPE: 01736 case BOOLEAN: return getEM()->newLeafExpr(kind); 01737 default: 01738 DebugAssert(false, "Bad use of bare keyword: "+e.toString()); 01739 return e; 01740 } 01741 } 01742 case RAW_LIST: break; // break out of switch, do the work 01743 default: 01744 return e; 01745 } 01746 DebugAssert(e.getKind()==RAW_LIST && e.arity() > 0 && e[0].getKind()==ID, 01747 "TheoryCore::parseExprOp:\n e = "+e.toString()); 01748 TRACE("parse", "TheoryCore::parseExprOp:\n e = ", e.toString(), ""); 01749 /* The first element of the list (e[0] is an ID of the operator. 01750 ID string values are the dirst element of the expression */ 01751 const Expr& c1 = e[0][0]; 01752 int kind = getEM()->getKind(c1.getString()); 01753 01754 if (isBasicKind(kind)) { 01755 vector<Expr> operatorStack; 01756 vector<Expr> operandStack; 01757 vector<int> childStack; 01758 Expr e2; 01759 01760 operatorStack.push_back(e); 01761 childStack.push_back(1); 01762 01763 while (!operatorStack.empty()) { 01764 DebugAssert(operatorStack.size() == childStack.size(), "Invariant violated"); 01765 01766 if (childStack.back() < operatorStack.back().arity()) { 01767 01768 e2 = operatorStack.back()[childStack.back()++]; 01769 01770 ExprMap<Expr>::iterator iParseCache = d_parseCache->find(e2); 01771 if (iParseCache != d_parseCache->end()) { 01772 operandStack.push_back((*iParseCache).second); 01773 } 01774 else if (e2.getKind() == RAW_LIST && 01775 e2.arity() > 0 && 01776 e2[0].getKind() == ID && 01777 isBasicKind(getEM()->getKind(e2[0][0].getString()))) { 01778 operatorStack.push_back(e2); 01779 childStack.push_back(1); 01780 } 01781 else { 01782 operandStack.push_back(parseExpr(e2)); 01783 } 01784 } 01785 else { 01786 e2 = operatorStack.back(); 01787 operatorStack.pop_back(); 01788 childStack.pop_back(); 01789 vector<Expr> children; 01790 vector<Expr>::iterator childStart = operandStack.end() - (e2.arity() - 1); 01791 children.insert(children.begin(), childStart, operandStack.end()); 01792 operandStack.erase(childStart, operandStack.end()); 01793 kind = getEM()->getKind(e2[0][0].getString()); 01794 operandStack.push_back(Expr(kind, children, e2.getEM())); 01795 (*d_parseCache)[e2] = operandStack.back(); 01796 if (!getEM()->isTypeKind(operandStack.back().getKind())) { 01797 operandStack.back().getType(); 01798 } 01799 } 01800 } 01801 DebugAssert(childStack.empty(), "Invariant violated"); 01802 DebugAssert(operandStack.size() == 1, "Expected single operand left"); 01803 return operandStack.back(); 01804 } 01805 01806 switch(kind) { 01807 case SUBTYPE: 01808 if (e.arity() <= 3) { 01809 Expr witness; 01810 if (e.arity() == 3) { 01811 witness = parseExpr(e[2]); 01812 } 01813 return newSubtypeExpr(parseExpr(e[1]), witness).getExpr(); 01814 } 01815 else { 01816 throw ParserException("Expected one or two arguments to SUBTYPE"); 01817 } 01818 case EQ: 01819 if(e.arity()==3) { 01820 Expr e1 = parseExpr(e[1]); 01821 Expr e2 = parseExpr(e[2]); 01822 if (e1.getType() == boolType() && 01823 getFlags()["convert-eq-iff"].getBool()) { 01824 return e1.iffExpr(e2); 01825 } 01826 else { 01827 return e1.eqExpr(e2); 01828 } 01829 } 01830 else 01831 throw ParserException("Equality requires exactly two arguments: " 01832 +e.toString()); 01833 break; 01834 01835 case NEQ: 01836 if(e.arity()==3) 01837 return !(parseExpr(e[1]).eqExpr(parseExpr(e[2]))); 01838 else 01839 throw ParserException("Disequality requires exactly two arguments: " 01840 +e.toString()); 01841 break; 01842 case TYPE: { 01843 if(e.arity()==2) { 01844 const Expr& types = e[1]; 01845 if(types.getKind() == RAW_LIST) { 01846 vector<Expr> names; 01847 for(Expr::iterator i=types.begin(), iend=types.end(); i!=iend; ++i) 01848 names.push_back(*i); 01849 return Expr(TYPEDECL, names, getEM()); 01850 } 01851 } 01852 else if(e.arity() == 3 && e[1].getKind() == ID) 01853 return Expr(TYPEDEF, e[1], parseExpr(e[2])); 01854 throw ParserException("Bad TYPE declaration: "+e.toString()); 01855 break; 01856 } 01857 //TODO: Is IF still used? 01858 case IF: 01859 if(e.arity() == 4) { 01860 Expr c(parseExpr(e[1])); 01861 Expr e1(parseExpr(e[2])); 01862 Expr e2(parseExpr(e[3])); 01863 return c.iteExpr(e1, e2); 01864 } else 01865 throw ParserException("Bad IF-THEN-ELSE expression: " 01866 +e.toString()); 01867 case COND: { 01868 if(e.arity() >= 3) 01869 return processCond(e, 1); 01870 else 01871 throw ParserException("Bad COND expression: "+e.toString()); 01872 break; 01873 } 01874 case LET: { // (LET ((v1 e1) (v2 e2) ... ) body) 01875 Expr e2(e); 01876 while (true) { 01877 if(!(e2.arity() == 3 && e2[1].getKind() == RAW_LIST && e2[1].arity() > 0)) 01878 throw ParserException("Bad LET expression: "+e2.toString()); 01879 01880 // Iterate through the bound variables 01881 for(Expr::iterator i=e2[1].begin(), iend=e2[1].end(); i!=iend; ++i) { 01882 const Expr& decl = *i; 01883 if (decl.getKind() != RAW_LIST || decl.arity() != 2) 01884 throw ParserException("Bad variable declaration block in LET " 01885 "expression: "+decl.toString()+ 01886 "\n e2 = "+e2.toString()); 01887 if (decl[0].getKind() != ID) 01888 throw ParserException("Variable must be an identifier in LET " 01889 "expression: "+decl[0].toString()+ 01890 "\n e2 = "+e2.toString()); 01891 addBoundVar(decl[0][0].getString(), Type(), parseExpr(decl[1])); 01892 } 01893 // Optimization for nested LETs: 01894 if (e2[2].getKind()==RAW_LIST && e2[2].arity() > 0 && 01895 e2[2][0].getKind()==ID && getEM()->getKind(e2[2][0][0].getString()) == LET) { 01896 e2 = e2[2]; 01897 } else break; 01898 } 01899 // Parse the body recursively and return it (nuke the LET) 01900 return parseExpr(e2[2]); 01901 } 01902 case TRUE_EXPR: { return e.getEM()->trueExpr(); } 01903 case FALSE_EXPR: { return e.getEM()->falseExpr();} 01904 case BOOLEAN: { return e.getEM()->boolExpr(); } 01905 break; 01906 default: 01907 DebugAssert(false, 01908 "TheoryCore::parseExprOp: invalid command or expression: " 01909 + e.toString()); 01910 break; 01911 } 01912 return e; 01913 } 01914 01915 ExprStream& TheoryCore::printSmtLibShared(ExprStream& os, const Expr& e) { 01916 DebugAssert(os.lang() == SMTLIB_LANG || os.lang() == SMTLIB_V2_LANG, 01917 "Invalid state in printSmtLibShared" ); 01918 switch(e.getKind()) { 01919 case TRUE_EXPR: os << "true"; break; 01920 case FALSE_EXPR: os << "false"; break; 01921 case UCONST: os << d_translator->escapeSymbol(d_translator->fixConstName(e.getName())); break; 01922 case BOOLEAN: e.printAST(os); break; 01923 case STRING_EXPR: e.print(os); break; 01924 case SUBTYPE: 01925 throw SmtlibException("TheoryCore::print: SMTLIB: SUBTYPE not implemented"); 01926 break; 01927 case TYPEDEF: { 01928 throw SmtlibException("TheoryCore::print: SMTLIB: TYPEDEF not implemented"); 01929 break; 01930 } 01931 case EQ: 01932 os << "(" << push << "=" << space << e[0] 01933 << space << e[1] << push << ")"; 01934 break; 01935 case DISTINCT: { 01936 int i=0, iend=e.arity(); 01937 os << "(" << push << "distinct"; 01938 for(; i!=iend; ++i) os << space << e[i]; 01939 os << push << ")"; 01940 break; 01941 } 01942 case NOT: 01943 os << "(" << push << "not" << space << e[0] << push << ")"; 01944 break; 01945 case AND: { 01946 int i=0, iend=e.arity(); 01947 if(iend == 1 && os.lang() == SMTLIB_V2_LANG) { 01948 os << e[0]; 01949 } else { 01950 os << "(" << push << "and"; 01951 for(; i!=iend; ++i) os << space << e[i]; 01952 os << push << ")"; 01953 } 01954 break; 01955 } 01956 case OR: { 01957 int i=0, iend=e.arity(); 01958 if(iend == 1 && os.lang() == SMTLIB_V2_LANG) { 01959 os << e[0]; 01960 } else { 01961 os << "(" << push << "or"; 01962 for(; i!=iend; ++i) os << space << e[i]; 01963 os << push << ")"; 01964 } 01965 break; 01966 } 01967 case XOR: { 01968 int i=0, iend=e.arity(); 01969 if(iend == 1 && os.lang() == SMTLIB_V2_LANG) { 01970 os << e[0]; 01971 } else { 01972 os << "(" << push << "xor"; 01973 for(; i!=iend; ++i) os << space << e[i]; 01974 os << push << ")"; 01975 } 01976 break; 01977 } 01978 01979 case TRANSFORM: 01980 throw SmtlibException("TheoryCore::print: SMTLIB: TRANSFORM not implemented"); 01981 os << "(" << push << "TRANSFORM" << space << e[0] << push << ")"; 01982 break; 01983 01984 case LETDECL: 01985 // throw SmtlibException("TheoryCore::print: SMTLIB: LETDECL not implemented"); 01986 if(e.arity() == 2) os << e[1]; 01987 else e.printAST(os); 01988 break; 01989 01990 01991 case PF_APPLY: { 01992 DebugAssert(e.arity() > 0, "TheoryCore::print(): " 01993 "Proof rule application must have at " 01994 "least one argument (rule name):\n "+e.toString()); 01995 // os << e[0]; by yeting 01996 os << e[0] << "\n" ; 01997 if(e.arity() > 1) { // Print the arguments 01998 os << push << "(" << push; 01999 bool first(true); 02000 for(int i=1; i<e.arity(); i++) { 02001 if(first) first=false; 02002 else os << push << "," << pop << space; 02003 // os << e[i]; by yeting 02004 os << e[i] << "\n"; 02005 } 02006 os << push << ")"; 02007 } 02008 break; 02009 } 02010 case RAW_LIST: { 02011 os << "(" << push; 02012 bool firstTime(true); 02013 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { 02014 if(firstTime) firstTime = false; 02015 else os << space; 02016 os << *i; 02017 } 02018 os << push << ")"; 02019 break; 02020 } 02021 case ANY_TYPE: 02022 os << "ANY_TYPE"; 02023 break; 02024 02025 case PF_HOLE: // FIXME: implement this (now fall through to default) 02026 default: 02027 throw SmtlibException("TheoryCore::print: SMTLIB_LANG: Unexpected expression: " 02028 +getEM()->getKindName(e.getKind())); 02029 } 02030 return os; 02031 } 02032 02033 static bool containsRec(const Expr& def, ExprHashMap<bool>& defs, ExprHashMap<bool>& visited) { 02034 ExprHashMap<bool>::iterator it = visited.find(def); 02035 if (it != visited.end()) return false; 02036 it = defs.find(def); 02037 if (it != defs.end()) return true; 02038 for(Expr::iterator i = def.begin(), iend=def.end(); i != iend; ++i) { 02039 if (containsRec(*i,defs,visited)) return true; 02040 } 02041 // [MGD] Closure exprs (LAMBDAs and quantifiers) don't have children, 02042 // they have bodies. 02043 if(def.isClosure()) { 02044 if (containsRec(def.getBody(),defs,visited)) return true; 02045 } 02046 visited[def] = true; 02047 return false; 02048 } 02049 02050 static bool contains(const Expr& def, ExprHashMap<bool>& defs) { 02051 ExprHashMap<bool> visited; 02052 return containsRec(def, defs, visited); 02053 } 02054 02055 ExprStream& TheoryCore::print(ExprStream& os, const Expr& e) 02056 { 02057 switch(os.lang()) { 02058 case SPASS_LANG: 02059 switch(e.getKind()) { 02060 case TRUE_EXPR: os << "true"; break; 02061 case FALSE_EXPR: os << "false"; break; 02062 case UCONST: 02063 if(isReal(getBaseType(e.getType()))) { 02064 // SPASS guys want "np" prefix on arith vars 02065 os << "np"; 02066 } 02067 os << e.getName(); 02068 break; 02069 case BOOLEAN: e.printAST(os); break; 02070 case STRING_EXPR: e.print(os); break; 02071 case TYPE: 02072 throw SmtlibException("TheoryCore::print: SPASS_LANG: TYPE should have been handled by Translator::finish()"); 02073 case ID: 02074 if(e.arity() == 1 && e[0].isString()) os << e[0].getString(); 02075 else e.printAST(os); 02076 break; 02077 case CONST: 02078 throw SmtlibException("TheoryCore::print: SPASS_LANG: CONST should have been handled by Translator::finish()"); 02079 case SUBTYPE: 02080 throw SmtlibException("TheoryCore::print: SPASS_LANG: SUBTYPE not implemented"); 02081 break; 02082 case TYPEDEF: { 02083 throw SmtlibException("TheoryCore::print: SPASS_LANG: TYPEDEF not implemented"); 02084 break; 02085 } 02086 case EQ: 02087 os << push << "equal(" << e[0] 02088 << "," << space << e[1] << push << ")"; 02089 break; 02090 case DISTINCT: { 02091 throw SmtlibException("TheoryCore::print: SPASS_LANG: SUBTYPE not implemented"); 02092 break; 02093 } 02094 case NOT: 02095 os << push << "not(" << e[0] << push << ")"; 02096 break; 02097 case AND: { 02098 int i=0, iend=e.arity(); 02099 os << push << "and(" << e[i]; 02100 while(++i != iend) os << "," << space << e[i]; 02101 os << push << ")"; 02102 break; 02103 } 02104 case OR: { 02105 int i=0, iend=e.arity(); 02106 os << push << "or(" << e[i]; 02107 while(++i != iend) os << "," << space << e[i]; 02108 os << push << ")"; 02109 break; 02110 } 02111 case XOR: { 02112 if(e.arity() != 2) { 02113 throw SmtlibException("TheoryCore::print: SPASS_LANG: XOR not supported when arity != 2 !"); 02114 } 02115 os << push << "or(and(" << e[0] << "," << space << "not(" << e[1] << "))," 02116 << space << "and(not(" << e[0] << ")," << space << e[1] << ")" 02117 << push << ")"; 02118 break; 02119 } 02120 case ITE: 02121 if (e.getType().isBool()) { 02122 os << push << "and(" << space 02123 << push << "implies(" << space 02124 << e[0] << "," << space << e[1] 02125 << push << ")" << "," << space 02126 << push << "implies(" << space 02127 << e[0].negate() << "," << space << e[2] 02128 << push << ")" 02129 << push << ")"; 02130 } else { 02131 os << push << "if_then_else(" 02132 << e[0] << "," << space 02133 << e[1] << "," << space 02134 << e[2] << push << ")"; 02135 } 02136 break; 02137 case IFF: 02138 os << push << "equiv(" << space 02139 << e[0] << space << "," << space << e[1] << push << ")"; 02140 break; 02141 case IMPLIES: 02142 os << push << "implies(" << space 02143 << e[0] << space << "," << space << e[1] << push << ")"; 02144 break; 02145 case ASSERT: 02146 // SPASS guys don't want formula(false) etc: comment them out 02147 if(e[0] == d_em->trueExpr() || 02148 e[0] == d_em->falseExpr().notExpr()) { 02149 os << "% "; 02150 } 02151 os << "formula(" << space << push << e[0].negate() << space << ")."; 02152 break; 02153 case TRANSFORM: 02154 throw SmtlibException("TheoryCore::print: SPASS: TRANSFORM not implemented"); 02155 break; 02156 case QUERY: 02157 // SPASS guys don't want formula(false) etc: comment them out 02158 if(e[0].negate() == d_em->trueExpr() || 02159 e[0].negate() == d_em->falseExpr().notExpr()) { 02160 os << "% "; 02161 } 02162 os << "formula(" << space << push << e[0] << space << ")."; 02163 break; 02164 case LETDECL: 02165 throw SmtlibException("TheoryCore::print: SPASS_LANG: LETDECL not implemented"); 02166 case LET: 02167 throw SmtlibException("TheoryCore::print: SPASS_LANG: LET should have been handled in Translator::finish()"); 02168 case BOUND_VAR: 02169 if(isReal(getBaseType(e.getType()))) { 02170 // SPASS guys want "np" prefix on arith vars 02171 os << "np"; 02172 } 02173 os << e.getName(); 02174 break; 02175 case SKOLEM_VAR: 02176 os << push << "SKOLEM_" + int2string((int)e.getIndex()); 02177 break; 02178 case PF_APPLY: 02179 throw SmtlibException("TheoryCore::print: SPASS_LANG: PF_APPLY not implemented"); 02180 case ANNOTATION: 02181 throw SmtlibException("TheoryCore::print: SPASS_LANG: ANNOTATION should have been handled by Translator::finish()"); 02182 02183 case RAW_LIST: 02184 case ANY_TYPE: 02185 case WHERE: 02186 case ASSERTIONS: 02187 case ASSUMPTIONS: 02188 case COUNTEREXAMPLE: 02189 case COUNTERMODEL: 02190 case PUSH: 02191 case POP: 02192 case POPTO: 02193 case PUSH_SCOPE: 02194 case POP_SCOPE: 02195 case POPTO_SCOPE: 02196 case RESET: 02197 case PF_HOLE: 02198 default: 02199 throw SmtlibException("TheoryCore::print: SPASS_LANG: Unexpected expression: " 02200 +getEM()->getKindName(e.getKind())); 02201 } 02202 break; // end of case SPASS_LANG 02203 02204 case SIMPLIFY_LANG: 02205 switch(e.getKind()) { 02206 case TRUE_EXPR: os << "TRUE"; break; 02207 case FALSE_EXPR: os << "FALSE"; break; 02208 case TYPE: 02209 break; // no type for Simplify 02210 case ID: 02211 if(e.arity() == 1 && e[0].isString()) os << e[0].getString(); 02212 else e.print(os); 02213 break; 02214 case CONST: 02215 // os << "ERROR:const to be supported\n"; simplify do not need this 02216 break; 02217 case SUBTYPE: 02218 break; 02219 case TYPEDEF: { 02220 break; 02221 } 02222 case EQ: 02223 os << "(EQ " << e[0] << " " << e[1] << ")"; 02224 break; 02225 case NOT: os << "(NOT " << e[0] << ")"; break; 02226 case AND: { 02227 int i=0, iend=e.arity(); 02228 os << "(AND "; 02229 if(i!=iend) { os << e[i]; ++i; } 02230 for(; i!=iend; ++i) os << " " << e[i]; 02231 os << ")"; 02232 } 02233 break; 02234 case OR: { 02235 int i=0, iend=e.arity(); 02236 os << "(OR "; 02237 if(i!=iend) { os << e[i]; ++i; } 02238 for(; i!=iend; ++i) os << " " << e[i]; 02239 os << ")"; 02240 } 02241 break; 02242 case ITE: 02243 os<<"ERROR:ITE:not supported yet\n"; 02244 break; 02245 case IFF: 02246 if(e.arity() == 2) 02247 os << "(IFF " << e[0] << " " << e[1] << ")"; 02248 else 02249 e.print(os); 02250 break; 02251 case IMPLIES: 02252 os << "(IMPLIES " <<e[0] << " " << e[1] << ")"; 02253 break; 02254 // Commands 02255 case ASSERT: 02256 os << "(BG_PUSH " << e[0] << ")\n"; 02257 break; 02258 case TRANSFORM: 02259 os << "ERROR:TRANSFORM:not supported in Simplify " << push << e[0] << push << "\n"; 02260 break; 02261 case QUERY: 02262 os << e[0] <<"\n"; 02263 break; 02264 case WHERE: 02265 os << "ERROR:WHERE:not supported in Simplify\n"; 02266 break; 02267 case ASSERTIONS: 02268 os << "ERROR:ASSERTIONS:not supported in Simplify\n"; 02269 break; 02270 case ASSUMPTIONS: 02271 os << "ERROR:ASSUMPTIONS:not supported in Simplify\n"; 02272 break; 02273 case COUNTEREXAMPLE: 02274 os << "ERROR:COUNTEREXAMPLE:not supported in Simplify\n"; 02275 break; 02276 case COUNTERMODEL: 02277 os << "ERROR:COUNTERMODEL:not supported in Simplify\n"; 02278 break; 02279 case PUSH: 02280 case POP: 02281 case POPTO: 02282 case PUSH_SCOPE: 02283 case POP_SCOPE: 02284 case POPTO_SCOPE: 02285 case RESET: 02286 os << "ERROR:PUSH and POP:not supported in Simplify\n"; 02287 break; 02288 // case CONSTDEF: 02289 case LETDECL: 02290 os << "LETDECL not supported in Simplify\n"; 02291 break; 02292 case LET: { 02293 // (LET (LETDECLS (LETDECL var [ type ] val) .... ) body) 02294 /* bool first(true); 02295 os << "(" << push << "LET" << space << push; 02296 for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) { 02297 if(!first) os << push << "," << pop << endl; 02298 else first = false; 02299 if(i->arity() == 3) { 02300 os << (*i)[0] << ":" << space << push << (*i)[1] 02301 << space << "= " << push << nodag << (*i)[2] << pop << pop; 02302 } else { 02303 os << (*i)[0]; 02304 Type tp((*i)[0].lookupType()); 02305 if(!tp.isNull()) os << ":" << space << push << tp.getExpr(); 02306 else os << push; 02307 os << space << "= " << push << nodag << (*i)[1] << pop << pop; 02308 } 02309 } 02310 os << pop << endl << "IN" << space << push << e[1] << push << ")"; 02311 */ 02312 os << "LET not supported in Simplify\n"; 02313 break; 02314 02315 } 02316 case BOUND_VAR: 02317 // os << e.getName()+"_"+e.getUid(); // by yeting for a neat output 02318 os << e.getName(); 02319 break; 02320 case SKOLEM_VAR: 02321 os << "SKOLEM_" + int2string((int)e.getIndex()); 02322 break; 02323 case PF_APPLY: // FIXME: this will eventually go to the "symsim" theory 02324 /* DebugAssert(e.arity() > 0, "TheoryCore::print(): " 02325 "Proof rule application must have at " 02326 "least one argument (rule name):\n "+e.toString()); 02327 os << e[0]; 02328 if(e.arity() > 1) { // Print the arguments 02329 os << push << "(" << push; 02330 bool first(true); 02331 for(int i=1; i<e.arity(); i++) { 02332 if(first) first=false; 02333 else os << push << "," << pop << space; 02334 os << e[i]; 02335 } 02336 os << push << ")"; 02337 }*/ 02338 02339 os << "PR_APPLY not supported in Simplify\n"; 02340 break; 02341 case RAW_LIST: { 02342 /* os << "[" << push; 02343 bool firstTime(true); 02344 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { 02345 if(firstTime) firstTime = false; 02346 else os << push << "," << pop << space; 02347 os << *i; 02348 } 02349 os << push << "]";*/ 02350 os << "RAW_LIST not supported in Simplify\n"; 02351 break; 02352 } 02353 case PF_HOLE: // FIXME: implement this (now fall through to default) 02354 default: 02355 // Print the top node in the default LISP format, continue with 02356 // pretty-printing for children. 02357 e.print(os); 02358 } 02359 break; // end of case simplify_LANG 02360 02361 case TPTP_LANG: { 02362 static int axiom_counter =0; 02363 switch(e.getKind()) { 02364 case TRUE_EXPR: os << "$true"; break; 02365 case FALSE_EXPR: os << "$false"; break; 02366 case TYPE: 02367 break; 02368 if(e.arity() == 0) os << "TYPE"; 02369 else if(e.arity() == 1) { 02370 for (int i=0; i < e[0].arity(); ++i) { 02371 if (i != 0) os << endl; 02372 os << e[0][i] << ": TYPE;"; 02373 } 02374 } 02375 else if(e.arity() == 2) 02376 os << e[0] << ":" << push << " TYPE = " << e[1] << push << ";"; 02377 else e.printAST(os); 02378 break; 02379 case ID: 02380 if(e.arity() == 1 && e[0].isString()) os << e[0].getString(); 02381 else e.print(os); 02382 break; 02383 case CONST: 02384 if(e.arity() == 2) { 02385 string ename = to_lower(e[0].toString()); 02386 os << "tff(" << ename << "_type, type,\n " << ename; 02387 os << ": " << e[1] << "). \n"; 02388 } 02389 else { 02390 os << "ERROR: CONST's arity > 2"; 02391 } 02392 break; 02393 02394 case SUBTYPE: 02395 break; 02396 case TYPEDEF: { 02397 break; 02398 } 02399 case EQ: 02400 os << e[0] << " = " << e[1]; 02401 break; 02402 02403 case DISTINCT: { 02404 int i=0, iend=e.arity(); 02405 os << "$distinct(" ; 02406 os << e[i] ; 02407 i++; 02408 for(; i!=iend; ++i) os << ", " << e[i] ; 02409 os << ")"; 02410 break; 02411 } 02412 02413 case NOT: 02414 os << "~(" << e[0]<<")" ; 02415 break; 02416 02417 case AND: { 02418 int i=0, iend=e.arity(); 02419 if(iend == 1) { 02420 os << e[i]; 02421 } 02422 02423 else if(iend > 1) { 02424 for(i=0 ; i < iend-1; i++) { 02425 os << "(" << e[i] << " \n& " ; 02426 } 02427 os << e[iend-1]; 02428 for(i=0 ; i < iend-1; i++) { 02429 os << ")"; 02430 } 02431 } 02432 else{ 02433 os <<"ERROR:AND has less than 1 parameter\n"; 02434 } 02435 break; 02436 } 02437 case OR: { 02438 int i=0, iend=e.arity(); 02439 if(iend == 1) { 02440 os << e[i]; 02441 } 02442 02443 else if(iend > 1) { 02444 for(i=0 ; i < iend-1; i++) { 02445 os << "(" << e[i] << " \n| " ; 02446 } 02447 os << e[iend-1]; 02448 for(i=0 ; i < iend-1; i++) { 02449 os << ")"; 02450 } 02451 } 02452 else{ 02453 os <<"ERROR:OR has less than 1 parameter\n"; 02454 } 02455 break; 02456 } 02457 case ITE: 02458 os<<"ERROR:ITE:not supported in TPTP yet\n"; 02459 /* os << "(AND (IMPLIES "<< e[0] << " " << e[1]<<")" 02460 << "(IMPLIES (NOT " <<e[0] << ")" << e[2] <<"))"; 02461 */ 02462 break; 02463 case IFF: 02464 if(e.arity() == 2) 02465 os << "(" << e[0] << " \n<=> " << e[1] << ")" ; 02466 else 02467 e.print(os); 02468 break; 02469 case IMPLIES: 02470 os << "(" << e[0] << " \n=> " << e[1] << ")" ; 02471 break; 02472 // Commands 02473 case ASSERT: 02474 os << "tff(" << axiom_counter++ << ", axiom, \n " <<e[0] << ").\n"; 02475 02476 break; 02477 case TRANSFORM: 02478 os << "ERROR:TRANSFORM:not supported in TPTP " << push << e[0] << push << "\n"; 02479 break; 02480 case QUERY: 02481 if(getFlags()["negate-query"].getBool() == true){ 02482 if (e[0].isNot()){ 02483 os << "tff(" << axiom_counter++ << ", conjecture, \n " <<e[0][0] << ").\n"; 02484 } 02485 else{ 02486 os << "tff(" << axiom_counter++ << ", conjecture, \n ~(" << e[0] << ")).\n"; 02487 } 02488 } 02489 else{ 02490 os << "tff(" << axiom_counter++ << ", conjecture, \n " <<e[0] << ").\n"; 02491 } 02492 break; 02493 case WHERE: 02494 os << "ERROR:WHERE:not supported in TPTP\n"; 02495 break; 02496 case ASSERTIONS: 02497 os << "ERROR:ASSERTIONS:not supported in TPTP\n"; 02498 break; 02499 case ASSUMPTIONS: 02500 os << "ERROR:ASSUMPTIONS:not supported in TPTP\n"; 02501 break; 02502 case COUNTEREXAMPLE: 02503 os << "ERROR:COUNTEREXAMPLE:not supported in TPTP\n"; 02504 break; 02505 case COUNTERMODEL: 02506 os << "ERROR:COUNTERMODEL:not supported in TPTP\n"; 02507 break; 02508 case PUSH: 02509 case POP: 02510 case POPTO: 02511 case PUSH_SCOPE: 02512 case POP_SCOPE: 02513 case POPTO_SCOPE: 02514 case RESET: 02515 os << "ERROR:PUSH and POP:not supported in TPTP\n"; 02516 break; 02517 // case CONSTDEF: 02518 case LETDECL: 02519 os << "LETDECL not supported in Simplify\n"; 02520 break; 02521 case LET: { 02522 bool first(true); 02523 os << " := [" ; 02524 for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) { 02525 if(!first) os << " , " ; 02526 else first = false; 02527 if(i->arity() == 3) { 02528 os << (*i)[0] << ":" << (*i)[1] 02529 << " ERROR= " << nodag << (*i)[2] ; 02530 } else { 02531 os << (*i)[0]; 02532 os << " := " << nodag << (*i)[1] ; 02533 } 02534 os <<endl; 02535 } 02536 os << "] : " << endl << "(" << e[1] << ")"; 02537 break; 02538 02539 } 02540 02541 case BOUND_VAR:{ 02542 // os << e.getName()+"_"+e.getUid() ; // by yeting 02543 os<< to_upper(e.getName()); 02544 break; 02545 } 02546 case SKOLEM_VAR: 02547 os << "SKOLEM_VAR is not supported in TPTP\n"; 02548 break; 02549 02550 case PF_APPLY: // FIXME: this will eventually go to the "symsim" theory 02551 /* DebugAssert(e.arity() > 0, "TheoryCore::print(): " 02552 "Proof rule application must have at " 02553 "least one argument (rule name):\n "+e.toString()); 02554 os << e[0]; 02555 if(e.arity() > 1) { // Print the arguments 02556 os << push << "(" << push; 02557 bool first(true); 02558 for(int i=1; i<e.arity(); i++) { 02559 if(first) first=false; 02560 else os << push << "," << pop << space; 02561 os << e[i]; 02562 } 02563 os << push << ")"; 02564 }*/ 02565 02566 os << "PR_APPLY not supported in TPTP\n"; 02567 break; 02568 case RAW_LIST: { 02569 /* os << "[" << push; 02570 bool firstTime(true); 02571 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { 02572 if(firstTime) firstTime = false; 02573 else os << push << "," << pop << space; 02574 os << *i; 02575 } 02576 os << push << "]";*/ 02577 os << "RAW_LIST not supported in TPTP\n"; 02578 break; 02579 } 02580 case PF_HOLE: 02581 os << "PF_HOLE not supported in TPTP\n"; 02582 break; 02583 case UCONST: 02584 {string name = e.getName(); 02585 if(name.length() >= 5){ 02586 if ('C' == name[0] && 'V' == name[1] && 'C' == name[2] && '_' == name[3] && isdigit(name[4])){ 02587 os << to_upper(name); 02588 } 02589 else { 02590 os << to_lower(name); 02591 } 02592 } 02593 else { 02594 os<<to_lower(name); 02595 } 02596 // 02597 // e.print(os); break; 02598 break; 02599 } 02600 case STRING_EXPR: 02601 os <<"ERROR:STRING_EXPR is not suppoerted in TPTP\n"; 02602 e.print(os); break; 02603 case BOOLEAN: 02604 os << "$o"; 02605 break; 02606 default: 02607 // Print the top node in the default LISP format, continue with 02608 // pretty-printing for children. 02609 os<<"unknown "; 02610 // cout<<e.toString(PRESENTATION_LANG)<<endl; 02611 // cout<<getEM()->getKindName(e.getKind())<<endl; 02612 e.print(os); 02613 } 02614 break; // end of case TPTP_LANG 02615 } 02616 02617 02618 case PRESENTATION_LANG: 02619 switch(e.getKind()) { 02620 case TRUE_EXPR: 02621 os << "TRUE"; 02622 break; 02623 case FALSE_EXPR: 02624 os << "FALSE"; 02625 break; 02626 case BOOLEAN: 02627 os << "BOOLEAN"; 02628 break; 02629 case UCONST: 02630 case STRING_EXPR: 02631 e.print(os); break; 02632 case TYPE: 02633 if(e.arity() == 0) os << "TYPE"; 02634 else if(e.arity() == 1) { 02635 for (int i=0; i < e[0].arity(); ++i) { 02636 if (i != 0) os << endl; 02637 os << e[0][i] << ": TYPE;"; 02638 } 02639 } 02640 else if(e.arity() == 2) 02641 os << e[0] << ":" << push << " TYPE = " << e[1] << push << ";"; 02642 else e.printAST(os); 02643 break; 02644 case ID: 02645 if(e.arity() == 1 && e[0].isString()) os << e[0].getString(); 02646 else e.printAST(os); 02647 break; 02648 case CONST: 02649 if(e.arity() == 2) { 02650 if(e[0].getKind() == RAW_LIST) { 02651 bool first(true); 02652 for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) { 02653 if(first) first = false; 02654 else os << push << "," << pop << space; 02655 os << (*i); 02656 } 02657 } 02658 else 02659 os << e[0]; 02660 os << ":" << push << space << e[1] << push << ";"; 02661 } else if(e.arity() == 3) 02662 os << e[0] << ":" << push << space << e[1] 02663 << space << "=" << space << push << e[2] << push << ";"; 02664 else 02665 e.printAST(os); 02666 break; 02667 case SUBTYPE: 02668 os << "SUBTYPE(" << push << e[0] << push << ")"; 02669 break; 02670 case TYPEDEF: { 02671 // This is used when dumping declarations to file. Print just 02672 // the name of the type, unless it's a messed-up expression. 02673 if(e.arity() != 2) e.printAST(os); 02674 else if(e[0].isString()) os << e[0].getString(); 02675 else e[0].print(os); 02676 break; 02677 } 02678 case EQ: 02679 // When a separator starts with a space (like " = "), add the 02680 // leading space with 'space' modifier. If this separator goes 02681 // to the next line, the leading spaces must be eaten up to get 02682 // the indentation right; 'space' will tell the indentation 02683 // engine that it is a space that can be eaten. A space in a 02684 // string (like " ") will never be eaten. 02685 os << "(" << push << e[0] << space << "= " << e[1] << push << ")"; 02686 break; 02687 case DISTINCT: { 02688 os << "DISTINCT(" << push; 02689 bool first(true); 02690 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { 02691 if (!first) os << push << "," << pop << space; 02692 else first = false; 02693 os << (*i); 02694 } 02695 os << push << ")"; 02696 } 02697 break; 02698 case NOT: os << "NOT " << e[0]; break; 02699 case AND: { 02700 int i=0, iend=e.arity(); 02701 os << "(" << push; 02702 if(i!=iend) { os << e[i]; ++i; } 02703 for(; i!=iend; ++i) os << space << "AND " << e[i]; 02704 os << push << ")"; 02705 } 02706 break; 02707 case OR: { 02708 int i=0, iend=e.arity(); 02709 os << "(" << push; 02710 if(i!=iend) { os << e[i]; ++i; } 02711 for(; i!=iend; ++i) os << space << "OR " << e[i]; 02712 os << push << ")"; 02713 } 02714 break; 02715 case XOR: { 02716 int i=0, iend=e.arity(); 02717 os << "(" << push; 02718 if(i!=iend) { os << e[i]; ++i; } 02719 for(; i!=iend; ++i) os << space << "XOR " << e[i]; 02720 os << push << ")"; 02721 } 02722 break; 02723 case ITE: 02724 os << push << "IF " << push << e[0] << popSave 02725 << space << "THEN " << pushRestore << e[1] << popSave 02726 << space << "ELSE " << pushRestore << e[2] << pop 02727 << space << "ENDIF"; 02728 break; 02729 case IFF: 02730 if(e.arity() == 2) 02731 os << "(" << push << e[0] << space << "<=> " << e[1] << push << ")"; 02732 else 02733 e.printAST(os); 02734 break; 02735 case IMPLIES: 02736 os << "(" << push << e[0] << space << "=> " << e[1] << push << ")"; 02737 break; 02738 // Commands 02739 case ASSERT: 02740 os << "ASSERT " << push << e[0] << push << ";"; 02741 break; 02742 case TRANSFORM: 02743 os << "TRANSFORM " << push << e[0] << push << ";"; 02744 break; 02745 case QUERY: 02746 os << "QUERY " << push << e[0] << push << ";"; 02747 break; 02748 case WHERE: 02749 os << "WHERE;"; 02750 break; 02751 case ASSERTIONS: 02752 os << "ASSERTIONS;"; 02753 break; 02754 case ASSUMPTIONS: 02755 os << "ASSUMPTIONS;"; 02756 break; 02757 case COUNTEREXAMPLE: 02758 os << "COUNTEREXAMPLE;"; 02759 break; 02760 case COUNTERMODEL: 02761 os << "COUNTERMODEL;"; 02762 break; 02763 case PUSH: 02764 if(e.arity()==0) 02765 os << "PUSH;"; 02766 else 02767 os << "PUSH" << space << e[0] << push << ";"; 02768 break; 02769 case POP: 02770 if(e.arity()==0) 02771 os << "POP;"; 02772 else 02773 os << "POP" << space << e[0] << push << ";"; 02774 break; 02775 case POPTO: 02776 os << "POPTO" << space << e[0] << push << ";"; break; 02777 case PUSH_SCOPE: 02778 if(e.arity()==0) 02779 os << "PUSH_SCOPE;"; 02780 else 02781 os << "PUSH_SCOPE" << space << e[0] << push << ";"; 02782 break; 02783 case POP_SCOPE: 02784 if(e.arity()==0) 02785 os << "POP_SCOPE;"; 02786 else 02787 os << "POP_SCOPE" << space << e[0] << push << ";"; 02788 break; 02789 case POPTO_SCOPE: 02790 os << "POPTO_SCOPE" << space << e[0] << push << ";"; break; 02791 case RESET: 02792 os << "RESET;"; 02793 break; 02794 case LETDECL: 02795 if(e.arity() == 2) os << e[1]; 02796 else e.printAST(os); 02797 break; 02798 case LET: { 02799 // (LET (LETDECLS (LETDECL var [ type ] val) .... ) body) 02800 bool first(true); 02801 os << "(" << push << "LET" << space << push; 02802 for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) { 02803 if(!first) os << push << "," << pop << endl; 02804 else first = false; 02805 if(i->arity() == 3) { 02806 os << (*i)[0] << ":" << space << push << (*i)[1] 02807 << space << "= " << push << nodag << (*i)[2] << pop << pop; 02808 } else { 02809 os << (*i)[0]; 02810 Type tp((*i)[0].lookupType()); 02811 if(!tp.isNull()) os << ":" << space << push << tp.getExpr(); 02812 else os << push; 02813 os << space << "= " << push << nodag << (*i)[1] << pop << pop; 02814 } 02815 } 02816 os << pop << endl << "IN" << space << push << e[1] << push << ")"; 02817 break; 02818 } 02819 case BOUND_VAR: 02820 // os << e.getName()+"_"+e.getUid(); 02821 02822 //by yeting, as requested by Sascha Boehme for proofs 02823 if(getFlags()["print-var-type"].getBool()) { 02824 os << e.getName() << "(" << e.getType() << ")"; 02825 } 02826 else { 02827 os << e.getName(); //for better support of proof translation yeting 02828 } 02829 break; 02830 case SKOLEM_VAR: 02831 os << "SKOLEM_" + int2string((int)e.getIndex()); 02832 break; 02833 case PF_APPLY: // FIXME: this will eventually go to the "symsim" theory 02834 DebugAssert(e.arity() > 0, "TheoryCore::print(): " 02835 "Proof rule application must have at " 02836 "least one argument (rule name):\n "+e.toString()); 02837 // os << e[0]; by yeting 02838 os << e[0] << "\n" ; 02839 if(e.arity() > 1) { // Print the arguments 02840 os << push << "(" << push; 02841 bool first(true); 02842 for(int i=1; i<e.arity(); i++) { 02843 if(first) first=false; 02844 else os << push << "," << pop << space; 02845 // os << e[i]; by yeting 02846 os << e[i] << "\n"; 02847 } 02848 os << push << ")"; 02849 } 02850 break; 02851 case RAW_LIST: { 02852 os << "[" << push; 02853 bool firstTime(true); 02854 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { 02855 if(firstTime) firstTime = false; 02856 else os << push << "," << pop << space; 02857 os << *i; 02858 } 02859 os << push << "]"; 02860 break; 02861 } 02862 case ANY_TYPE: 02863 os << "ANY_TYPE"; 02864 break; 02865 case ARITH_VAR_ORDER: { 02866 os << "ARITH_VAR_ORDER(" << push; 02867 bool firstTime(true); 02868 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { 02869 if(firstTime) firstTime = false; 02870 else os << push << "," << pop << space; 02871 os << *i; 02872 } 02873 os << push << ");"; 02874 break; 02875 } 02876 case ANNOTATION: { 02877 os << "%% "; 02878 os << e[0]; 02879 if (e.arity() > 1) { 02880 os << ": " << e[1]; 02881 } 02882 } 02883 case PF_HOLE: // FIXME: implement this (now fall through to default) 02884 default: 02885 // Print the top node in the default LISP format, continue with 02886 // pretty-printing for children. 02887 e.printAST(os); 02888 } 02889 break; // end of case PRESENTATION_LANG 02890 02891 /* There's a lot of overlap between SMT-LIB v1 and v2, so we'll only handle 02892 * v1-specific stuff here, then goto (!) then end of the v2 block below. 02893 */ 02894 case SMTLIB_LANG: 02895 switch(e.getKind()) { 02896 case TYPE: 02897 if (e.arity() == 1) { 02898 os << " :extrasorts ("; 02899 for (int i=0; i < e[0].arity(); ++i) { 02900 if (i != 0) os << push << space; 02901 os << push << e[0][i]; 02902 } 02903 os << push << ")"; 02904 } 02905 else if (e.arity() == 2) { 02906 break; 02907 } 02908 else { 02909 throw SmtlibException("TheoryCore::print: SMTLIB: Unexpected TYPE expression"); 02910 } 02911 break; 02912 02913 case CONST: 02914 if(e.arity() == 2) { 02915 if (e[1].getKind() == BOOLEAN) { 02916 os << " :extrapreds ((" << push << d_translator->fixConstName(e[0][0].getString()) 02917 << push << "))"; 02918 } 02919 else if (e[1].getKind() == ARROW && e[1][e[1].arity()-1].getKind() == BOOLEAN) { 02920 os << " :extrapreds ((" << push << d_translator->fixConstName(e[0][0].getString()) 02921 << space << nodag << e[1] << push << "))"; 02922 } 02923 else { 02924 os << " :extrafuns ((" << push << d_translator->fixConstName(e[0][0].getString()) 02925 << space << nodag << e[1] << push << "))"; 02926 } 02927 } 02928 else if (e.arity() == 0) e.printAST(os); 02929 else { 02930 throw SmtlibException("TheoryCore::print: SMTLIB: CONST not implemented"); 02931 } 02932 break; 02933 02934 case ID: // FIXME: when lisp becomes case-insensitive, fix printing of IDs 02935 if(e.arity() == 1 && e[0].isString()) os << e[0].getString(); 02936 else e.printAST(os); 02937 break; 02938 02939 case IMPLIES: 02940 os << "(" << push << "implies" << space 02941 << e[0] << space << e[1] << push << ")"; 02942 break; 02943 02944 case IFF: 02945 os << "(" << push << "iff" << space 02946 << e[0] << space << e[1] << push << ")"; 02947 break; 02948 02949 case ITE: 02950 os << "(" << push; 02951 if (e.getType().isBool()) os << "if_then_else"; 02952 else os << "ite"; 02953 os << space << e[0] 02954 << space << e[1] << space << e[2] << push << ")"; 02955 break; 02956 02957 // Commands 02958 case ASSERT: 02959 os << " :assumption" << space << push << e[0]; 02960 break; 02961 02962 case QUERY: 02963 os << " :formula" << space << push << e[0].negate(); 02964 break; 02965 02966 case LET: { 02967 // (LET ((var [ type ] val) .... ) body) 02968 for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) { 02969 os << "(" << push; 02970 Type tp(i->arity() == 3 ? (*i)[2].getType() : (*i)[1].getType()); 02971 DebugAssert(!tp.isNull(), "Unexpected Null type"); 02972 if (tp.getExpr().getKind() == BOOLEAN) { 02973 os << "flet" << space << "(" << push; 02974 } 02975 else { 02976 os << "let" << space << "(" << push; 02977 } 02978 if(i->arity() == 3) { 02979 os << (*i)[0] << space << nodag << (*i)[2]; 02980 } else { 02981 os << (*i)[0] << space << nodag << (*i)[1]; 02982 } 02983 os << push << ")" << pop << pop << space; 02984 } 02985 os << e[1] << push; 02986 for (int j = 0; j < e[0].arity(); ++j) 02987 os << ")"; 02988 break; 02989 } 02990 02991 case BOUND_VAR: { 02992 // os << push << "?" << e.getName()+"_"+e.getUid(); 02993 string str = e.getName(); 02994 if (str[0] == '_') str[0] = '?'; 02995 os << push << str; 02996 break; 02997 } 02998 case SKOLEM_VAR: 02999 os << push << "SKOLEM_" + int2string((int)e.getIndex()); 03000 break; 03001 03002 case WHERE: 03003 os << " :cvc_command \"WHERE\""; 03004 break; 03005 case ASSERTIONS: 03006 os << " :cvc_command \"ASSERTIONS\""; 03007 break; 03008 case ASSUMPTIONS: 03009 os << " :cvc_command \"ASSUMPTIONS\""; 03010 break; 03011 case COUNTEREXAMPLE: 03012 os << " :cvc_command \"COUNTEREXAMPLE\""; 03013 break; 03014 case COUNTERMODEL: 03015 os << " :cvc_command \"COUNTERMODEL\""; 03016 break; 03017 case PUSH: 03018 os << " :cvc_command" << space; 03019 if(e.arity()==0) 03020 os << "\"PUSH\""; 03021 else 03022 os << "\"PUSH" << space << e[0] << push << "\""; 03023 break; 03024 case POP: 03025 os << " :cvc_command" << space; 03026 if(e.arity()==0) 03027 os << "\"POP\""; 03028 else 03029 os << "\"POP" << space << e[0] << push << "\""; 03030 break; 03031 case POPTO: 03032 os << " :cvc_command" << space; 03033 os << "\"POPTO" << space << e[0] << push << "\""; break; 03034 case PUSH_SCOPE: 03035 os << " :cvc_command" << space; 03036 if(e.arity()==0) 03037 os << "\"PUSH_SCOPE\""; 03038 else 03039 os << "\"PUSH_SCOPE" << space << e[0] << push << "\""; 03040 break; 03041 case POP_SCOPE: 03042 os << " :cvc_command" << space; 03043 if(e.arity()==0) 03044 os << "\"POP_SCOPE\""; 03045 else 03046 os << "\"POP_SCOPE" << space << e[0] << push << "\""; 03047 break; 03048 case POPTO_SCOPE: 03049 os << " :cvc_command" << space; 03050 os << "\"POPTO_SCOPE" << space << e[0] << push << "\""; break; 03051 break; 03052 case RESET: 03053 os << " :cvc_command" << space; 03054 os << "\"RESET\""; break; 03055 break; 03056 case ANNOTATION: { 03057 os << " :" << e[0].getString(); 03058 if (e[0].getString() == "notes") { 03059 os << space << e[1]; 03060 } 03061 else if (e.arity() > 1) { 03062 os << space << "{" << e[1].getString() << "}"; 03063 } 03064 break; 03065 } 03066 03067 default: /* Must be shared, jump to the end of SMT-LIB v2 symbols */ 03068 printSmtLibShared(os,e); 03069 } 03070 break; 03071 03072 case SMTLIB_V2_LANG: 03073 03074 switch(e.getKind()) { 03075 case TYPE: 03076 if (e.arity() == 1) { 03077 for (int i=0; i < e[0].arity(); ++i) { 03078 if( i!=0 ) { 03079 os << endl; 03080 } 03081 os << "(declare-sort" << space 03082 << push << nodag << e[0][i] << " 0)" << pop; 03083 } 03084 } else if (e.arity() == 2) { 03085 break; 03086 } else { 03087 throw SmtlibException("TheoryCore::print: SMTLIB: Unexpected TYPE expression"); 03088 } 03089 break; 03090 03091 case BOOLEAN: 03092 os << "Bool"; 03093 break; 03094 03095 case CONST: 03096 if(e.arity() == 2) { 03097 os << "(declare-fun" << space << push 03098 << d_translator->escapeSymbol(d_translator->fixConstName(e[0][0].getString())) 03099 << space; 03100 if( e[1].getKind() == ARROW ) { 03101 os << nodag << e[1]; 03102 } else { 03103 os << "()" << space << nodag << e[1]; 03104 } 03105 os << ")" << pop; 03106 } 03107 else if (e.arity() == 0) e.printAST(os); 03108 else { 03109 throw SmtlibException("TheoryCore::print: SMTLIB: CONST not implemented"); 03110 } 03111 break; 03112 03113 case ID: // FIXME: when lisp becomes case-insensitive, fix printing of IDs 03114 if(e.arity() == 1 && e[0].isString()) os << d_translator->escapeSymbol(e[0].getString()); 03115 else e.printAST(os); 03116 break; 03117 03118 case IMPLIES: 03119 os << "(" << push << "=>" << space 03120 << e[0] << space << e[1] << push << ")"; 03121 break; 03122 03123 case IFF: 03124 os << "(" << push << "=" << space 03125 << e[0] << space << e[1] << push << ")"; 03126 break; 03127 03128 case ITE: 03129 os << "(" << push << "ite"; 03130 os << space << e[0] 03131 << space << e[1] << space << e[2] << push << ")"; 03132 break; 03133 03134 // Commands 03135 case ASSERT: 03136 os << "(assert" << space << push << e[0] << ")" << pop; 03137 break; 03138 03139 case QUERY: 03140 if (e[0] != falseExpr() && e[0].negate() != trueExpr()) { 03141 os << push << "(assert" << space << push << e[0].negate() << pop << ")" << pop << endl; 03142 } 03143 os << "(check-sat)"; 03144 break; 03145 03146 case LET: { 03147 // (LET ((var [ type ] val) .... ) body) 03148 Expr var, def; 03149 bool first = true; 03150 int letCount = 0; 03151 ExprHashMap<bool> defs; 03152 for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) { 03153 Type tp(i->arity() == 3 ? (*i)[2].getType() : (*i)[1].getType()); 03154 DebugAssert(!tp.isNull(), "Unexpected Null type"); 03155 var = (*i)[0]; 03156 if(i->arity() == 3) { 03157 def = (*i)[2]; 03158 } 03159 else { 03160 def = (*i)[1]; 03161 } 03162 if (first || contains(def, defs)) { 03163 if (!first) { 03164 os << push << ")" << pop << pop << space; 03165 defs.clear(); 03166 } 03167 os << "(" << push << "let" << space << "(" << push; 03168 ++letCount; 03169 first = false; 03170 } 03171 else { 03172 os << space; 03173 } 03174 defs[def] = true; 03175 os << "(" << push << var << space << nodag << def << ")" << pop; 03176 } 03177 DebugAssert(!first, "Expected at least one child"); 03178 os << push << ")" << pop << pop << space << e[1]; 03179 for (int j = 0; j < letCount; ++j) 03180 os << ")" << pop; 03181 break; 03182 } 03183 case BOUND_VAR: { 03184 string str = e.getName(); 03185 if (str[0] == '_') str[0] = '?'; 03186 os << push << d_translator->escapeSymbol(str); 03187 break; 03188 } 03189 case SKOLEM_VAR: 03190 os << "SKOLEM_" + int2string((int)e.getIndex()); 03191 break; 03192 03193 case WHERE: 03194 case ASSERTIONS: 03195 case ASSUMPTIONS: 03196 os << "(get-assertions)"; 03197 break; 03198 case COUNTEREXAMPLE: 03199 os << "(get-unsat-core)"; 03200 break; 03201 case COUNTERMODEL: 03202 os << "(get-model)"; 03203 break; 03204 case PUSH: 03205 case PUSH_SCOPE: 03206 if(e.arity()==0) 03207 os << "(push 1)"; 03208 else 03209 os << "(push" << space << push << e[0] << ")" << pop; 03210 break; 03211 case POP: 03212 case POP_SCOPE: 03213 if(e.arity()==0) 03214 os << "(pop 1)"; 03215 else 03216 os << "(pop" << space << push << e[0] << ")" << pop; 03217 break; 03218 case POPTO: 03219 os << " :cvc_command" << space 03220 << "\"POPTO" << space << e[0] << push << "\""; break; 03221 case POPTO_SCOPE: 03222 os << " :cvc_command" << space 03223 << "\"POPTO_SCOPE" << space << push << e[0] << "\"" << pop; 03224 break; 03225 case RESET: 03226 os << " :cvc_command" << space; 03227 os << "\"RESET\""; break; 03228 break; 03229 case ANNOTATION: { 03230 os << "(set-info :" << e[0].getString(); 03231 if (e.arity() > 1) 03232 os << space << d_translator->quoteAnnotation(e[1].getString()); 03233 os << ")"; 03234 break; 03235 } 03236 03237 default: // fall-through to shared symbols 03238 printSmtLibShared(os,e); 03239 } 03240 break; 03241 03242 case LISP_LANG: 03243 switch(e.getKind()) { 03244 case TRUE_EXPR: 03245 case FALSE_EXPR: 03246 case UCONST: 03247 e.print(os); break; 03248 case TYPE: 03249 if(e.arity() == 0) os << "TYPE"; 03250 else if(e.arity() == 1) 03251 os << "(" << push << "TYPE" << space << e[0] << push << ")"; 03252 else if(e.arity() == 2) 03253 os << "(" << push << "TYPE" << space << e[0] 03254 << space << e[1] << push << ")"; 03255 else e.printAST(os); 03256 break; 03257 case ID: // FIXME: when lisp becomes case-insensitive, fix printing of IDs 03258 if(e.arity() == 1 && e[0].isString()) os << e[0].getString(); 03259 else e.printAST(os); 03260 break; 03261 case CONST: 03262 if(e.arity() == 2) 03263 os << "(" << push << "CONST" << space << e[0] 03264 << space << e[1] << push << ")"; 03265 else 03266 e.printAST(os); 03267 break; 03268 case SUBTYPE: 03269 os << "SUBTYPE(" << push << e[0] << push << ")"; 03270 break; 03271 case TYPEDEF: { 03272 // This is used when dumping declarations to file. Print just 03273 // the name of the type, unless it's a messed-up expression. 03274 if(e.arity() != 2) e.printAST(os); 03275 else if(e[0].isString()) os << e[0].getString(); 03276 else e[0].print(os); 03277 break; 03278 } 03279 case EQ: 03280 // When a separator starts with a space (like " = "), add the 03281 // leading space with 'space' modifier. If this separator goes 03282 // to the next line, the leading spaces must be eaten up to get 03283 // the indentation right; 'space' will tell the indentation 03284 // engine that it is a space that can be eaten. A space in a 03285 // string (like " ") will never be eaten. 03286 os << "(" << push << "=" << space << e[0] 03287 << space << e[1] << push << ")"; 03288 break; 03289 case NOT: 03290 os << "(" << push << "NOT" << space << e[0] << push << ")"; 03291 break; 03292 case AND: { 03293 int i=0, iend=e.arity(); 03294 os << "(" << push << "AND"; 03295 for(; i!=iend; ++i) os << space << e[i]; 03296 os << push << ")"; 03297 } 03298 break; 03299 case OR: { 03300 int i=0, iend=e.arity(); 03301 os << "(" << push << "OR"; 03302 for(; i!=iend; ++i) os << space << e[i] << space; 03303 os << push << ")"; 03304 } 03305 break; 03306 case ITE: 03307 os << "(" << push << "IF" << space << e[0] 03308 << space << e[1] << space << e[2] << push << ")"; 03309 break; 03310 case IFF: 03311 os << "(" << push << "<=>" << space 03312 << e[0] << space << e[1] << push << ")"; 03313 break; 03314 case IMPLIES: 03315 os << "(" << push << "=>" << space 03316 << e[0] << space << e[1] << push << ")"; 03317 break; 03318 // Commands 03319 case ASSERT: 03320 os << "(" << push << "ASSERT" << space << e[0] << push << ")"; 03321 break; 03322 case TRANSFORM: 03323 os << "(" << push << "TRANSFORM" << space << e[0] << push << ")"; 03324 break; 03325 case QUERY: 03326 os << "(" << push << "QUERY" << space << e[0] << push << ")"; 03327 break; 03328 case PUSH: 03329 os << "(PUSH)"; break; 03330 case POP: 03331 os << "(POP)"; break; 03332 case POPTO: 03333 os << "(" << push << "POPTO" << space << e[0] << push << ")"; break; 03334 case RESET: 03335 os << "(" << push << "RESET" << push << ")"; break; 03336 case LETDECL: 03337 if(e.arity() == 2) os << e[1]; 03338 else if(e.arity()==3) // It's a declaration of a named Expr 03339 os << e[0] << push << ":" << space << push << e[1] << push << " =" 03340 << pop << pop << space << e[2]; 03341 else e.printAST(os); 03342 break; 03343 case LET: { 03344 // (LET ((var [ type ] val) .... ) body) 03345 bool first(true); 03346 os << "(" << push << "LET" << space << "(" << push; 03347 for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) { 03348 if(!first) os << space; 03349 else first = false; 03350 os << "(" << push; 03351 if(i->arity() == 3) { 03352 os << (*i)[0] << space << (*i)[1] 03353 << space << nodag << (*i)[2]; 03354 } else { 03355 os << (*i)[0]; 03356 Type tp((*i)[0].lookupType()); 03357 if(!tp.isNull()) os << space << tp.getExpr(); 03358 os << space << nodag << (*i)[1]; 03359 } 03360 os << push << ")" << pop << pop; 03361 } 03362 os << push << ")" << pop << pop << space << e[1] << push << ")"; 03363 break; 03364 } 03365 case BOUND_VAR: 03366 // os << e.getName()+"_"+e.getUid(); by yeting 03367 os << e.getName(); 03368 break; 03369 case SKOLEM_VAR: 03370 os << "SKOLEM_" + int2string((int)e.getIndex()); 03371 break; 03372 case PF_APPLY: {// FIXME: this will eventually go to the "symsim" theory 03373 DebugAssert(e.arity() > 0, "TheoryCore::print(): " 03374 "Proof rule application must have at " 03375 "least one argument (rule name):\n "+e.toString()); 03376 os << push << "(" << push; 03377 bool first(true); 03378 for(int i=0; i<e.arity(); i++) { 03379 if(first) first=false; 03380 else os << space; 03381 os << e[i]; 03382 } 03383 os << push << ")"; 03384 break; 03385 } 03386 case RAW_LIST: { 03387 os << "(" << push; 03388 bool firstTime(true); 03389 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { 03390 if(firstTime) firstTime = false; 03391 else os << space; 03392 os << *i; 03393 } 03394 os << push << ")"; 03395 break; 03396 } 03397 case ANY_TYPE: 03398 os << "ANY_TYPE"; 03399 break; 03400 case PF_HOLE: // FIXME: implement this (now fall through to default) 03401 default: 03402 // Print the top node in the default LISP format, continue with 03403 // pretty-printing for children. 03404 e.printAST(os); 03405 } 03406 break; // end of case LISP_LANGUAGE 03407 default: 03408 // Print the top node in the default LISP format, continue with 03409 // pretty-printing for children. 03410 e.printAST(os); 03411 } 03412 return os; 03413 } 03414 03415 bool TheoryCore::refineCounterExample(Theorem& thm) 03416 { 03417 // Theory 0 is TheoryCore, skip it 03418 for(int i = 1; i<getNumTheories(); i++) { 03419 if(d_theories[i] != this) 03420 d_theories[i]->refineCounterExample(); 03421 if(inconsistent()) { 03422 thm = inconsistentThm(); 03423 return false; 03424 } 03425 } 03426 return true; 03427 } 03428 03429 void TheoryCore::refineCounterExample() 03430 { 03431 // Theory 0 is TheoryCore, skip it 03432 for(int i = 1; i<getNumTheories(); i++) { 03433 if(d_theories[i] != this) 03434 d_theories[i]->refineCounterExample(); 03435 if(inconsistent()) { 03436 vector<Expr> assump; 03437 inconsistentThm().getLeafAssumptions(assump); 03438 Expr a = Expr(RAW_LIST, assump, d_em); 03439 throw EvalException("Theory["+d_theories[i]->getName() 03440 +"]: Model Creation failed due " 03441 "to the following assumptions:\n\n" 03442 +a.toString() 03443 +"\n\nYou might be using an incomplete logical fragment."); 03444 } 03445 } 03446 } 03447 03448 03449 void TheoryCore::computeModelBasic(const vector<Expr>& v) { 03450 for(vector<Expr>::const_iterator i=v.begin(), iend=v.end(); i!=iend; ++i) { 03451 TRACE("model", "Model var "+i->toString()+" = ", find(*i).getRHS(), ""); 03452 DebugAssert((*i).getType().isBool(), "TheoryCore::computeModel: *i = " 03453 +(*i).toString()); 03454 Expr val = find(*i).getRHS(); 03455 if(!val.isBoolConst()) val = d_em->trueExpr(); 03456 assignValue(*i, val); 03457 } 03458 } 03459 03460 03461 /*****************************************************************************/ 03462 /* 03463 * User-level API methods 03464 */ 03465 /*****************************************************************************/ 03466 03467 03468 void TheoryCore::addFact(const Theorem& e) 03469 { 03470 //<<<<<<< theory_core_sat.cpp 03471 // cout<<"theory_core_sat.cpp asserted fact:"<<e<<endl; 03472 // IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');) 03473 // TRACE("addFact", indentStr, "Assert: ", e.getExpr().toString(PRESENTATION_LANG)); 03474 //======= 03475 IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');) 03476 TRACE("addFact", indentStr, "Assert: ", e.getExpr().toString(PRESENTATION_LANG)); 03477 //>>>>>>> 1.7 03478 DebugAssert(!d_inAddFact, "Recursive call to addFact() is not allowed"); 03479 DebugAssert(d_queue.empty(), "addFact[start]: Expected empty queue"); 03480 // DebugAssert(d_queueSE.empty(), "addFact[start]: Expected empty queue"); 03481 DebugAssert(d_update_thms.empty() && d_update_data.empty(), 03482 "addFact[start]: Expected empty update list"); 03483 ScopeWatcher sw(&d_inAddFact); 03484 03485 if(!d_inconsistent && !outOfResources()) { 03486 getResource(); 03487 d_queue.push(e); 03488 03489 // cout<<"queue pushed" <<e<<endl; 03490 // cout<<"queue pushed id" <<e.getQuantLevel()<<endl; 03491 03492 if (outOfResources()) { 03493 // No more resources: ignore all the remaining facts and fail 03494 // gracefully 03495 setIncomplete("Exhausted user-specified resource"); 03496 } 03497 processFactQueue(); 03498 } 03499 03500 DebugAssert(d_queue.empty(), "addFact[end]: Expected empty queue"); 03501 DebugAssert(d_queueSE.empty(), "addFact[end]: Expected empty queue"); 03502 DebugAssert(d_update_thms.empty() && d_update_data.empty(), 03503 "addFact[end]: Expected empty update list"); 03504 } 03505 03506 03507 bool TheoryCore::checkSATCore() 03508 { 03509 DebugAssert(d_queue.empty(), "checkSATCore[start]: Expected empty queue"); 03510 DebugAssert(d_queueSE.empty(), "checkSATCore[start]: Expected empty queue"); 03511 DebugAssert(!d_inCheckSATCore, "Recursive call to checkSATCore is not allowed!"); 03512 ScopeWatcher sw(&d_inCheckSATCore); 03513 IF_DEBUG(debugger.counter("DP checkSAT(fullEffort) calls")++;) 03514 DebugAssert(d_update_thms.empty() && d_update_data.empty(), 03515 "addFact[start]: Expected empty update list"); 03516 03517 bool lemmas = processFactQueue(FULL); 03518 03519 DebugAssert(d_queue.empty(), "checkSATCore[start]: Expected empty queue"); 03520 DebugAssert(d_queueSE.empty(), "checkSATCore[start]: Expected empty queue"); 03521 DebugAssert(d_update_thms.empty() && d_update_data.empty(), 03522 "addFact[end]: Expected empty update list"); 03523 03524 return !lemmas; 03525 } 03526 03527 03528 bool TheoryCore::incomplete(vector<string>& reasons) 03529 { 03530 if(d_incomplete.size() > 0) { 03531 for(CDMap<string,bool>::iterator i=d_incomplete.begin(), 03532 iend=d_incomplete.end(); i!=iend; ++i) 03533 reasons.push_back((*i).first); 03534 return true; 03535 } 03536 else 03537 return false; 03538 } 03539 03540 03541 void TheoryCore::registerAtom(const Expr& e, const Theorem& thm) 03542 { 03543 DebugAssert(!e.isEq() || e[0] != e[1], "expected non-reflexive"); 03544 DebugAssert(!e.isRegisteredAtom(), "atom registered more than once"); 03545 // if (e.isQuantifier()) return; 03546 e.setRegisteredAtom(); 03547 if(d_termTheorems.find(e) != d_termTheorems.end()){ 03548 // cout<<"found this before 1 : "<<e<<endl; 03549 } 03550 // cout<<"#1# get into "<<e<<endl; 03551 d_termTheorems[e] = thm; 03552 DebugAssert(e.isAbsAtomicFormula(), "Expected atomic formula"); 03553 ScopeWatcher sw(&d_inRegisterAtom); 03554 Theorem thm2 = simplify(e); 03555 if (thm2.getRHS().isTrue()) { 03556 setFindLiteral(d_commonRules->iffTrueElim(thm2)); 03557 } 03558 else if (thm2.getRHS().isFalse()) { 03559 setFindLiteral(d_commonRules->iffFalseElim(thm2)); 03560 } 03561 else { 03562 //TODO: why does arith need thm2.getRHS() instead of e? 03563 // theoryOf(e)->registerAtom(e); 03564 theoryOf(thm2.getRHS())->registerAtom(thm2.getRHS()); 03565 setupSubFormulas(thm2.getRHS(), e, thm); 03566 } 03567 processFactQueue(LOW); 03568 } 03569 03570 03571 Theorem TheoryCore::getImpliedLiteral(void) 03572 { 03573 Theorem res; 03574 if (d_impliedLiteralsIdx < d_impliedLiterals.size()) { 03575 res = d_impliedLiterals[d_impliedLiteralsIdx]; 03576 d_impliedLiteralsIdx = d_impliedLiteralsIdx + 1; 03577 } 03578 return res; 03579 } 03580 03581 03582 Theorem TheoryCore::getImpliedLiteralByIndex(unsigned index) 03583 { 03584 DebugAssert(index < d_impliedLiterals.size(), "index out of bounds"); 03585 return d_impliedLiterals[index]; 03586 } 03587 03588 03589 Expr TheoryCore::parseExpr(const Expr& e) 03590 { 03591 // check cache 03592 ExprMap<Expr>::iterator iParseCache = d_parseCache->find(e); 03593 if (iParseCache != d_parseCache->end()) { 03594 return (*iParseCache).second; 03595 } 03596 // Remember the current size of the bound variable stack 03597 size_t boundVarSize = d_boundVarStack.size(); 03598 03599 // Compute the kind to determine what to do with the expression 03600 int kind = NULL_KIND; 03601 Expr res; 03602 03603 switch(e.getKind()) { 03604 case ID: { 03605 const Expr c1 = e[0]; 03606 kind = getEM()->getKind(c1.getString()); 03607 if(kind == NULL_KIND) { // It's an identifier; try to resolve it 03608 res = resolveID(e[0].getString()); 03609 if(res.isNull()) 03610 throw ParserException("cannot resolve an identifier: " 03611 +e[0].toString()); 03612 else { 03613 DebugAssert(!e.isApply(), "Unexpected apply function"); 03614 } 03615 } 03616 // Otherwise exit the switch and use DP-specific parsing 03617 break; 03618 } 03619 case RAW_LIST: { 03620 if(e.arity() == 0) 03621 throw ParserException("Empty list is not an expression!"); 03622 const Expr& op = e[0]; 03623 // First, resolve the operator 03624 switch(op.getKind()) { 03625 case ID: { // The operator in the list is ID: is it keyword or variable? 03626 kind = getEM()->getKind(op[0].getString()); 03627 if(kind == NULL_KIND) { 03628 // It's a named function application. Resolve the ID. 03629 res = resolveID(op[0].getString()); 03630 if(res.isNull()){ 03631 // cout<<"stop here: " << e << endl; 03632 // cout<<"stop here op: " << op << endl; 03633 // cout<<"stop here op[0]: " << op[0] << endl; 03634 throw ParserException("cannot resolve an identifier: " 03635 +op[0].toString()); 03636 } 03637 if(e.arity() < 2) 03638 throw ParserException("Bad function application: "+e.toString()); 03639 Expr::iterator i=e.begin(), iend=e.end(); 03640 ++i; 03641 vector<Expr> args; 03642 for(; i!=iend; ++i) args.push_back(parseExpr(*i)); 03643 res = Expr(res.mkOp(), args); 03644 } 03645 // Proceed to DP-specific parsing 03646 break; 03647 } 03648 case RAW_LIST: 03649 // This can only be a lambda expression application. 03650 kind = LAMBDA; 03651 break; 03652 case STRING_EXPR: { 03653 vector<Expr> assignmentVars; 03654 if(op.getString() == "_ANNOTATION") { 03655 for(int i = 0; i < e[2].arity(); ++i) { 03656 if(e[2][i][0][0].getString() == ":named") { 03657 FatalAssert(e[2][i].arity() == 2 && e[2][i][1].getKind() == ID, 03658 ":named annotation must take a name"); 03659 assignmentVars.push_back(e[2][i][1]); 03660 } 03661 } 03662 Expr parsed = parseExpr(e[1]); 03663 for(unsigned i = 0; i < assignmentVars.size(); ++i) { 03664 d_assignment.push_back(make_pair(assignmentVars[i], parsed)); 03665 } 03666 // Return rather than break; nothing more to do with the 03667 // annotation expr itself; it is stripped away. 03668 return parsed; 03669 } 03670 /* else fall through... */ 03671 } 03672 default: 03673 throw ParserException("Bad operator in "+e.toString()); 03674 } 03675 break; // Exit the top-level switch, proceed to DP-specific parsing 03676 } 03677 default: // Can only be a string or a number. 03678 res = e; 03679 } 03680 03681 // DP-specific parsing 03682 if(res.isNull()) { 03683 if (hasTheory(kind)) { 03684 res = theoryOf(kind)->parseExprOp(e); 03685 // Restore the bound variable stack 03686 if (d_boundVarStack.size() > boundVarSize) { 03687 d_parseCache->clear(); 03688 if (boundVarSize == 0) { 03689 d_parseCache = &d_parseCacheTop; 03690 } 03691 while(d_boundVarStack.size() > boundVarSize) { 03692 pair<string,Expr>& bv = d_boundVarStack.back(); 03693 hash_map<string,Expr>::iterator iBoundVarMap = d_boundVarMap.find(bv.first); 03694 DebugAssert(iBoundVarMap != d_boundVarMap.end(), "Expected bv in map"); 03695 if ((*iBoundVarMap).second.getKind() == RAW_LIST) { 03696 (*iBoundVarMap).second = (*iBoundVarMap).second[1]; 03697 } 03698 else d_boundVarMap.erase(bv.first); 03699 d_boundVarStack.pop_back(); 03700 } 03701 } 03702 } 03703 else { 03704 res = e; 03705 } 03706 } 03707 (*d_parseCache)[e] = res; 03708 if (!getEM()->isTypeKind(res.getOpKind())) res.getType(); 03709 return res; 03710 } 03711 03712 03713 void TheoryCore::assignValue(const Expr& t, const Expr& val) 03714 { 03715 DebugAssert(d_varAssignments.count(t) == 0 03716 || d_varAssignments[t].getRHS() == val, 03717 "TheoryCore::assignValue("+t.toString()+" := "+val.toString() 03718 +")\n variable already has a different value"); 03719 // Check if the assignment theorem can be derived from the find of t 03720 Theorem thm(find(t)); 03721 Expr t2 = thm.getRHS(); 03722 03723 if(t2!=val) { 03724 bool isBool(t2.getType().isBool()); 03725 Expr assump = (isBool)? t2.iffExpr(val) : t2.eqExpr(val); 03726 Theorem assertThm = d_coreSatAPI->addAssumption(assump); 03727 addFact(assertThm); 03728 thm = transitivityRule(thm, assertThm); 03729 } 03730 d_varAssignments[t] = thm; 03731 } 03732 03733 03734 void TheoryCore::assignValue(const Theorem& thm) 03735 { 03736 DebugAssert(thm.isRewrite(), "TheoryCore::assignValue("+thm.toString()+")"); 03737 const Expr& t = thm.getLHS(); 03738 const Expr& val = thm.getRHS(); 03739 DebugAssert(d_varAssignments.count(t) == 0 03740 || d_varAssignments[t].getRHS() == val, 03741 "TheoryCore::assignValue("+thm.getExpr().toString() 03742 +")\n variable already has a different value:\n " 03743 +d_varAssignments[t].getExpr().toString()); 03744 d_varAssignments[t] = thm; 03745 // Check if the assignment theorem can be derived from the find of t 03746 Theorem findThm(find(t)); 03747 const Expr& t2 = findThm.getRHS(); 03748 03749 if(t2!=val) { 03750 Theorem thm2 = transitivityRule(symmetryRule(findThm), thm); 03751 addFact(thm2); 03752 } 03753 } 03754 03755 03756 void TheoryCore::addToVarDB(const Expr& e) 03757 { 03758 TRACE("model", "TheoryCore::addToVarDB(", e, ")"); 03759 d_vars.push_back(e); 03760 } 03761 03762 03763 void TheoryCore::collectBasicVars() 03764 { 03765 TRACE_MSG("model", "collectBasicVars() {"); 03766 // Clear caches 03767 d_varModelMap.clear(); 03768 d_varAssignments.clear(); 03769 d_basicModelVars.clear(); 03770 d_simplifiedModelVars.clear(); 03771 // Current stack of variables to process 03772 vector<Expr> stack(d_vars.begin(), d_vars.end()); 03773 size_t lastSize(0); 03774 while(stack.size() > 0) { 03775 Expr var(stack.back()); 03776 stack.pop_back(); 03777 if(d_varModelMap.count(var) > 0) continue; // Already processed 03778 Theorem findThm(find(var)); 03779 if(findThm.getRHS()!=var) { // Replace var with its find 03780 d_simplifiedModelVars[var] = findThm; 03781 stack.push_back(findThm.getRHS()); 03782 TRACE("model", "collectBasicVars: simplified var: ", findThm.getExpr(), ""); 03783 continue; // Recycle to the beginning of the loop 03784 } 03785 lastSize = stack.size(); 03786 TRACE("model", "getModelTerm(", var, ") {"); 03787 getModelTerm(var, stack); 03788 TRACE("model", "getModelTerm => ", 03789 Expr(RAW_LIST, stack, getEM()), " }"); 03790 if(stack.size() == lastSize) { 03791 // Add a primitive variable 03792 TRACE("model", "collectBasicVars: adding primitive var: ", var, ""); 03793 d_basicModelVars.push_back(var); 03794 if(var.isTerm()) { 03795 Theory* t1 = theoryOf(var); 03796 Theory* t2 = theoryOf(getBaseType(var).getExpr().getKind()); 03797 if(t1 != t2) { 03798 TRACE("model", "collectBasicVars: adding shared var: ", var, ""); 03799 t1->addSharedTerm(var); 03800 t2->addSharedTerm(var); 03801 } 03802 } 03803 } else { // Record the descendants of var 03804 vector<Expr>& kids = d_varModelMap[var]; 03805 for(size_t i=lastSize; i<stack.size(); ++i) { 03806 DebugAssert(stack[i] != var, "Primitive var was pushed on " 03807 "the stack in computeModelTerm(): "+var.toString()); 03808 kids.push_back(stack[i]); 03809 } 03810 TRACE("model", "collectBasicVars: var="+var.toString() 03811 +" maps into vars=", Expr(RAW_LIST, kids, getEM()), ""); 03812 } 03813 } 03814 TRACE_MSG("model", "collectBasicVars() => }"); 03815 } 03816 03817 bool TheoryCore::buildModel(Theorem& thm) 03818 { 03819 size_t numTheories = getNumTheories(); 03820 // Use STL set to prune duplicate variables in theories 03821 vector<set<Expr> > theoryExprs(numTheories+1); 03822 03823 // Sort out model vars by theories 03824 for(size_t j = 0 ; j<d_basicModelVars.size() ; j++) { 03825 const Expr& var = d_basicModelVars[j]; 03826 Theorem findThm(find(var)); 03827 if(findThm.getRHS()!=var) { // Replace var with its find and skip it 03828 TRACE("model", "buildModel: replace var="+var.toString(), " with find(var)=", findThm.getRHS()); 03829 d_simplifiedModelVars[var] = findThm; 03830 continue; 03831 } 03832 03833 Theory *th = theoryOf(getBaseType(var).getExpr().getKind()); 03834 size_t i=0; 03835 for(; i<numTheories && d_theories[i] != th; ++i); 03836 DebugAssert(i<numTheories && d_theories[i] == th, "TheoryCore::buildModel: cannot find the theory [" +th->getName()+"] for the variable: " +var.toString()); 03837 theoryExprs[i].insert(var); 03838 TRACE("model", "buildModel: adding ", var, " to theory "+d_theories[i]->getName()); 03839 } 03840 03841 // Build a model for the basic-type variables 03842 for(int i=0; i<getNumTheories(); i++) { 03843 if(theoryExprs[i].size() > 0) { 03844 TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] {"); 03845 // Copy the corresponding variables into a vector 03846 vector<Expr> vars; 03847 vars.insert(vars.end(), theoryExprs[i].begin(), theoryExprs[i].end()); 03848 d_theories[i]->computeModelBasic(vars); 03849 TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] => }"); 03850 if(inconsistent()) { 03851 vector<Expr> assump; 03852 thm = inconsistentThm(); 03853 return false; 03854 } 03855 } 03856 } 03857 03858 return true; 03859 } 03860 03861 03862 void TheoryCore::buildModel(ExprMap<Expr>& m) 03863 { 03864 TRACE_MSG("model", "buildModel() {"); 03865 03866 size_t numTheories = getNumTheories(); 03867 // Use STL set to prune duplicate variables in theories 03868 vector<set<Expr> > theoryExprs(numTheories+1); 03869 // Sort out model vars by theories 03870 for(size_t j = 0 ; j<d_basicModelVars.size() ; j++) { 03871 const Expr& var = d_basicModelVars[j]; 03872 Theorem findThm(find(var)); 03873 if(findThm.getRHS()!=var) { // Replace var with its find and skip it 03874 TRACE("model", "buildModel: replace var="+var.toString(), 03875 " with find(var)=", findThm.getRHS()); 03876 d_simplifiedModelVars[var] = findThm; 03877 continue; 03878 } 03879 03880 Theory *th = theoryOf(getBaseType(var).getExpr().getKind()); 03881 size_t i=0; 03882 for(; i<numTheories && d_theories[i] != th; ++i); 03883 DebugAssert(i<numTheories && d_theories[i] == th, 03884 "TheoryCore::buildModel: cannot find the theory [" 03885 +th->getName()+"] for the variable: " 03886 +var.toString()); 03887 theoryExprs[i].insert(var); 03888 TRACE("model", "buildModel: adding ", var, 03889 " to theory "+d_theories[i]->getName()); 03890 } 03891 // Build a model for the basic-type variables 03892 for(int i=0; i<getNumTheories(); i++) { 03893 if(theoryExprs[i].size() > 0) { 03894 TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] {"); 03895 // Copy the corresponding variables into a vector 03896 vector<Expr> vars; 03897 vars.insert(vars.end(), theoryExprs[i].begin(), theoryExprs[i].end()); 03898 d_theories[i]->computeModelBasic(vars); 03899 TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] => }"); 03900 if(inconsistent()) { 03901 vector<Expr> assump; 03902 inconsistentThm().getLeafAssumptions(assump); 03903 Expr a = Expr(RAW_LIST, assump, d_em); 03904 throw EvalException 03905 ("Model Creation failed in Theory[" 03906 +d_theories[i]->getName() 03907 +"] due to the following assumptions:\n\n" 03908 +a.toString() 03909 +"\n\nYou might be using an incomplete logical fragment."); 03910 } 03911 } 03912 } 03913 // Recombine the values for the compound-type variables 03914 ExprHashMap<Theorem>::iterator k, kend=d_simplifiedModelVars.end(); 03915 for(vector<Expr>::const_iterator i=d_vars.begin(), iend=d_vars.end(); i!=iend; ++i) { 03916 Expr var(*i); 03917 TRACE("model", "buildModel: recombining var=", var, ""); 03918 k=d_simplifiedModelVars.find(var); 03919 Theorem simp; // Null by default 03920 if(k!=kend) { // This var is simplified 03921 simp = k->second; 03922 TRACE("model", "buildModel: simplified var="+var.toString()+" to ", 03923 simp.getRHS(), ""); 03924 var = simp.getRHS(); 03925 } 03926 collectModelValues(var, m); 03927 if(d_varAssignments.count(var) > 0) { 03928 if(!simp.isNull()) { 03929 Theorem thm(transitivityRule(simp, d_varAssignments[var])); 03930 assignValue(thm); 03931 DebugAssert(thm.getLHS() == *i, ""); 03932 m[*i] = thm.getRHS(); 03933 } else 03934 m[*i] = d_varAssignments[var].getRHS(); 03935 } 03936 // else if(simp.isNull()) 03937 // m[*i] = *i; 03938 // else 03939 // m[*i] = simp.getRHS(); 03940 } 03941 TRACE_MSG("model", "buildModel => }"); 03942 } 03943 03944 03945 // Recursively build a compound-type variable assignment for e 03946 /*! Not all theories may implement aggregation of compound values. If 03947 * a compound variable is not assigned by a theory, add the more 03948 * primitive variable assignments to 'm'. 03949 * 03950 * Some variables may simplify to something else (simplifiedVars map). 03951 * INVARIANT: e is always simplified (it's not in simplifiedVars map). 03952 * Also, if v simplifies to e, and e is assigned, then v must be assigned. 03953 */ 03954 void TheoryCore::collectModelValues(const Expr& e, ExprMap<Expr>& m) 03955 { 03956 TRACE("model", "collectModelValues(", e, ") {"); 03957 if(d_varAssignments.count(e) > 0) { 03958 TRACE("model", "collectModelValues[cached] => ", 03959 d_varAssignments[e].getRHS(), " }"); 03960 return; // Got it already 03961 } 03962 ExprHashMap<Theorem>::iterator k, kend=d_simplifiedModelVars.end(); 03963 k=d_simplifiedModelVars.find(e); 03964 if(k!=kend) { 03965 const Theorem& findThm = k->second; 03966 const Expr& ee = findThm.getRHS(); 03967 collectModelValues(ee, m); 03968 if(d_varAssignments.count(ee) > 0) { 03969 Theorem thm = transitivityRule(findThm, d_varAssignments[ee]); 03970 assignValue(thm); 03971 } 03972 TRACE("model", "collectModelValues[simplified] => ", 03973 d_varAssignments[e].getRHS(), " }"); 03974 return; 03975 } 03976 if(d_varModelMap.count(e) == 0) { // Consider it a value of itself 03977 assignValue(reflexivityRule(e)); 03978 TRACE("model", "collectModelValues[e=e] => ", e, " }"); 03979 return; // Got it already 03980 } 03981 // Get the vector of more primitive vars 03982 const vector<Expr>& vars = d_varModelMap[e]; 03983 // Recurse 03984 bool gotAll(true); // Whether we got all the values 03985 for(vector<Expr>::const_iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) { 03986 Expr var(*i); 03987 // k=d_simplifiedModelVars.find(var); 03988 // Theorem simp; // Null by default 03989 // if(k!=kend) { // This var is simplified 03990 // simp = k->second; 03991 // var = simp.getRHS(); 03992 // } 03993 collectModelValues(var, m); 03994 if(d_varAssignments.count(var) == 0) { 03995 gotAll = false; 03996 } 03997 // else if(!simp.isNull()) { 03998 // Theorem thm(transitivityRule(simp, d_varAssignments[var])); 03999 // DebugAssert(thm.getLHS() == *i, ""); 04000 // assignValue(thm); 04001 // } 04002 } 04003 IF_DEBUG(vector<Expr> res;) 04004 if(gotAll) { 04005 vector<Expr> assigned; // What DP actually assigns 04006 Theory* th = theoryOf(getBaseType(e).getExpr()); 04007 TRACE("model", "computeModel["+th->getName()+"](", e, ") {"); 04008 th->computeModel(e, assigned); 04009 TRACE("model", "computeModel["+th->getName()+"] => ", 04010 Expr(RAW_LIST, assigned, getEM()), " }"); 04011 // Check if the assigned vars are different from e 04012 if(!(assigned.size()==1 && assigned[0]==e)) { 04013 // if(d_varAssignments.count(e) == 0) { 04014 for(vector<Expr>::iterator i=assigned.begin(), iend=assigned.end(); 04015 i!=iend; ++i) { 04016 if(*i == e) continue; // Skip the original var 04017 m[*i] = getModelValue(*i).getRHS(); 04018 IF_DEBUG(res.push_back(getModelValue(*i).getExpr());) 04019 } 04020 } else { 04021 IF_DEBUG(res.push_back(getModelValue(e).getExpr());) 04022 } 04023 } 04024 TRACE("model", "collectModelValues => ", 04025 Expr(RAW_LIST, res, getEM()), " }"); 04026 } 04027 04028 04029 Theorem TheoryCore::rewriteLiteral(const Expr& e) { 04030 DebugAssert(e.isAbsLiteral(), "rewriteLiteral("+e.toString() 04031 +")\nExpected a literal."); 04032 Theorem res; 04033 //Theory* i = theoryOf(getBaseType(e).getExpr()); 04034 bool neg(e.isNot()); 04035 const Expr a = neg? e[0] : e; 04036 Theory * i; 04037 if(a.isEq()) 04038 i = theoryOf(getBaseType(a[0]).getExpr()); 04039 else if (a.arity() > 1) 04040 i = theoryOf(getBaseType(a[0]).getExpr()); 04041 else 04042 i = theoryOf(a); 04043 res = i->rewriteAtomic(a); 04044 if(neg) res = d_commonRules->iffContrapositive(res); 04045 return res; 04046 } 04047 04048 04049 04050 04051 04052 04053 void TheoryCore::setTimeLimit(unsigned limit) { 04054 initTimeLimit(); 04055 d_timeLimit = limit; 04056 } 04057 04058 void TheoryCore::initTimeLimit() { 04059 d_timeBase = clock() / (CLOCKS_PER_SEC / 10); 04060 } 04061 04062 bool TheoryCore::timeLimitReached() { 04063 if (d_timeLimit > 0 04064 && d_timeLimit < (unsigned)(clock() / (CLOCKS_PER_SEC / 10)) - d_timeBase) { 04065 setIncomplete("Exhausted user-specified time limit"); 04066 return true; 04067 } else { 04068 return false; 04069 } 04070 } 04071 04072 04073 04074 /*****************************************************************************/ 04075 /* 04076 * Methods provided for benefit of theories 04077 */ 04078 /*****************************************************************************/ 04079 04080 04081 /*! 04082 * Invariants: 04083 * - The input theorem e is either an equality or a conjunction of 04084 * equalities; 04085 * - In each equality e1=e2, the RHS e2 i-leaf-simplified; 04086 * - At the time of calling update(), all equalities in the queue are 04087 * processed by assertFormula() and the equivalence classes are merged 04088 * in the union-find database. 04089 * 04090 * In other words, the entire equality queue is processed "in parallel". 04091 */ 04092 04093 void TheoryCore::assertEqualities(const Theorem& e) 04094 { 04095 IF_DEBUG( 04096 string indentStr(getCM()->scopeLevel(), ' '); 04097 TRACE("facts", indentStr, "assertEqualities: ", e); 04098 if (!incomplete()) d_solver->checkAssertEqInvariant(e); 04099 ) 04100 TRACE("quant update", "equs in core ", e.getExpr(), ""); 04101 04102 // fast case 04103 if (e.isRewrite()) { 04104 const Expr& lhs = e.getLHS(); 04105 const Expr& rhs = e.getRHS(); 04106 DebugAssert(lhs.isTerm(), "term expected"); 04107 DebugAssert(findReduced(lhs) && 04108 findReduced(rhs), "should be find-reduced"); 04109 DebugAssert(lhs != rhs, "expected different lhs and rhs"); 04110 assertFormula(e); 04111 lhs.setFind(e); 04112 Theorem tmp = lhs.getEqNext(); 04113 lhs.setEqNext(transitivityRule(e, rhs.getEqNext())); 04114 rhs.setEqNext(transitivityRule(symmetryRule(e), tmp)); 04115 d_em->invalidateSimpCache(); 04116 NotifyList *L; 04117 L = lhs.getNotify(); 04118 if (L) processNotify(e, L); 04119 processNotify(e, &d_notifyEq); 04120 } 04121 else if (e.getExpr().isFalse()) { 04122 setInconsistent(e); 04123 } 04124 else { 04125 Expr conj = e.getExpr(); 04126 DebugAssert(conj.isAnd(), "Expected conjunction"); 04127 vector<Theorem> eqs; 04128 Theorem t; 04129 int index; 04130 04131 for (index = 0; index < conj.arity(); ++index) { 04132 t = d_commonRules->andElim(e, index); 04133 eqs.push_back(t); 04134 if (t.getExpr().isFalse()) { 04135 setInconsistent(t); 04136 return; 04137 } 04138 DebugAssert(t.isRewrite(), "Expected rewrite"); 04139 DebugAssert(t.getLHS().isTerm(), "term expected"); 04140 DebugAssert(findReduced(t.getLHS()) && 04141 findReduced(t.getRHS()), "should be find-reduced"); 04142 assertFormula(t); 04143 if (d_inconsistent) return; 04144 } 04145 04146 // Merge the equivalence classes 04147 vector<Theorem>::iterator i = eqs.begin(), iend = eqs.end(); 04148 for(; i!=iend; ++i) { 04149 const Theorem& thm = *i; 04150 const Expr& lhs = thm.getLHS(); 04151 const Expr& rhs = thm.getRHS(); 04152 DebugAssert(find(lhs).getRHS() == lhs, 04153 "find error: thm = "+thm.getExpr().toString() 04154 +"\n\n find(lhs) = " 04155 +find(lhs).getRHS().toString()); 04156 DebugAssert(find(rhs).getRHS() == rhs, 04157 "find error: thm = "+thm.getExpr().toString() 04158 +"\n\n find(rhs) = " 04159 +find(rhs).getRHS().toString()); 04160 lhs.setFind(thm); 04161 Theorem tmp = lhs.getEqNext(); 04162 lhs.setEqNext(transitivityRule(thm, rhs.getEqNext())); 04163 rhs.setEqNext(transitivityRule(symmetryRule(thm), tmp)); 04164 } 04165 04166 d_em->invalidateSimpCache(); 04167 04168 // Call the update() functions (process NotifyLists). 04169 04170 for(i=eqs.begin(); i!=iend && !d_inconsistent; ++i) { 04171 const Theorem& thm = *i; 04172 NotifyList *L = thm.getLHS().getNotify(); 04173 if (L) processNotify(thm, L); 04174 processNotify(thm, &d_notifyEq); 04175 } 04176 } 04177 } 04178 04179 04180 void TheoryCore::setIncomplete(const string& reason) 04181 { 04182 d_incomplete.insert(reason, true); 04183 } 04184 04185 04186 Theorem TheoryCore::typePred(const Expr& e) 04187 { 04188 return d_rules->typePred(e); 04189 } 04190 04191 04192 static bool hasBoundVarRec(const Expr& e) 04193 { 04194 if (e.getFlag()) return false; 04195 if (e.isQuantifier()) return false; 04196 if (e.getKind() == BOUND_VAR) return true; 04197 for (int i = 0, ar = e.arity(); i < ar; ++i) { 04198 if (hasBoundVarRec(e[i])) return true; 04199 } 04200 e.setFlag(); 04201 return false; 04202 } 04203 04204 IF_DEBUG( 04205 static bool hasBoundVar(const Expr& e) 04206 { 04207 e.getEM()->clearFlags(); 04208 return hasBoundVarRec(e); 04209 } 04210 ) 04211 04212 04213 void TheoryCore::enqueueFact(const Theorem& e) 04214 { 04215 // The theorem scope shouldn't be higher than current 04216 DebugAssert(e.getScope() <= d_cm->scopeLevel(), 04217 "\n e.getScope()="+int2string(e.getScope()) 04218 +"\n scopeLevel="+int2string(d_cm->scopeLevel()) 04219 +"\n e = "+e.getExpr().toString()); 04220 DebugAssert(okToEnqueue(), 04221 "enqueueFact() is called outside of addFact()" 04222 " or checkSATCore() or registerAtom() or preprocess"); 04223 DebugAssert((e.isRewrite() && !hasBoundVar(e.getLHS()) 04224 && !hasBoundVar(e.getRHS())) || 04225 (!e.isRewrite() && !hasBoundVar(e.getExpr())), 04226 "Bound vars shouldn't be free: " + e.toString()); 04227 04228 // No need to enqueue when already inconsistent or out of resources 04229 if (d_inconsistent || outOfResources()) return; 04230 04231 if (!e.isRewrite() && e.getExpr().isFalse()) { 04232 setInconsistent(e); 04233 } else { 04234 getResource(); 04235 d_queue.push(e); 04236 if (outOfResources()) { 04237 // No more resources: ignore all the remaining facts and fail 04238 // gracefully 04239 setIncomplete("Exhausted user-specified resource"); 04240 } 04241 } 04242 } 04243 04244 04245 void TheoryCore::setInconsistent(const Theorem& e) 04246 { 04247 DebugAssert(e.getExpr() == falseExpr(), "Expected proof of false"); 04248 d_inconsistent = true; d_incThm = e; 04249 // if(!d_queueSE.empty()){ 04250 // cout<<"before SAT 1"<<endl; 04251 // } 04252 d_queueSE.clear(); 04253 // Theory 0 is TheoryCore, skip it 04254 for(unsigned i=1; i < d_theories.size(); ++i) { 04255 d_theories[i]->notifyInconsistent(e); 04256 } 04257 } 04258 04259 04260 void TheoryCore::setupTerm(const Expr& t, Theory* i, const Theorem& thm) 04261 { 04262 int k; 04263 // Atomic formulas (non-terms) may have find pointers without the 04264 // subterms being setup. Recurse down to the terms before checking 04265 // for find pointers. 04266 if (!t.isTerm()) { 04267 if (!t.isStoredPredicate()) { 04268 DebugAssert(t.isAbsLiteral(), "Expected absliteral"); 04269 for (k = 0; k < t.arity(); ++k) { 04270 setupTerm(t[k], i, thm); 04271 } 04272 t.setStoredPredicate(); 04273 d_predicates.push_back(t); 04274 d_termTheorems[t] = thm; 04275 theoryOf(t)->setup(t); 04276 TRACE("quantlevel", "==========\npushed pred | ", t.getIndex(), "|" + t.toString()+"because : "+thm.toString() ); 04277 TRACE("quant","pushed pred ",t,thm); 04278 } 04279 return; 04280 } 04281 04282 // Even if t is already setup, it may become shared with another theory 04283 Theory* j = theoryOf(t); 04284 if(i != j) { 04285 j->addSharedTerm(t); 04286 i->addSharedTerm(t); 04287 } 04288 04289 // If already setup, nothing else to do 04290 if (t.hasFind()) return; 04291 04292 // Proceed with the setup 04293 04294 // Add the term into the set of all terms 04295 d_terms.push_back(t); 04296 d_termTheorems[t] = thm; 04297 TRACE("quantlevel","=========\npushed term ("+t.toString(), ") with quantlevel: ", thm.getQuantLevel()); 04298 04299 for (k = 0; k < t.arity(); ++k) { 04300 setupTerm(t[k], j, thm); 04301 } 04302 t.setFind(reflexivityRule(t)); 04303 t.setEqNext(reflexivityRule(t)); 04304 j->setup(t); 04305 04306 // Assert the subtyping predicate AFTER the setup is complete 04307 Theorem pred = d_rules->typePred(t); 04308 pred = iffMP(pred, simplify(pred.getExpr())); 04309 const Expr& predExpr = pred.getExpr(); 04310 if(predExpr.isFalse()) { 04311 IF_DEBUG(debugger.counter("conflicts from type predicate")++;) 04312 setInconsistent(pred); 04313 } 04314 else if(!predExpr.isTrue()) { 04315 Theory* k = theoryOf(t.getType().getExpr()); 04316 k->assertTypePred(t, pred); 04317 } 04318 } 04319 04320 Expr TheoryCore::getAssignment() { 04321 vector<Expr> v; 04322 for(unsigned i = 0; i < d_assignment.size(); ++i) { 04323 Theorem res = d_exprTrans->preprocess(d_assignment[i].second); 04324 Theorem simpThm = d_theoryCore->simplify(res.getRHS()); 04325 vector<Expr> pr; 04326 pr.push_back(d_assignment[i].first); 04327 pr.push_back(simpThm.getRHS()); 04328 v.push_back(Expr(RAW_LIST, pr, getEM())); 04329 } 04330 return Expr(RAW_LIST, v, getEM()); 04331 } 04332 04333 Expr TheoryCore::getValue(Expr e) { 04334 Theorem res = d_exprTrans->preprocess(e); 04335 Theorem simpThm = d_theoryCore->simplify(res.getRHS()); 04336 return simpThm.getRHS(); 04337 } 04338