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_quant.h"
00031 #include "typecheck_exception.h"
00032 #include "parser_exception.h"
00033 #include "smtlib_exception.h"
00034 #include "quant_proof_rules.h"
00035 #include "theory_core.h"
00036 #include "command_line_flags.h"
00037
00038
00039 using namespace std;
00040 using namespace CVCL;
00041
00042
00043
00044
00045
00046
00047
00048
00049 TheoryQuant::TheoryQuant(TheoryCore* core)
00050 : Theory(core, "Quantified Expressions"),
00051 d_univs(core->getCM()->getCurrentContext()),
00052 d_savedTermsPos(core->getCM()->getCurrentContext(), 0, 0),
00053 d_univsSavedPos(core->getCM()->getCurrentContext(), 0, 0),
00054 d_univsPosFull(core->getCM()->getCurrentContext(), 0, 0),
00055 d_univsContextPos(core->getCM()->getCurrentContext(), 0, 0),
00056 d_instCount(core->getCM()->getCurrentContext(), 0,0),
00057 d_contextTerms(core->getCM()->getCurrentContext()),
00058 d_contextCache(core->getCM()->getCurrentContext()),
00059 d_maxQuantInst(&(core->getFlags()["max-quant-inst"].getInt())),
00060 d_useNew(&(core->getFlags()["quant-new"].getBool())),
00061 d_useLazyInst(&(core->getFlags()["quant-lazy"].getBool())),
00062 d_useSemMatch(&(core->getFlags()["quant-sem-match"].getBool())),
00063 d_useAtomSem(&(core->getFlags()["quant-const-match"].getBool())),
00064 d_allInstCount(core->getStatistics().counter("quantifier instantiations")),
00065 d_instRound(core->getCM()->getCurrentContext(), 0,0)
00066 {
00067 IF_DEBUG(d_univs.setName("CDList[TheoryQuant::d_univs]"));
00068 vector<int> kinds;
00069
00070 d_instCount = 0;
00071
00072 d_rules=createProofRules();
00073 kinds.push_back(EXISTS);
00074 kinds.push_back(FORALL);
00075 registerTheory(this, kinds);
00076 }
00077
00078
00079 TheoryQuant::~TheoryQuant() {
00080 if(d_rules != NULL) delete d_rules;
00081 for(std::map<Type, CDList<size_t>* ,TypeComp>::iterator
00082 it = d_contextMap.begin(), iend = d_contextMap.end();
00083 it!= iend; ++it)
00084 delete it->second;
00085 }
00086
00087 void TheoryQuant::setup(const Expr& e) {}
00088 void TheoryQuant::update(const Theorem& e, const Expr& d) {}
00089
00090 void TheoryQuant::enqueueInst(const Theorem thm)
00091 {
00092 enqueueFact(thm);
00093 d_allInstCount++;
00094 d_instThisRound++;
00095 }
00096
00097
00098 bool canGetHead(const Expr& e)
00099 {
00100 return (e.getKind() == UFUNC || e.getKind() == 2001);
00101
00102 }
00103
00104
00105 std::string TheoryQuant::getHead(const Expr& e)
00106 {
00107 if (e.getKind() == UFUNC)
00108 return e.getOp().getExpr().getName();
00109
00110 if (e.getKind() == 2001)
00111 {
00112 std::string eStr = e.toString();
00113 size_t pos1 = eStr.find('[');
00114 size_t pos2 = eStr.find('(');
00115 if (std::string::npos == pos1)
00116 {
00117 cout<<"I do not know how this happen in get head"<<endl;
00118 return "";
00119 }
00120 else
00121 return eStr.substr(0,(pos1<pos2?pos1:pos2));
00122 }
00123
00124 cout <<"cannot get the term head of "<<e.toString()<<endl;
00125 return "";
00126 }
00127
00128 static void recursiveGetSubTerm(const Expr& e, std::vector<Expr> & res) {
00129
00130 if(e.getFlag())
00131 return;
00132
00133 if(e.isClosure())
00134 return recursiveGetSubTerm(e.getBody(),res);
00135
00136
00137 if ( e.isTerm() && (!e.isVar()) && (e.getKind()!=RATIONAL_EXPR) )
00138
00139 {
00140 res.push_back(e);
00141 }
00142
00143 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
00144 {
00145 recursiveGetSubTerm(*i,res);
00146 }
00147
00148 e.setFlag();
00149 return ;
00150 }
00151
00152
00153 std::vector<Expr> getSubTerms(const Expr& e)
00154 {
00155 e.clearFlags();
00156 std::vector<Expr> res;
00157 recursiveGetSubTerm(e,res);
00158 e.clearFlags();
00159 TRACE("getsub","e is ", e.toString(),"");
00160 TRACE("getsub","have ", res.size()," subterms");
00161 return res;
00162 }
00163
00164
00165 static void recursiveGetBoundVars(const Expr& e, std::set<Expr>& result) {
00166
00167 if(e.getFlag())
00168 return ;
00169
00170 if(e.isClosure())
00171 return recursiveGetBoundVars(e.getBody(),result);
00172
00173 if (BOUND_VAR == e.getKind() ){
00174 result.insert(e);
00175 }
00176 else
00177 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i){
00178 recursiveGetBoundVars(*i,result);
00179 }
00180
00181 e.setFlag();
00182 return ;
00183 }
00184
00185
00186 std::set<Expr> getBoundVars(const Expr& e)
00187 {
00188 e.clearFlags();
00189 std::set<Expr> result;
00190 recursiveGetBoundVars(e,result);
00191 e.clearFlags();
00192 return result;
00193 }
00194
00195 bool isGoodTrigger(const Expr& e, const std::vector<Expr>& bVarsThm)
00196 {
00197 if(!canGetHead(e))
00198 return false;
00199
00200 const std::set<Expr>& bvs = getBoundVars(e);
00201 if (bvs.size() >= bVarsThm.size())
00202 {
00203 for(size_t i=0; i<bVarsThm.size(); i++)
00204 {
00205 if (bvs.find(bVarsThm[i]) == bvs.end())
00206 return false;
00207 }
00208 return true;
00209 }
00210 else return false;
00211 }
00212
00213
00214 void TheoryQuant::setupTriggers(const Theorem& thm)
00215 {
00216 const Expr & e = thm.getExpr();
00217 TRACE("triggers","====================","","");
00218 TRACE("triggers","setup ",e.toString(),"");
00219
00220 if (0 == d_univsTriggers[e].size())
00221 {
00222 const std::vector<Expr>& bVarsThm = e.getVars();
00223 const std::vector<Expr> & subterms = getSubTerms(e);
00224 for( std::vector<Expr>::const_iterator i = subterms.begin(),iend=subterms.end(); i!=iend;i++)
00225 {
00226 if(isGoodTrigger(*i,bVarsThm))
00227 {
00228 bool notfound = true;
00229 for(size_t index=0;index<d_univsTriggers[e].size();index++)
00230 {
00231 if (i->subExprOf(d_univsTriggers[e][index]))
00232 {
00233 (d_univsTriggers[e][index])=*i;
00234 notfound=false;
00235 }
00236 }
00237 if (notfound)
00238 d_univsTriggers[e].push_back(*i);
00239 }
00240 }
00241
00242 for (size_t i=0; i< d_univsTriggers[e].size();i++)
00243 {
00244 TRACE("triggers", "triggers:", d_univsTriggers[e][i].toString(),"");
00245 TRACE("triggers","------------","","");
00246 }
00247 }
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257 void TheoryQuant::assertFact(const Theorem& e)
00258 {
00259 TRACE("quant", "assertFact => ", e.toString(), "{");
00260 Theorem rule, result;
00261 const Expr& expr = e.getExpr();
00262
00263 if(expr.isExists()) {
00264 TRACE("quant", "assertFact => (ignoring existential) }", "", "");
00265 return;
00266 }
00267 DebugAssert(expr.isForall()
00268 || (expr.isNot() && (expr[0].isExists() || expr[0].isForall())),
00269 "Theory of quantifiers cannot handle expression "
00270 + expr.toString());
00271
00272 if(expr.isNot()) {
00273 if(expr[0].isForall()) {
00274 rule = d_rules->rewriteNotForall(expr);
00275 }
00276 else if(expr[0].isExists()) {
00277 rule = d_rules->rewriteNotExists(expr);
00278 }
00279 result = iffMP(e, rule);
00280 }
00281 else
00282 result = e;
00283
00284 result = d_rules->boundVarElim(result);
00285
00286 if(result.getExpr().isExists())
00287 {
00288 TRACE("quant", "assertFact => enqueuing: ", result.toString(), "}");
00289 enqueueFact(result);
00290 }
00291 else if(result.getExpr().isForall())
00292 {
00293 TRACE("quant", "assertFact => storing: ", result.toString(), "}");
00294 d_univs.push_back(result);
00295 if(*d_useNew)
00296 setupTriggers(result);
00297
00298 }
00299 else {
00300 TRACE("quant", "assertFact => enqueueing: ", result.toString(), "}");
00301 enqueueFact(result);
00302 }
00303
00304 }
00305
00306 void TheoryQuant::recGoodSemMatch(const Expr& e,
00307 const std::vector<Expr>& bVars,
00308 std::vector<Expr>& newInst,
00309 std::set<std::vector<Expr> >& instSet)
00310 {
00311 size_t curPos = newInst.size();
00312 if (bVars.size() == curPos) {
00313 Expr simpleExpr = simplifyExpr(e.substExpr(bVars,newInst));
00314 if (simpleExpr.hasFind()){
00315 std::vector<Expr> temp = newInst;
00316 instSet.insert(temp);
00317 TRACE("quant yeting", "new inst found for ", e.toString()+" ==> ", simpleExpr.toString());
00318 };
00319 }
00320 else {
00321 Type t = getBaseType(bVars[curPos]);
00322 std::vector<Expr> tyExprs= d_typeExprMap[t];
00323 if (0 == tyExprs.size()) {
00324
00325 return;
00326 }
00327 else{
00328 for (size_t i=0;i<tyExprs.size();i++){
00329 newInst.push_back(tyExprs[i]);
00330 recGoodSemMatch(e,bVars,newInst,instSet);
00331 newInst.pop_back();
00332 }
00333 }
00334 }
00335 }
00336
00337
00338 bool TheoryQuant::recSynMatch(const Expr& gterm, const Expr& vterm, ExprMap<Expr>& env)
00339 {
00340 TRACE("quant match", "gterm "+gterm.toString()," e "+vterm.toString(),"");
00341 DebugAssert ((BOUND_VAR != gterm.getKind()),"gound term "+gterm.toString()+" has bound var");
00342 if (BOUND_VAR == vterm.getKind())
00343 {
00344 ExprMap<Expr>::iterator p = env.find(vterm);
00345 if ( p != env.end())
00346 {
00347 if (simplifyExpr(gterm) != simplifyExpr(p->second))
00348 {
00349
00350 return false;
00351 }
00352 else
00353 return true;
00354 }
00355 else
00356 {
00357 env[vterm] = gterm;
00358 return true;
00359 }
00360 }
00361 else
00362 {
00363 if(simplifyExpr(vterm) == simplifyExpr(gterm))
00364 {
00365 return true;
00366 }
00367 else
00368 if ( (vterm.arity() != gterm.arity()) || (vterm.getKind() != gterm.getKind() ))
00369
00370
00371 {
00372 TRACE("quant match","different sub terms found, arity not same","gterm "+gterm.toString(), "vterm "+vterm.toString());
00373 return false;
00374 }
00375 else
00376 {
00377 if(canGetHead(vterm) && canGetHead(gterm))
00378 {
00379 if (getHead(vterm) != getHead(gterm))
00380 return false;
00381 }
00382 for(int i=0;i<vterm.arity();i++)
00383 {
00384 if (false == recSynMatch(gterm[i],vterm[i],env))
00385 return false;
00386 }
00387 return true;
00388 }
00389 }
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 void TheoryQuant::goodSynMatch(const Expr& e,
00426 const std::vector<Expr> & boundVars,
00427 std::set<std::vector<Expr> >& instSet,
00428 size_t tBegin)
00429 {
00430 const CDList<Expr>& allterms = theoryCore()->getTerms();
00431 for (size_t i=tBegin; i<allterms.size(); i++)
00432 {
00433 Expr gterm = allterms[i];
00434 if (0 == gterm.arity() )
00435 continue;
00436
00437 if(canGetHead(gterm) && (getHead(gterm) == getHead(e)) )
00438 {
00439 ExprMap<Expr> env;
00440 env.clear();
00441 bool found = recSynMatch(gterm,e,env);
00442 if(found)
00443 {
00444 TRACE("quant yeting", "found one",gterm.toString()+" to " , e.toString());
00445 std::vector<Expr> inst;
00446 DebugAssert((boundVars.size() == env.size()),"bound var size != env.size()");
00447 for(size_t i=0; i<boundVars.size(); i++)
00448 {
00449 ExprMap<Expr>::iterator p = env.find(boundVars[i]);
00450 DebugAssert((p!=env.end()),"bound var cannot be found");
00451 inst.push_back(p->second);
00452 }
00453 instSet.insert(inst);
00454 }
00455 }
00456 }
00457 }
00458
00459
00460 bool TheoryQuant::hasGoodSynInst(const Expr& trig,
00461 std::vector<Expr> & boundVars,
00462 std::set<std::vector<Expr> >& instSet,
00463 size_t tBegin)
00464 {
00465 const std::set<Expr>& bvs = getBoundVars(trig);
00466
00467 boundVars.clear();
00468 for(std::set<Expr>::iterator i=bvs.begin(),iend=bvs.end(); i!=iend; ++i)
00469 boundVars.push_back(*i);
00470
00471 instSet.clear();
00472
00473 goodSynMatch(trig,boundVars,instSet,tBegin);
00474
00475 if (instSet.size() > 0)
00476 return true;
00477 else
00478 return false;
00479 }
00480
00481
00482
00483 bool inStrCache(std::set<std::string> cache, std::string str)
00484 {
00485 return (cache.find(str) != cache.end());
00486 }
00487
00488
00489
00490 bool TheoryQuant::hasGoodSemInst(const Expr& e,
00491 std::vector<Expr> & boundVars,
00492 std::set<std::vector<Expr> >& instSet,
00493 size_t tBegin)
00494 {
00495 const std::set<Expr> bvs = getBoundVars(e);
00496
00497 boundVars.clear();
00498 for(std::set<Expr>::iterator i=bvs.begin(),iend=bvs.end(); i!=iend; ++i)
00499 boundVars.push_back(*i);
00500
00501 std::vector<Expr> newInst;
00502 instSet.clear();
00503 if(inStrCache(cacheHead,getHead(e)))
00504 recGoodSemMatch(e,boundVars,newInst,instSet);
00505
00506 if (instSet.size() > 0)
00507 return true;
00508 else
00509 return false;
00510 }
00511
00512
00513 void genInstSetThm(const std::vector<Expr>& bVarsThm,
00514 const std::vector<Expr>& bVarsTerm,
00515 const std::set<std::vector<Expr> >& termInst,
00516 std::set<std::vector<Expr> >& instSetThm)
00517 {
00518 std::vector<int> bVmap;
00519
00520 for(size_t i=0; i< bVarsThm.size(); ++i)
00521 {
00522 bVmap.push_back(-1);
00523 for (size_t j=0; j<bVarsTerm.size(); j++)
00524 {
00525 if (bVarsThm[i] == bVarsTerm[j])
00526 if(bVmap[i] != -1)
00527 {
00528 cout <<"I do not expect here";
00529 }
00530 else
00531 bVmap[i]=j;
00532 }
00533 }
00534
00535 for(size_t i=0; i< bVarsThm.size(); ++i)
00536 if( -1 == bVmap[i])
00537 {
00538
00539 return;
00540 }
00541
00542 for(std::set<std::vector<Expr> > ::iterator i=termInst.begin(),
00543 iend=termInst.end();i!=iend; i++)
00544 {
00545 std::vector<Expr> buf;
00546 buf.clear();
00547 for(size_t j=0; j< bVarsThm.size(); ++j)
00548 {
00549 buf.push_back((*i)[bVmap[j]]);
00550
00551 }
00552
00553 instSetThm.insert(buf);
00554 }
00555 }
00556
00557 void TheoryQuant::synInst(const Theorem & univ, size_t tBegin)
00558 {
00559 const Expr& quantExpr = univ.getExpr();
00560 TRACE("quant inst", "now dealing with ", quantExpr.toString() , " ");
00561 const std::vector<Expr>& bVarsThm = quantExpr.getVars();
00562 const std::vector<Expr>& triggers = d_univsTriggers[quantExpr];
00563 std::set<std::vector<Expr> > instSetThm;
00564
00565 for( std::vector<Expr>::const_iterator i= triggers.begin(), iend=triggers.end();i!=iend;++i)
00566 {
00567 std::set<std::vector<Expr> > termInst;
00568 std::vector<Expr> bVarsTrig;
00569 const Expr& trig = *i;
00570
00571
00572 TRACE("quant inst","handle trigger", trig.toString(),"");
00573 termInst.clear();
00574 bVarsTrig.clear();
00575 if(hasGoodSynInst(trig,bVarsTrig,termInst,tBegin))
00576 {
00577 genInstSetThm(bVarsThm,bVarsTrig,termInst,instSetThm);
00578
00579
00580 }
00581 }
00582
00583 if(0 == instSetThm.size())
00584 {
00585 TRACE("quant yeting","sorry, no instantiation found","","");
00586 }
00587 else
00588 {
00589 for(std::set<std::vector<Expr> >::iterator i=instSetThm.begin(), iend=instSetThm.end(); i!=iend; ++i)
00590 {
00591 Theorem t = d_rules->universalInst(univ,*i);
00592 enqueueInst(t);
00593 TRACE("quant yeting inst", "instantiating", univ.toString(), "|"+(t.toString()));
00594 }
00595 }
00596 }
00597
00598 void TheoryQuant::semInst(const Theorem & univ, size_t tBegin)
00599 {
00600 const Expr& quantExpr = univ.getExpr();
00601 TRACE("quant inst", "now dealing with ", quantExpr.toString() , " ");
00602 const std::vector<Expr>& bVarsThm = quantExpr.getVars();
00603 const std::vector<Expr>& triggers = d_univsTriggers[quantExpr];
00604 std::set<std::vector<Expr> > instSetThm;
00605
00606 for( std::vector<Expr>::const_iterator i= triggers.begin(), iend=triggers.end();i!=iend;++i)
00607 {
00608 std::set<std::vector<Expr> > termInst;
00609 std::vector<Expr> bVarsTrig;
00610 const Expr& trig = *i;
00611
00612
00613 TRACE("quant inst","handle trigger", trig.toString(),"");
00614 termInst.clear();
00615 bVarsTrig.clear();
00616 if(hasGoodSemInst(trig,bVarsTrig,termInst,tBegin))
00617 {
00618 genInstSetThm(bVarsThm,bVarsTrig,termInst,instSetThm);
00619
00620
00621 }
00622 }
00623
00624 if(0 == instSetThm.size())
00625 {
00626 TRACE("quant yeting","sorry, no instantiation found","","");
00627 }
00628 else
00629 {
00630 for(std::set<std::vector<Expr> >::iterator i=instSetThm.begin(), iend=instSetThm.end(); i!=iend; ++i)
00631 {
00632 Theorem t = d_rules->universalInst(univ,*i);
00633 enqueueInst(t);
00634 TRACE("quant yeting inst", "instantiating", univ.toString(), "|"+(t.toString()));
00635 }
00636 }
00637 }
00638
00639 void TheoryQuant::checkSat(bool fullEffort)
00640 {
00641 d_instThisRound = 0;
00642 if (!(*d_useNew))
00643 naiveCheckSat(fullEffort);
00644 else if (*d_useSemMatch)
00645 semCheckSat(fullEffort);
00646 else synCheckSat(fullEffort);
00647
00648 if( (*d_useNew) && (0 == d_instThisRound) && fullEffort )
00649 {
00650 naiveCheckSat(fullEffort);
00651 }
00652
00653 }
00654
00655 void TheoryQuant::synCheckSat(bool fullEffort)
00656 {
00657
00658
00659 size_t uSize = d_univs.size() ;
00660
00661 if (0 == uSize )
00662 return;
00663
00664 if((*d_useLazyInst) && (!fullEffort) )
00665 return;
00666
00667 if(fullEffort)
00668 {
00669 setIncomplete("Quantifier instantiation");
00670 }
00671
00672 if (d_callThisRound > 30)
00673 return;
00674
00675 const CDList<Expr>& allterms = theoryCore()->getTerms();
00676 size_t tSize = allterms.size();
00677
00678 TRACE("quant",uSize, " uSize and univsSavedPOS " , d_univsSavedPos);
00679 TRACE("quant",tSize, " tSize and TermsSavedPos ",d_savedTermsPos);
00680
00681 if ( (uSize == d_univsSavedPos) && (tSize == d_savedTermsPos) )
00682 return;
00683
00684 if ( (uSize > d_univsSavedPos) && (tSize > d_savedTermsPos) )
00685 {
00686 for(size_t id=d_univsSavedPos; id<uSize; id++)
00687 {
00688 synInst(d_univs[id],0);
00689 }
00690 for(size_t id=0; id<d_univsSavedPos; id++)
00691 {
00692 synInst(d_univs[id],d_savedTermsPos);
00693 }
00694 }
00695
00696 else if ( (uSize == d_univsSavedPos) && (tSize > d_savedTermsPos) )
00697 {
00698 for(size_t id=0 ; id<uSize; id++)
00699 {
00700 synInst(d_univs[id],d_savedTermsPos);
00701 }
00702 }
00703
00704 else if ( (uSize > d_univsSavedPos) && (tSize == d_savedTermsPos) )
00705 {
00706 for(size_t id=d_univsSavedPos ; id<uSize; id++)
00707 {
00708 synInst(d_univs[id],0);
00709 }
00710 }
00711 else
00712 cout <<" I do not believe this"<<endl;;
00713
00714 d_univsSavedPos.set(uSize);
00715 d_savedTermsPos.set(tSize);
00716
00717 if(d_instRound==theoryCore()->getCM()->scopeLevel())
00718 d_callThisRound++;
00719 else
00720 {
00721 d_callThisRound=0;
00722 d_instRound.set(theoryCore()->getCM()->scopeLevel());
00723 }
00724
00725 TRACE("quant","this round; ",d_callThisRound,"");
00726 return;
00727
00728 }
00729
00730
00731 void TheoryQuant::semCheckSat(bool fullEffort)
00732 {
00733 size_t uSize = d_univs.size() ;
00734
00735 if (0 == uSize )
00736 return;
00737
00738 if((*d_useLazyInst) && (!fullEffort) )
00739 return;
00740
00741 if(fullEffort)
00742 {
00743 setIncomplete("Quantifier instantiation");
00744 }
00745
00746 if (d_callThisRound > 30)
00747 return;
00748
00749
00750 const CDList<Expr>& allterms = theoryCore()->getTerms();
00751 size_t tSize = allterms.size();
00752
00753 TRACE("quant",uSize, " uSize and univsSavedPOS " , d_univsSavedPos);
00754 TRACE("quant",tSize, " tSize and TermsSavedPos ",d_savedTermsPos);
00755
00756 if ( (uSize == d_univsSavedPos) && (tSize == d_savedTermsPos) )
00757 return;
00758
00759 d_typeExprMap.clear();
00760 cacheHead.clear();
00761 for (size_t i=0; i<tSize; i++)
00762 {
00763 Expr term = allterms[i];
00764
00765 if (*d_useAtomSem)
00766 {
00767 if (0 ==term.arity())
00768 {
00769 Type t = getBaseType(term);
00770 (d_typeExprMap[t]).push_back(term);
00771 }
00772 }
00773 else
00774 { Type t = getBaseType(term);
00775 (d_typeExprMap[t]).push_back(term);
00776 }
00777 if(canGetHead(term))
00778 cacheHead.insert(getHead(term));
00779 }
00780
00781 if ( (uSize > d_univsSavedPos) && (tSize > d_savedTermsPos) )
00782 {
00783 for(size_t id=d_univsSavedPos; id<uSize; id++)
00784 {
00785 semInst(d_univs[id],0);
00786 }
00787 for(size_t id=0; id<d_univsSavedPos; id++)
00788 {
00789 semInst(d_univs[id],d_savedTermsPos);
00790 }
00791 }
00792
00793 else if ( (uSize == d_univsSavedPos) && (tSize > d_savedTermsPos) )
00794 {
00795 for(size_t id=0 ; id<uSize; id++)
00796 {
00797 semInst(d_univs[id],d_savedTermsPos);
00798 }
00799 }
00800
00801 else if ( (uSize > d_univsSavedPos) && (tSize == d_savedTermsPos) )
00802 {
00803 for(size_t id=d_univsSavedPos ; id<uSize; id++)
00804 {
00805 semInst(d_univs[id],0);
00806 }
00807 }
00808 else
00809 cout <<" I do not believe this"<<endl;;
00810
00811 d_univsSavedPos.set(uSize);
00812 d_savedTermsPos.set(tSize);
00813 if(d_instRound==theoryCore()->getCM()->scopeLevel())
00814 d_callThisRound++;
00815 else
00816 {
00817 d_callThisRound=0;
00818 d_instRound.set(theoryCore()->getCM()->scopeLevel());
00819 }
00820 TRACE("quant","this round; ",d_callThisRound,"");
00821 return;
00822 }
00823
00824
00825
00826 void TheoryQuant::naiveCheckSat(bool fullEffort)
00827 {
00828 TRACE("quant", "checkSat ", fullEffort, "{");
00829 IF_DEBUG(int instCount = d_instCount);
00830 size_t uSize = d_univs.size(), stSize = d_savedTerms.size();
00831 if(fullEffort && uSize > 0) {
00832
00833 setIncomplete("Quantifier instantiation");
00834
00835 if(d_instCount>=*d_maxQuantInst)
00836 return;
00837
00838
00839
00840 bool savedOnly = ((uSize > d_univsSavedPos.get() && stSize > 0) ||
00841 (stSize > d_savedTermsPos.get()));
00842 int origCount = d_instCount;
00843 if(savedOnly)
00844 {
00845 TRACE("quant", "checkSat [saved insts]: univs size = ", uSize , " ");
00846 for(size_t i=0, pos = d_univsSavedPos.get(); i<uSize; i++) {
00847 if(d_instCount>= *d_maxQuantInst)
00848 break;
00849 else
00850 instantiate(d_univs[i], i>=pos, true, d_savedTermsPos.get());
00851 }
00852 d_univsSavedPos.set(d_univs.size());
00853 d_savedTermsPos.set(stSize);
00854 }
00855 if(!savedOnly || d_instCount == origCount)
00856 {
00857 TRACE("quant", "checkSat [context insts]: univs size = ", uSize , " ");
00858 const CDList<Expr>& assertions = theoryCore()->getTerms();
00859 int origSize = d_contextTerms.size();
00860
00861
00862
00863 mapTermsByType(assertions);
00864 for(size_t i=0, pos = d_univsContextPos.get(); i<uSize; i++) {
00865 if(d_instCount>= *d_maxQuantInst)
00866 break;
00867 else
00868 instantiate(d_univs[i], i>=pos, false, origSize);
00869 }
00870 d_univsContextPos.set(d_univs.size());
00871 }
00872 TRACE("quant terse", "checkSat total insts: ",
00873 d_instCount, ", new "+int2string(d_instCount - instCount));
00874 }
00875 TRACE("quant", "checkSat total insts: ", d_instCount, " ");
00876 TRACE("quant", "checkSat new insts: ", d_instCount - instCount, " ");
00877 TRACE("quant", "checkSat effort:", fullEffort, " }");
00878
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 void TheoryQuant::instantiate(Theorem univ, bool all, bool savedMap,
00891 size_t newIndex)
00892 {
00893
00894 if(!all && ((savedMap && newIndex == d_savedTerms.size())
00895 ||(!savedMap && newIndex == d_contextTerms.size())))
00896 return;
00897
00898 TRACE("quant", "instanitate", all , "{");
00899 std::vector<Expr> varReplacements;
00900 recInstantiate(univ, all, savedMap, newIndex, varReplacements);
00901 TRACE("quant", "instanitate", "", "}");
00902
00903 }
00904
00905
00906 void TheoryQuant::recInstantiate(Theorem& univ, bool all, bool savedMap,
00907 size_t newIndex,
00908 std::vector<Expr>& varReplacements)
00909 {
00910 Expr quantExpr = univ.getExpr();
00911 const vector<Expr>& boundVars = quantExpr.getVars();
00912
00913 size_t curPos = varReplacements.size();
00914 TRACE("quant", "recInstantiate: ", boundVars.size() - curPos, "");
00915
00916 if(curPos == boundVars.size()) {
00917 if(!all)
00918 return;
00919 Theorem t = d_rules->universalInst(univ, varReplacements);
00920 d_insts[t.getExpr()] = varReplacements;
00921 TRACE("quant", "recInstantiate => " , t.toString(), "");
00922 if(d_instCount< *d_maxQuantInst) {
00923 d_instCount=d_instCount+1;
00924 enqueueInst(t);
00925 }
00926 return;
00927 }
00928
00929
00930 else {
00931 Type t = getBaseType(boundVars[curPos]);
00932 int iendC=0, iendS=0, iend;
00933 std::vector<size_t>* typeVec = NULL;
00934 CDList<size_t>* typeList = NULL;
00935 if(d_savedMap.count(t) > 0) {
00936 typeVec = &(d_savedMap[t]);
00937 iendS = typeVec->size();
00938 TRACE("quant", "adding from savedMap: ", iendS, "");
00939 }
00940 if(!savedMap) {
00941 if(d_contextMap.count(t) > 0) {
00942 typeList = d_contextMap[t];
00943 iendC = typeList->size();
00944 TRACE("quant", "adding from contextMap:", iendC , "");
00945 }
00946 }
00947 iend = iendC + iendS;
00948 for(int i =0; i<iend; i++) {
00949 TRACE("quant", "I must have gotten here!", "", "");
00950 size_t index;
00951 if(i<iendS){
00952 index = (*typeVec)[i];
00953 varReplacements.push_back(d_savedTerms[index]);
00954 }
00955 else {
00956 index = (*typeList)[i-iendS];
00957 varReplacements.push_back(d_contextTerms[index]);
00958 }
00959 if((index < newIndex) || (!savedMap && i<iendS))
00960 recInstantiate(univ, all, savedMap, newIndex, varReplacements);
00961 else
00962 recInstantiate(univ, true, savedMap, newIndex, varReplacements);
00963 varReplacements.pop_back();
00964 }
00965
00966
00967 }
00968 }
00969
00970
00971
00972
00973
00974
00975 void TheoryQuant::mapTermsByType(const CDList<Expr>& terms)
00976 {
00977 Expr trExpr=trueExpr(), flsExpr = falseExpr();
00978 Type boolT = boolType();
00979 if(d_contextMap.count(boolT) == 0)
00980 {
00981 d_contextMap[boolT] =
00982 new CDList<size_t>(theoryCore()->getCM()->getCurrentContext());
00983 size_t pos = d_contextTerms.size();
00984 d_contextTerms.push_back(trExpr);
00985 d_contextTerms.push_back(flsExpr);
00986 (*d_contextMap[boolT]).push_back(pos);
00987 (*d_contextMap[boolT]).push_back(pos+1);
00988 }
00989 for(size_t i=0; i<terms.size(); i++)
00990 recursiveMap(terms[i]);
00991
00992 for(size_t i=0; i<d_univs.size(); i++)
00993 recursiveMap(d_univs[i].getExpr());
00994 }
00995
00996
00997
00998
00999
01000
01001
01002
01003 bool TheoryQuant::recursiveMap(const Expr& e)
01004 {
01005 if(d_contextCache.count(e)>0) {
01006 return(d_contextCache[e]);
01007 }
01008 if(e.arity()>0) {
01009 for(Expr::iterator it = e.begin(), iend = e.end(); it!=iend; ++it)
01010
01011 if(recursiveMap(*it) == false) {
01012 d_contextCache[e] = false;
01013 }
01014 }
01015 else if(e.getKind() == EXISTS || e.getKind() == FORALL){
01016
01017 if(recursiveMap(e.getBody())==false) {
01018 d_contextCache[e]=false;
01019 }
01020 }
01021
01022 if(d_contextCache.count(e)>0) {
01023 return false;
01024 }
01025
01026 if(d_savedCache.count(e) > 0) {
01027 return true;
01028 }
01029
01030 Type type = getBaseType(e);
01031
01032 if(!type.isBool() && !(e.getKind()==BOUND_VAR)){
01033 TRACE("quant", "recursiveMap: found ",
01034 e.toString() + " of type " + type.toString(), "");
01035 int pos = d_contextTerms.size();
01036 d_contextTerms.push_back(e);
01037 if(d_contextMap.count(type)==0)
01038 d_contextMap[type] =
01039 new CDList<size_t>(theoryCore()->getCM()->getCurrentContext());
01040 (*d_contextMap[type]).push_back(pos);
01041 }
01042
01043 if(e.getKind() == BOUND_VAR) {
01044 d_contextCache[e] = false;
01045 return false;
01046 }
01047 else {
01048 d_contextCache[e] = true;
01049 return true;
01050 }
01051
01052
01053
01054 }
01055
01056
01057
01058
01059 void TheoryQuant::notifyInconsistent(const Theorem& thm)
01060 {
01061
01062
01063
01064 if(d_univs.size() == 0)
01065 return;
01066 DebugAssert(thm.getExpr().getKind()== FALSE, "notifyInconsistent called with"
01067 " theorem: " + thm.toString() + " which is not a derivation of false");
01068 TRACE("quant", "notifyInconsistent: { " , thm.toString(), "}");
01069 thm.clearAllFlags();
01070 findInstAssumptions(thm);
01071 TRACE("quant terse", "notifyInconsistent: savedTerms size = ",
01072 d_savedTerms.size(), "");
01073 TRACE("quant terse", "last term: ",
01074 d_savedTerms.size()? d_savedTerms.back() : Expr(), "");
01075 }
01076
01077
01078
01079 void TheoryQuant::findInstAssumptions(const Theorem& thm)
01080 {
01081 if(thm.isFlagged() || thm.isNull())
01082 return;
01083 thm.setFlag();
01084 const Expr& e = thm.getExpr();
01085 if(d_insts.count(e) > 0) {
01086 vector<Expr>& insts = d_insts[e];
01087 int pos;
01088 for(vector<Expr>::iterator it = insts.begin(), iend = insts.end(); it!=iend
01089 ; ++it)
01090 {
01091 if(d_savedCache.count(*it) == 0) {
01092 TRACE("quant", "notifyInconsistent: found:", (*it).toString(), "");
01093 d_savedCache[*it] = true;
01094 pos = d_savedTerms.size();
01095 d_savedTerms.push_back(*it);
01096 d_savedMap[getBaseType(*it)].push_back(pos);
01097 }
01098 }
01099 }
01100 if(thm.isAssump())
01101 return;
01102 const Assumptions& a = thm.getAssumptionsRef();
01103 for(Assumptions::iterator it =a.begin(), iend = a.end(); it!=iend; ++it){
01104 findInstAssumptions(*it);
01105 }
01106 }
01107
01108
01109 void TheoryQuant::computeType(const Expr& e)
01110 {
01111 switch (e.getKind()) {
01112 case FORALL:
01113 case EXISTS: {
01114 if(!e.getBody().getType().isBool())
01115 throw TypecheckException("Type mismatch for expression:\n\n "
01116 + e.getBody().toString()
01117 + "\n\nhas the following type:\n\n "
01118 + e.getBody().getType().toString()
01119 + "\n\nbut the expected type is Boolean:\n\n ");
01120 else
01121
01122 e.setType(e.getBody().getType());
01123 break;
01124 }
01125 default:
01126 DebugAssert(false,"Unexpected kind in Quantifier Theory: "
01127 + e.toString());
01128 break;
01129 }
01130 }
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 Expr TheoryQuant::computeTCC(const Expr& e) {
01141 DebugAssert(e.isQuantifier(), "Unexpected expression in Quantifier Theory: "
01142 + e.toString());
01143
01144 bool forall(e.getKind() == FORALL);
01145 const Expr& phi = e.getBody();
01146 Expr tcc_phi = getTCC(phi);
01147 Expr forall_tcc = getEM()->newClosureExpr(FORALL, e.getVars(), tcc_phi);
01148 Expr exists_tcc = getEM()->newClosureExpr(EXISTS, e.getVars(),
01149 tcc_phi && (forall? !phi : phi));
01150 return (forall_tcc || exists_tcc);
01151 }
01152
01153
01154 ExprStream&
01155 TheoryQuant::print(ExprStream& os, const Expr& e) {
01156 switch(os.lang()) {
01157 case PRESENTATION_LANG: {
01158 switch(e.getKind()){
01159 case FORALL:
01160 case EXISTS: {
01161 if(!e.isQuantifier()) {
01162 e.printAST(os);
01163 break;
01164 }
01165 os << "(" << push << ((e.getKind() == FORALL)? "FORALL" : "EXISTS")
01166 << space << push;
01167 const vector<Expr>& vars = e.getVars();
01168 bool first(true);
01169 os << "(" << push;
01170 for(vector<Expr>::const_iterator i=vars.begin(), iend=vars.end();
01171 i!=iend; ++i) {
01172 if(first) first = false;
01173 else os << push << "," << pop << space;
01174 os << *i;
01175
01176
01177 if(i->isVar())
01178 os << ":" << space << pushdag << (*i).getType() << popdag;
01179 }
01180 os << push << "): " << pushdag << push
01181 << e.getBody() << push << ")";
01182 }
01183 break;
01184 default:
01185 e.printAST(os);
01186 break;
01187 }
01188 break;
01189 }
01190 case SMTLIB_LANG: {
01191 d_theoryUsed = true;
01192 switch(e.getKind()){
01193 case FORALL:
01194 case EXISTS: {
01195 if(!e.isQuantifier()) {
01196 e.printAST(os);
01197 break;
01198 }
01199 os << "(" << push << ((e.getKind() == FORALL)? "forall" : "exists")
01200 << space;
01201 const vector<Expr>& vars = e.getVars();
01202 bool first(true);
01203
01204 for(vector<Expr>::const_iterator i=vars.begin(), iend=vars.end();
01205 i!=iend; ++i) {
01206 if(first) first = false;
01207 else os << space;
01208 os << "(" << push << *i;
01209
01210
01211 if(i->isVar())
01212 os << space << pushdag << (*i).getType() << popdag;
01213 os << push << ")" << pop << pop;
01214 }
01215 os << pushdag
01216 << e.getBody() << push << ")";
01217 break;
01218 }
01219 default:
01220 throw SmtlibException("TheoryQuant::print: SMTLIB_LANG: Unexpected expression: "
01221 +getEM()->getKindName(e.getKind()));
01222 break;
01223 }
01224 break;
01225 }
01226 case LISP_LANG: {
01227 switch(e.getKind()){
01228 case FORALL:
01229 case EXISTS: {
01230 if(!e.isQuantifier()) {
01231 e.printAST(os);
01232 break;
01233 }
01234 os << "(" << push << ((e.getKind() == FORALL)? "FORALL" : "EXISTS")
01235 << space;
01236 const vector<Expr>& vars = e.getVars();
01237 bool first(true);
01238 os << "(" << push;
01239 for(vector<Expr>::const_iterator i=vars.begin(), iend=vars.end();
01240 i!=iend; ++i) {
01241 if(first) first = false;
01242 else os << space;
01243 os << "(" << push << *i;
01244
01245
01246 if(i->isVar())
01247 os << space << pushdag << (*i).getType() << popdag;
01248 os << push << ")" << pop << pop;
01249 }
01250 os << push << ")" << pop << pop << pushdag
01251 << e.getBody() << push << ")";
01252 }
01253 break;
01254 default:
01255 e.printAST(os);
01256 break;
01257 }
01258 break;
01259 }
01260 default:
01261 e.printAST(os);
01262 break;
01263 }
01264 return os;
01265 }
01266
01267
01268
01269
01270
01271 Expr
01272 TheoryQuant::parseExprOp(const Expr& e) {
01273 TRACE("parser", "TheoryQuant::parseExprOp(", e, ")");
01274
01275
01276 if(RAW_LIST != e.getKind()) return e;
01277
01278 DebugAssert(e.arity() > 0,
01279 "TheoryQuant::parseExprOp:\n e = "+e.toString());
01280
01281 const Expr& c1 = e[0][0];
01282 const string& opName(c1.getString());
01283 int kind = getEM()->getKind(opName);
01284 switch(kind) {
01285 case FORALL:
01286 case EXISTS: {
01287 if(!(e.arity() == 3 && e[1].getKind() == RAW_LIST && e[1].arity() > 0))
01288 throw ParserException("Bad "+opName+" expression: "+e.toString());
01289
01290 vector<pair<string,Type> > vars;
01291 for(Expr::iterator i=e[1].begin(), iend=e[1].end(); i!=iend; ++i) {
01292 if(i->getKind() != RAW_LIST || i->arity() < 2)
01293 throw ParserException("Bad variable declaration block in "+opName
01294 +" expression: "+i->toString()
01295 +"\n e = "+e.toString());
01296
01297
01298
01299 Type tp(parseExpr((*i)[i->arity()-1]));
01300 for(int j=0, jend=i->arity()-1; j<jend; ++j) {
01301 if((*i)[j].getKind() != ID)
01302 throw ParserException("Bad variable declaration in "+opName+""
01303 " expression: "+(*i)[j].toString()+
01304 "\n e = "+e.toString());
01305 vars.push_back(pair<string,Type>((*i)[j][0].getString(), tp));
01306 }
01307 }
01308
01309 vector<Expr> boundVars;
01310 for(vector<pair<string,Type> >::iterator i=vars.begin(), iend=vars.end();
01311 i!=iend; ++i)
01312 boundVars.push_back(addBoundVar(i->first, i->second));
01313
01314 Expr body(parseExpr(e[2]));
01315
01316 Expr res = getEM()->newClosureExpr((kind == FORALL) ? FORALL : EXISTS,
01317 boundVars, body);
01318 return res;
01319 break;
01320 }
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331 default:
01332 DebugAssert(false,
01333 "TheoryQuant::parseExprOp: invalid command or expression: " + e.toString());
01334 break;
01335 }
01336 return e;
01337 }