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 }