00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "theory_core.h"
00031 #include "common_proof_rules.h"
00032 #include "typecheck_exception.h"
00033 #include "theorem_manager.h"
00034
00035
00036 using namespace CVCL;
00037 using namespace std;
00038
00039
00040 Theory::Theory(void) : d_theoryCore(NULL) { }
00041
00042
00043 Theory::Theory(TheoryCore* theoryCore, const string& name)
00044 : d_em(theoryCore->getEM()),
00045 d_theoryCore(theoryCore),
00046 d_commonRules(theoryCore->getTM()->getRules()),
00047 d_name(name), d_theoryUsed(false) {
00048 }
00049
00050
00051 Theory::~Theory(void) { }
00052
00053
00054 void Theory::computeModelTerm(const Expr& e, vector<Expr>& v) {
00055 TRACE("model", "Theory::computeModelTerm(", e, "): is a variable");
00056
00057 }
00058
00059
00060 Theorem Theory::simplifyOp(const Expr& e) {
00061 int ar = e.arity();
00062 if (ar > 0) {
00063 vector<Theorem> newChildrenThm;
00064 vector<unsigned> changed;
00065 for(int k = 0; k < ar; ++k) {
00066
00067 Theorem thm = simplifyRec(e[k]);
00068 if (thm.getLHS() != thm.getRHS()) {
00069 newChildrenThm.push_back(thm);
00070 changed.push_back(k);
00071 }
00072 }
00073 if(changed.size() > 0)
00074 return d_commonRules->substitutivityRule(e, changed, newChildrenThm);
00075 }
00076 return reflexivityRule(e);
00077 }
00078
00079
00080 Expr Theory::computeTCC(const Expr& e) {
00081 vector<Expr> kids;
00082 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
00083 kids.push_back(getTCC(*i));
00084 return (kids.size()>0) ?
00085 d_commonRules->rewriteAnd(andExpr(kids)).getRHS() : trueExpr();
00086 }
00087
00088
00089 bool Theory::inconsistent()
00090 {
00091 return d_theoryCore->inconsistent();
00092 }
00093
00094
00095 void Theory::setInconsistent(const Theorem& e)
00096 {
00097 TRACE("facts assertFact", ("setInconsistent[" + getName() + "->]("), e, ")");
00098 TRACE("conflict", ("setInconsistent[" + getName() + "->]("), e, ")");
00099 IF_DEBUG(debugger.counter("conflicts from DPs")++);
00100 d_theoryCore->setInconsistent(e);
00101 }
00102
00103
00104 void Theory::setIncomplete(const string& reason)
00105 {
00106 TRACE("facts assertFact", "setIncomplete["+getName()+"](", reason, ")");
00107 d_theoryCore->setIncomplete(reason);
00108 }
00109
00110
00111 Theorem Theory::simplify(const Expr& e, bool forceRebuild)
00112 {
00113 TRACE("simplify", ("simplify[" + getName() + "->]("), e, ") {");
00114 Theorem res(d_theoryCore->simplify(e, forceRebuild));
00115 TRACE("simplify", "simplify[" + getName() + "] => ", res, "}");
00116 return res;
00117 }
00118
00119
00120 Theorem Theory::simplifyRec(const Expr& e)
00121 {
00122 TRACE("simplifyRec", ("simplifyRec[" + getName() + "->]("), e, ") {");
00123 Theorem res(d_theoryCore->simplifyRec(e));
00124 TRACE("simplifyRec", "simplifyRec[" + getName() + "] => ", res, "}");
00125 return res;
00126 }
00127
00128
00129 void Theory::enqueueFact(const Theorem& e)
00130 {
00131 TRACE("facts assertFact", ("enqueueFact[" + getName() + "->]("), e, ")");
00132 d_theoryCore->enqueueFact(e);
00133 }
00134
00135
00136 void Theory::enqueueEquality(const Theorem& e)
00137 {
00138 TRACE("facts assertFact", ("enqueueEquality[" + getName() + "->]("), e, ")");
00139 DebugAssert(e.isRewrite(), "Theory::enqueueEquality("+e.toString()+")");
00140
00141
00142 d_theoryCore->enqueueEquality(e);
00143 }
00144
00145
00146 void Theory::assertEqualities(const Theorem& e)
00147 {
00148 d_theoryCore->assertEqualities(e);
00149 }
00150
00151
00152 void Theory::addSplitter(const Expr& e, int priority) {
00153 TRACE("facts assertFact", "addSplitter[" + getName() + "->](", e,
00154 ", pri="+int2string(priority)+")");
00155 d_theoryCore->d_coreSatAPI->addSplitter(e, priority);
00156 }
00157
00158
00159 void Theory::assignValue(const Expr& t, const Expr& val) {
00160 TRACE("facts assertFact", "assignValue["+getName()+"](", t, ", "+
00161 val.toString()+") {");
00162 d_theoryCore->assignValue(t, val);
00163 TRACE("facts assertFact", "assignValue[", getName(), "] => }");
00164 }
00165
00166
00167 void Theory::assignValue(const Theorem& thm) {
00168 TRACE("facts assertFact", "assignValue["+getName()+"](", thm, ") {");
00169 d_theoryCore->assignValue(thm);
00170 TRACE("facts assertFact", "assignValue[", getName(), "] => }");
00171 }
00172
00173
00174 void Theory::registerKinds(Theory* theory, vector<int>& kinds)
00175 {
00176 vector<int>::const_iterator k;
00177 vector<int>::const_iterator kEnd;
00178 for (k = kinds.begin(), kEnd = kinds.end(); k != kEnd; ++k) {
00179 DebugAssert(d_theoryCore->d_theoryMap.count(*k) == 0,
00180 "kind already registered: "+getEM()->getKindName(*k)
00181 +" = "+int2string(*k));
00182 d_theoryCore->d_theoryMap[*k] = theory;
00183 }
00184 }
00185
00186
00187 void Theory::registerTheory(Theory* theory, vector<int>& kinds,
00188 bool hasSolver)
00189 {
00190 registerKinds(theory, kinds);
00191 d_theoryCore->d_theories.push_back(theory);
00192 if (hasSolver) {
00193 DebugAssert(!d_theoryCore->d_solver,"Solver already registered");
00194 d_theoryCore->d_solver = theory;
00195 }
00196 }
00197
00198
00199 int Theory::getNumTheories()
00200 {
00201 return d_theoryCore->d_theories.size();
00202 }
00203
00204
00205 bool Theory::hasTheory(int kind) {
00206 return (d_theoryCore->d_theoryMap.count(kind) > 0);
00207 }
00208
00209
00210 Theory* Theory::theoryOf(int kind)
00211 {
00212 DebugAssert(d_theoryCore->d_theoryMap.count(kind) > 0,
00213 "Unknown operator: " + getEM()->getKindName(kind));
00214 return d_theoryCore->d_theoryMap[kind];
00215 }
00216
00217
00218 Theory* Theory::theoryOf(const Expr& e)
00219 {
00220 if (e.isNot() || e.isEq()) {
00221 return theoryOf(e[0]);
00222 }
00223 if (e.isApply()) {
00224 return theoryOf(e.getOpKind());
00225 }
00226 if (!e.isVar()) {
00227 return theoryOf(e.getKind());
00228 }
00229
00230
00231
00232 const Expr& typeExpr = getBaseType(e).getExpr();
00233 DebugAssert(!typeExpr.isNull(),"Null type");
00234 int kind = typeExpr.getKind();
00235 if (typeExpr.isApply()) kind = typeExpr.getOpKind();
00236 DebugAssert(d_theoryCore->d_theoryMap.count(kind) > 0,
00237 "Unknown operator: " + getEM()->getKindName(kind));
00238 return d_theoryCore->d_theoryMap[kind];
00239 }
00240
00241
00242 Theorem Theory::find(const Expr& e)
00243 {
00244 Theorem thm1 = e.hasFind() ? e.getFind() : reflexivityRule(e);
00245 const Expr& e1 = thm1.getRHS();
00246 if (e1 == e || !e1.hasFind()) return thm1;
00247 Theorem thm2 = find(e1);
00248 DebugAssert(thm2.getLHS()==e1,"");
00249 if (thm2.getLHS() != thm2.getRHS()) {
00250 e.setFind(transitivityRule(thm1,thm2));
00251 return e.getFind();
00252 }
00253 return thm1;
00254 }
00255
00256
00257 Expr Theory::getTCC(const Expr& e)
00258 {
00259 const Expr& tccCached = e.lookupTCC();
00260 if (!tccCached.isNull()) return tccCached;
00261 if(e.isVar()) {
00262 e.setTCC(trueExpr());
00263 return trueExpr();
00264 }
00265 Theory* i = theoryOf(e.getKind());
00266 TRACE("tccs", "computeTCC["+i->getName()+"](", e, ") {");
00267 e.setTCC(i->computeTCC(e));
00268 TRACE("tccs", "computeTCC["+i->getName()+"] => ", e.lookupTCC(), " }");
00269 return e.lookupTCC();
00270 }
00271
00272
00273 Type Theory::getBaseType(const Expr& e)
00274 {
00275 return getBaseType(e.getType());
00276 }
00277
00278
00279 Type Theory::getBaseType(const Type& tp)
00280 {
00281 const Expr& e = tp.getExpr();
00282 DebugAssert(!e.isNull(), "Theory::getBaseType(Type(Null))");
00283
00284 Type res(e.lookupType());
00285 if(!res.isNull()) return res;
00286
00287 DebugAssert(theoryOf(e) != NULL,
00288 "Theory::getBaseType(): No theory for the type: "
00289 +tp.toString());
00290 TRACE("types", "getBaseType["+theoryOf(e)->getName()+"](", e, ") {");
00291 res= theoryOf(e)->computeBaseType(tp);
00292 TRACE("types", "getBaseType["+theoryOf(e)->getName()+"] => ", res, " }");
00293 e.setType(res);
00294 return res;
00295 }
00296
00297
00298 Expr Theory::getTypePred(const Type& t, const Expr& e)
00299 {
00300 Expr pred;
00301 Theory *i = theoryOf(t.getExpr().getKind());
00302 TRACE("typePred", "computeTypePred["+i->getName()+"]("+t.toString()+", ", e, ") {");
00303 pred = i->computeTypePred(t, e);
00304 TRACE("typePred", "computeTypePred["+i->getName()+"] => ", pred, " }");
00305 return pred;
00306 }
00307
00308
00309 Theorem Theory::updateHelper(const Expr& e)
00310 {
00311 vector<Theorem> newChildrenThm;
00312 vector<unsigned> changed;
00313 int k(0), ar(e.arity());
00314 Theorem thm;
00315 for (; k < ar; ++k) {
00316 thm = find(e[k]);
00317 if (thm.getLHS() != thm.getRHS()) {
00318 newChildrenThm.push_back(thm);
00319 changed.push_back(k);
00320 }
00321 }
00322 if (changed.size() == 0) thm = reflexivityRule(e);
00323 else thm = d_commonRules->substitutivityRule(e, changed, newChildrenThm);
00324 return thm;
00325 }
00326
00327
00328
00329 void Theory::setupCC(const Expr& e) {
00330 TRACE("facts setup", "setupCC["+getName()+"](", e, ") {");
00331 for (int k = 0; k < e.arity(); ++k) {
00332 e[k].addToNotify(this, e);
00333 }
00334 Theorem thm = reflexivityRule(e);
00335 e.setSig(thm);
00336 e.setRep(thm);
00337 TRACE_MSG("facts setup", "setupCC["+getName()+"]() => }");
00338 }
00339
00340
00341
00342 void Theory::updateCC(const Theorem& e, const Expr& d) {
00343 TRACE("facts update", "updateCC["+getName()+"]("+e.getExpr().toString()+", ",
00344 d, ") {");
00345 int k, ar(d.arity());
00346 const Theorem& dEQdsig = d.getSig();
00347 if (!dEQdsig.isNull()) {
00348 const Expr& dsig = dEQdsig.getRHS();
00349 Theorem thm = updateHelper(d);
00350 const Expr& sigNew = thm.getRHS();
00351 if (sigNew == dsig) {
00352 TRACE_MSG("facts update", "updateCC["+getName()+"]() [no change] => }");
00353 return;
00354 }
00355 dsig.setRep(Theorem());
00356 const Theorem& repEQsigNew = sigNew.getRep();
00357 if (!repEQsigNew.isNull()) {
00358 d.setSig(Theorem());
00359 enqueueFact(transitivityRule(repEQsigNew, symmetryRule(thm)));
00360 }
00361 else {
00362 for (k = 0; k < ar; ++k) {
00363 if (sigNew[k] != dsig[k]) {
00364 sigNew[k].addToNotify(this, d);
00365 }
00366 }
00367 d.setSig(thm);
00368 sigNew.setRep(thm);
00369 }
00370 }
00371 TRACE_MSG("facts update", "updateCC["+getName()+"]() => }");
00372 }
00373
00374
00375
00376 Theorem Theory::rewriteCC(const Expr& e) {
00377 const Theorem& rep = e.getRep();
00378 if (rep.isNull()) return reflexivityRule(e);
00379 else return symmetryRule(rep);
00380 }
00381
00382
00383 Expr Theory::parseExpr(const Expr& e) {
00384 TRACE("facts parseExpr", "parseExpr(", e, ") {");
00385 Expr res(d_theoryCore->parseExpr(e));
00386 TRACE("facts parseExpr", "parseExpr => ", res, " }");
00387 return res;
00388 }
00389
00390
00391 void Theory::getModelTerm(const Expr& e, vector<Expr>& v)
00392 {
00393 Theory *i = theoryOf(getBaseType(e).getExpr());
00394 TRACE("model", "computeModelTerm["+i->getName()+"](", e, ") {");
00395 IF_DEBUG(unsigned size = v.size();)
00396 i->computeModelTerm(e, v);
00397 TRACE("model", "computeModelTerm[", i->getName(), "] => }");
00398 DebugAssert(v.size() <= size || v.back() != e, "Primitive var was pushed on "
00399 "the stack in computeModelTerm["+i->getName()
00400 +"]: "+e.toString());
00401
00402 }
00403
00404
00405 Theorem Theory::getModelValue(const Expr& e) {
00406 return d_theoryCore->getModelValue(e);
00407 }
00408
00409
00410 bool Theory::isLeafIn(const Expr& e1, const Expr& e2)
00411 {
00412 DebugAssert(isLeaf(e1),"Expected leaf");
00413 if (e1 == e2) return true;
00414 if (theoryOf(e2) != this) return false;
00415 for(Expr::iterator i=e2.begin(), iend=e2.end(); i != iend; ++i)
00416 if (isLeafIn(e1, *i)) return true;
00417 return false;
00418 }
00419
00420
00421 bool Theory::leavesAreSimp(const Expr& e)
00422 {
00423 if (isLeaf(e)) {
00424 bool res(e.getFind().getRHS() == e);
00425 IF_DEBUG(if(!res) TRACE("facts leavesAreSimp", "leavesAreSimp(", e,
00426 " = "+e.getFind().getRHS().toString()
00427 +") => false"));
00428 return res;
00429 }
00430 for (int k = 0; k < e.arity(); ++k) {
00431 if (!leavesAreSimp(e[k])) return false;
00432 }
00433 return true;
00434 }
00435
00436
00437 Expr Theory::newVar(const string& name, const Type& type)
00438 {
00439 DebugAssert(!type.isNull(), "Error: defining a variable of NULL type");
00440 Expr res = resolveID(name);
00441 Type t;
00442
00443 if (!res.isNull()) {
00444 t = res.getType();
00445 if (t != type) {
00446 throw TypecheckException
00447 ("incompatible redefinition of variable "+name+":\n "
00448 "already defined with type: "+t.toString()
00449 +"\n the new type is: "+type.toString());
00450 }
00451 return res;
00452 }
00453
00454 t = type;
00455 while(t.getExpr().getKind() == TYPEDEF) {
00456 DebugAssert(t.arity() == 2, "Bad TYPEDEF: "+t.toString());
00457 t = t[1];
00458 }
00459 if (type.isBool()) res = d_em->newSymbolExpr(name, UCONST);
00460 else res = getEM()->newVarExpr(name);
00461
00462
00463 d_theoryCore->addToVarDB(res);
00464
00465 installID(name, res);
00466
00467 DebugAssert(type.getExpr().getKind() != ARROW,"");
00468 DebugAssert(res.lookupType().isNull(),
00469 "newVarExpr: redefining a variable "
00470 + name);
00471 res.setType(type);
00472 return res;
00473 }
00474
00475
00476 Expr Theory::newVar(const string& name, const Type& type, const Expr& def)
00477 {
00478 DebugAssert(!type.isNull(), "Error: defining a variable of NULL type");
00479 Type t;
00480 Expr res = resolveID(name);
00481 if (!res.isNull()) {
00482 throw TypecheckException
00483 ("Redefinition of variable "+name+":\n "
00484 "This variable is already defined.");
00485 }
00486 Expr v;
00487 if (type.isBool()) v = getEM()->newSymbolExpr(name, UCONST);
00488 else v = getEM()->newVarExpr(name);
00489 res = Expr(CONSTDEF, v, def);
00490
00491
00492 t = type;
00493 while(t.getExpr().getKind() == TYPEDEF) {
00494 DebugAssert(t.arity() == 2, "Bad TYPEDEF: "+t.toString());
00495 t = t[1];
00496 }
00497 v.setType(type);
00498
00499
00500 if(getBaseType(def) != getBaseType(v)) {
00501 throw TypecheckException("Type mismatch in constant definition:\n"
00502 "Constant "+v.toString()+
00503 " is declared with type:\n "
00504 +v.getType().toString()
00505 +"\nBut the type of definition is\n "
00506 +def.getType().toString());
00507 }
00508 DebugAssert(type.getExpr().getKind() != ARROW,"");
00509 DebugAssert(res.lookupType().isNull(),
00510 "newVarExpr: redefining a variable "
00511 + name);
00512
00513
00514 installID(name, res);
00515
00516 return res;
00517 }
00518
00519
00520 Op Theory::newFunction(const string& name, const Type& type,
00521 bool computeTransClosure) {
00522 DebugAssert(!type.isNull(), "Error: defining a variable of NULL type");
00523 Expr res = resolveID(name);
00524 Type t;
00525 if (!res.isNull()) {
00526 t = res.getType();
00527 throw TypecheckException
00528 ("Redefinition of variable "+name+":\n "
00529 "already defined with type: "+t.toString()
00530 +"\n the new type is: "+type.toString());
00531 }
00532 res = getEM()->newSymbolExpr(name, UFUNC);
00533
00534 t = type;
00535 while(t.getExpr().getKind() == TYPEDEF) {
00536 DebugAssert(t.arity() == 2, "Bad TYPEDEF: "+t.toString());
00537 t = t[1];
00538 }
00539 res.setType(t);
00540
00541 d_theoryCore->addToVarDB(res);
00542
00543 installID(name, res);
00544 if (computeTransClosure &&
00545 t.isFunction() && t.arity() == 3 && t[2].isBool())
00546 res.setComputeTransClosure();
00547 return res.mkOp();
00548 }
00549
00550
00551 Op Theory::newFunction(const string& name, const Type& type,
00552 const Expr& def) {
00553 DebugAssert(!type.isNull(), "Error: defining a variable of NULL type");
00554 Expr res = resolveID(name);
00555 Type t;
00556 if (!res.isNull()) {
00557 t = res.getType();
00558 throw TypecheckException
00559 ("Redefinition of variable "+name+":\n "
00560 "already defined with type: "+t.toString()
00561 +"\n the new type is: "+type.toString());
00562 }
00563 res = getEM()->newSymbolExpr(name, UFUNC);
00564
00565 t = type;
00566 while(t.getExpr().getKind() == TYPEDEF) {
00567 DebugAssert(t.arity() == 2, "Bad TYPEDEF: "+t.toString());
00568 t = t[1];
00569 }
00570 res.setType(t);
00571
00572 installID(name, res);
00573 return res.mkOp();
00574 }
00575
00576
00577 static int boundVarCount = 0;
00578
00579
00580 Expr Theory::addBoundVar(const string& name, const Type& type) {
00581 ostringstream ss;
00582 ss << boundVarCount++;
00583 Expr v(getEM()->newBoundVarExpr(name, ss.str(), type));
00584 d_theoryCore->d_boundVarStack.push_back(pair<string,Expr>(name,v));
00585 TRACE("vars", "addBoundVar("+name+", ", type, ") => "+v.toString());
00586 return v;
00587 }
00588
00589
00590 Expr Theory::addBoundVar(const string& name, const Type& type,
00591 const Expr& def) {
00592 Expr res;
00593
00594 if(type.isNull())
00595 res = def;
00596 else {
00597
00598 ostringstream ss;
00599 ss << boundVarCount++;
00600 res = Expr(LETDECL,
00601 getEM()->newBoundVarExpr(name, ss.str(), type), def);
00602 }
00603 d_theoryCore->d_boundVarStack.push_back(pair<string,Expr>(name,res));
00604 TRACE("vars", "addBoundVar("+name+", "+type.toString()+", ", def,
00605 ") => "+res.toString());
00606 return res;
00607 }
00608
00609
00610 Expr Theory::lookupVar(const string& name, Type* type)
00611 {
00612 Expr e = getEM()->newVarExpr(name);
00613 *type = e.lookupType();
00614
00615
00616
00617 if ((*type).isNull()) return Expr();
00618
00619 return e;
00620 }
00621
00622
00623
00624 Type Theory::newTypeExpr(const string& name)
00625 {
00626 Expr res = resolveID(name);
00627 if (!res.isNull()) {
00628 throw TypecheckException
00629 ("Redefinition of type variable "+name+":\n "
00630 "This variable is already defined.");
00631 }
00632 res = Expr(TYPEDECL, getEM()->newStringExpr(name));
00633
00634 installID(name, res);
00635 return Type(res);
00636 }
00637
00638
00639 Type Theory::newTypeExpr(const string& name, const Type& def)
00640 {
00641 Expr res = resolveID(name);
00642 if (!res.isNull()) {
00643 throw TypecheckException
00644 ("Redefinition of type variable "+name+":\n "
00645 "This variable is already defined.");
00646 }
00647 res = def.getExpr();
00648
00649 installID(name, res);
00650 return Type(res);
00651 }
00652
00653
00654 Expr Theory::resolveID(const string& name) {
00655 TRACE("vars", "resolveID(", name, ") {");
00656 Expr res;
00657
00658 for(vector<pair<string, Expr> >::iterator
00659 i=d_theoryCore->d_boundVarStack.begin(),
00660 iend=d_theoryCore->d_boundVarStack.end();
00661 i!=iend && res.isNull(); ++i) {
00662 if(i->first == name)
00663 res = i->second;
00664 }
00665 if(res.isNull()) {
00666
00667 map<string,Expr>::iterator i=d_theoryCore->d_globals.find(name),
00668 iend=d_theoryCore->d_globals.end();
00669 if(i!=iend)
00670 res = i->second;
00671 }
00672 TRACE("vars", "resolveID => ", res, " }");
00673 return res;
00674 }
00675
00676
00677 void Theory::installID(const string& name, const Expr& e)
00678 {
00679 DebugAssert(resolveID(name).isNull(),
00680 "installID called on existing identifier");
00681 d_theoryCore->d_globals[name] = e;
00682 }
00683
00684
00685 Theorem Theory::typePred(const Expr& e) {
00686 return d_theoryCore->typePred(e);
00687 }
00688
00689
00690 Theorem Theory::subtypePredicate(const Expr& e) {
00691 return d_theoryCore->subtypePredicate(e);
00692 }