CVC3

quant_theorem_producer.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003 * \file quant_theorem_producer.cpp
00004  *
00005  * Author: Daniel Wichs, Yeting Ge
00006  *
00007  * Created: Jul 07 22:22:38 GMT 2003
00008  *
00009  * <hr>
00010  *
00011  * License to use, copy, modify, sell and/or distribute this software
00012  * and its documentation for any purpose is hereby granted without
00013  * royalty, subject to the terms and conditions defined in the \ref
00014  * LICENSE file provided with this distribution.
00015  *
00016  * <hr>
00017  *
00018  * CLASS: QuantProofRules
00019  *
00020  *
00021  * Description: TRUSTED implementation of arithmetic proof rules.
00022  *
00023  */
00024 /*****************************************************************************/
00025 
00026 // This code is trusted
00027 #define _CVC3_TRUSTED_
00028 
00029 
00030 #include "quant_theorem_producer.h"
00031 #include "theory_quant.h"
00032 #include "theory_core.h"
00033 
00034 
00035 using namespace std;
00036 using namespace CVC3;
00037 
00038 
00039 QuantProofRules* TheoryQuant::createProofRules() {
00040   return new QuantTheoremProducer(theoryCore()->getTM(), this);
00041 }
00042 
00043 
00044 #define CLASS_NAME "CVC3::QuantTheoremProducer"
00045 
00046 
00047 //! ==> NOT FORALL (vars): e  IFF EXISTS (vars) NOT e
00048 Theorem
00049 QuantTheoremProducer::rewriteNotForall(const Expr& e) {
00050   if(CHECK_PROOFS) {
00051     CHECK_SOUND(e.isNot() && e[0].isForall(),
00052     "rewriteNotForall: expr must be NOT FORALL:\n"
00053     +e.toString());
00054   }
00055   Proof pf;
00056   if(withProof())
00057     pf = newPf("rewrite_not_forall", e);
00058   return newRWTheorem(e, e.getEM()->newClosureExpr(EXISTS, e[0].getVars(),
00059                                                    !e[0].getBody()),
00060                       Assumptions::emptyAssump(), pf);
00061 }
00062 
00063 Theorem
00064 QuantTheoremProducer::addNewConst(const Expr& e) {
00065   Proof pf;
00066   if(withProof())
00067     pf = newPf("add_new_const", e);
00068   return newTheorem(e, Assumptions::emptyAssump(), pf);
00069 }
00070 
00071 ///do not use this rule, this is for debug only
00072 Theorem
00073 QuantTheoremProducer::newRWThm(const Expr& e, const Expr& newE) {
00074   Proof pf;
00075   if(withProof())
00076     pf = newPf("from cache", e);
00077   return newRWTheorem(e, newE,Assumptions::emptyAssump(), pf);
00078 }
00079 
00080 
00081 Theorem
00082 QuantTheoremProducer::normalizeQuant(const Expr& quant) {
00083   if(CHECK_PROOFS) {
00084     CHECK_SOUND(quant.isForall()||quant.isExists(),
00085     "normalizeQuant: expr must be FORALL or EXISTS\n"
00086     +quant.toString());
00087   }
00088 
00089 
00090   std::map<Expr,int>::iterator typeIter;
00091   std::string base("_BD");
00092   int counter(0);
00093 
00094   vector<Expr> newVars;
00095   const std::vector<Expr>& cur_vars = quant.getVars();
00096   for(size_t j =0; j<cur_vars.size(); j++){
00097     Type t = cur_vars[j].getType();
00098     int typeIndex ;
00099 
00100     typeIter = d_typeFound.find(t.getExpr());
00101 
00102     if(d_typeFound.end() ==  typeIter){
00103       typeIndex = d_typeFound.size();
00104       d_typeFound[t.getExpr()] = typeIndex;
00105     }
00106     else{
00107       typeIndex = typeIter->second;
00108     }
00109 
00110     counter++;
00111     std::stringstream stringType;
00112     stringType << counter << "TY" << typeIndex ;
00113     std::string out_str = base + stringType.str();
00114     Expr newExpr = d_theoryQuant->getEM()->newBoundVarExpr(out_str, int2string(counter));
00115     newExpr.setType(t);
00116     newVars.push_back(newExpr);
00117   }
00118 
00119   vector<vector<Expr> > trigs = quant.getTriggers();
00120   for(size_t i = 0 ; i < trigs.size(); i++){
00121     for(size_t j = 0 ; j < trigs[i].size(); j++){
00122       trigs[i][j] = trigs[i][j].substExpr(cur_vars,newVars);
00123     }
00124   }
00125 
00126   Expr normBody = quant.getBody().substExpr(cur_vars,newVars);
00127   Expr normQuant = d_theoryQuant->getEM()->newClosureExpr(quant.isForall()?FORALL:EXISTS, newVars, normBody, trigs);
00128 
00129   Proof pf;
00130   if(withProof())
00131     pf = newPf("normalizeQuant", quant, normQuant);
00132 
00133   return newRWTheorem(quant, normQuant, Assumptions::emptyAssump(), pf);
00134 
00135 }
00136 
00137 
00138 //! ==> NOT EXISTS (vars): e  IFF FORALL (vars) NOT e
00139 Theorem QuantTheoremProducer::rewriteNotExists(const Expr& e) {
00140   if(CHECK_PROOFS) {
00141     CHECK_SOUND(e.isNot() && e[0].isExists(),
00142     "rewriteNotExists: expr must be NOT FORALL:\n"
00143     +e.toString());
00144   }
00145   Proof pf;
00146   if(withProof())
00147     pf = newPf("rewrite_not_exists", e);
00148   return newRWTheorem(e, e.getEM()->newClosureExpr(FORALL, e[0].getVars(),
00149                                                    !e[0].getBody()),
00150                       Assumptions::emptyAssump(), pf);
00151 }
00152 
00153 
00154 Theorem QuantTheoremProducer::universalInst(const Theorem& t1, const  vector<Expr>& terms, int quantLevel, Expr gterm){
00155   Expr e = t1.getExpr();
00156   const vector<Expr>& boundVars = e.getVars();
00157 
00158      for(unsigned int i=0; i<terms.size(); i++){
00159        if (d_theoryQuant->getBaseType(boundVars[i]) !=
00160     d_theoryQuant->getBaseType(terms[i])){
00161   Proof pf;
00162   return newRWTheorem(terms[i],terms[i], 
00163           Assumptions::emptyAssump(), pf);
00164        }
00165  //this is the same as return a TRUE theorem, which will be ignored immeridatele.  So, this is just return doing nothing. 
00166      }
00167 
00168 
00169   if(CHECK_PROOFS) {
00170     CHECK_SOUND(boundVars.size() == terms.size(),
00171     "Universal instantiation: size of terms array does "
00172     "not match quanitfied variables array size");
00173     CHECK_SOUND(e.isForall(),
00174     "universal instantiation: expr must be FORALL:\n"
00175     +e.toString());
00176 
00177     for(unsigned int i=0; i<terms.size(); i++)
00178       CHECK_SOUND(d_theoryQuant->getBaseType(boundVars[i]) ==
00179       d_theoryQuant->getBaseType(terms[i]),
00180       "Universal instantiation: type mismatch");
00181   }
00182 
00183   //build up a conjunction of type predicates for expression
00184   Expr tr = e.getEM()->trueExpr();
00185   Expr typePred = tr;
00186   //  unsigned qlevel, qlevelMax = 0;
00187   for(unsigned int i=0; i<terms.size(); i++) {
00188     Expr p = d_theoryQuant->getTypePred(boundVars[i].getType(),terms[i]);
00189     if(p!=tr) {
00190       if(typePred==tr)
00191   typePred = p;
00192       else
00193   typePred = typePred.andExpr(p);
00194     }
00195     //    qlevel = d_theoryQuant->theoryCore()->getQuantLevelForTerm(terms[i]);
00196     //    if (qlevel > qlevelMax) qlevel = qlevelMax;
00197   }
00198 
00199 
00200   //  Expr inst = e.getBody().substExprQuant(e.getVars(), terms);
00201   Expr inst = e.getBody().substExpr(e.getVars(), terms);
00202 
00203   //  Expr inst = e.getBody().substExpr(e.getVars(), terms);
00204 
00205 
00206   Proof pf;
00207   if(withProof()) {
00208     vector<Proof> pfs;
00209     vector<Expr> es;
00210     pfs.push_back(t1.getProof());
00211     es.push_back(e);
00212     es.push_back(Expr(RAW_LIST,terms));
00213     //    es.insert(es.end(), terms.begin(), terms.end());
00214     es.push_back(inst);
00215     if (gterm.isNull()) {
00216       es.push_back( d_theoryQuant->getEM()->newRatExpr(0));
00217     }
00218     else {es.push_back(gterm);
00219     }
00220     pf= newPf("universal_elimination1", es, pfs);
00221   }
00222 
00223 
00224   //   Expr inst = e.getBody().substExpr(e.getVars(), terms);
00225 
00226 
00227    Expr imp;
00228    if(typePred == tr ) //just for a easy life, yeting, change this assp
00229      imp = inst;
00230    else
00231      imp = typePred.impExpr(inst);
00232    Theorem ret = newTheorem(imp, t1.getAssumptionsRef(), pf);
00233 
00234    int thmLevel = t1.getQuantLevel();
00235    if(quantLevel  >= thmLevel) {
00236       ret.setQuantLevel(quantLevel+1);
00237     }
00238     else{
00239       ret.setQuantLevel(thmLevel+1);
00240     }
00241 
00242    //   ret.setQuantLevel(quantLevel+1);
00243    return ret;
00244 }
00245 
00246 
00247 //! Instantiate a  universally quantified formula
00248 /*! From T|-FORALL(var): e generate T|-psi => e' where e' is obtained
00249  * from e by instantiating bound variables with terms in
00250  * vector<Expr>& terms.  The vector of terms should be the same
00251  * size as the vector of bound variables in e. Also elements in
00252  * each position i need to have matching base types. psi is the conjunction of
00253  * subtype predicates for the bound variables of the quanitfied expression.
00254  * \param t1 the quantifier (a Theorem)
00255  * \param terms the terms to instantiate.
00256  * \param quantLevel the quantification level for the formula
00257  */
00258 Theorem QuantTheoremProducer::universalInst(const Theorem& t1, const  vector<Expr>& terms, int quantLevel){
00259 
00260   Expr e = t1.getExpr();
00261   const vector<Expr>& boundVars = e.getVars();
00262   if(CHECK_PROOFS) {
00263     CHECK_SOUND(boundVars.size() == terms.size(),
00264     "Universal instantiation: size of terms array does "
00265     "not match quanitfied variables array size");
00266     CHECK_SOUND(e.isForall(),
00267     "universal instantiation: expr must be FORALL:\n"
00268     +e.toString());
00269      for(unsigned int i=0; i<terms.size(); i++)
00270        CHECK_SOUND(d_theoryQuant->getBaseType(boundVars[i]) ==
00271                    d_theoryQuant->getBaseType(terms[i]),
00272         "Universal instantiation: type mismatch");
00273   }
00274 
00275   //build up a conjunction of type predicates for expression
00276   Expr tr = e.getEM()->trueExpr();
00277   Expr typePred = tr;
00278   //  unsigned qlevel, qlevelMax = 0;
00279   for(unsigned int i=0; i<terms.size(); i++) {
00280     Expr p = d_theoryQuant->getTypePred(boundVars[i].getType(),terms[i]);
00281     if(p!=tr) {
00282       if(typePred==tr)
00283   typePred = p;
00284       else
00285   typePred = typePred.andExpr(p);
00286     }
00287     //    qlevel = d_theoryQuant->theoryCore()->getQuantLevelForTerm(terms[i]);
00288     //    if (qlevel > qlevelMax) qlevel = qlevelMax;
00289   }
00290 
00291   //Expr inst = e.getBody().substExprQuant(e.getVars(), terms);
00292   Expr inst = e.getBody().substExpr(e.getVars(), terms);
00293 
00294 
00295   //  Expr inst = e.getBody().substExpr(e.getVars(), terms);
00296 
00297 
00298   Proof pf;
00299   if(withProof()) {
00300     vector<Proof> pfs;
00301     vector<Expr> es;
00302     pfs.push_back(t1.getProof());
00303     es.push_back(e);
00304     es.push_back(Expr(RAW_LIST,terms));
00305     //    es.insert(es.end(), terms.begin(), terms.end());
00306     es.push_back(inst);
00307     pf= newPf("universal_elimination2", es, pfs);
00308   }
00309 
00310   //   Expr inst = e.getBody().substExpr(e.getVars(), terms);
00311 
00312 
00313    Expr imp;
00314    if(typePred == tr) //just for a easy life, yeting, change this assp
00315      imp = inst;
00316    else
00317      imp = typePred.impExpr(inst);
00318    Theorem ret = newTheorem(imp, t1.getAssumptionsRef(), pf);
00319 
00320    int thmLevel = t1.getQuantLevel();
00321    if(quantLevel >= thmLevel) {
00322       ret.setQuantLevel(quantLevel+1);
00323     }
00324     else{
00325       ret.setQuantLevel(thmLevel+1);
00326     }
00327 
00328    //   ret.setQuantLevel(quantLevel+1);
00329    return ret;
00330 }
00331 
00332 Theorem QuantTheoremProducer::universalInst(const Theorem& t1, const  vector<Expr>& terms){
00333 
00334   Expr e = t1.getExpr();
00335   const vector<Expr>& boundVars = e.getVars();
00336   if(CHECK_PROOFS) {
00337     CHECK_SOUND(boundVars.size() == terms.size(),
00338     "Universal instantiation: size of terms array does "
00339     "not match quanitfied variables array size");
00340     CHECK_SOUND(e.isForall(),
00341     "universal instantiation: expr must be FORALL:\n"
00342     +e.toString());
00343     for(unsigned int i=0; i<terms.size(); i++)
00344       CHECK_SOUND(d_theoryQuant->getBaseType(boundVars[i]) ==
00345                   d_theoryQuant->getBaseType(terms[i]),
00346         "Universal instantiation: type mismatch");
00347   }
00348 
00349   //build up a conjunction of type predicates for expression
00350   Expr tr = e.getEM()->trueExpr();
00351   Expr typePred = tr;
00352   unsigned qlevel=0, qlevelMax = 0;
00353   for(unsigned int i=0; i<terms.size(); i++) {
00354     Expr p = d_theoryQuant->getTypePred(boundVars[i].getType(),terms[i]);
00355     if(p!=tr) {
00356       if(typePred==tr)
00357   typePred = p;
00358       else
00359   typePred = typePred.andExpr(p);
00360     }
00361     qlevel = d_theoryQuant->theoryCore()->getQuantLevelForTerm(terms[i]);
00362     if (qlevel > qlevelMax) qlevel = qlevelMax;
00363   }
00364 
00365   Expr inst = e.getBody().substExpr(e.getVars(), terms);
00366   //  Expr inst = e.getBody().substExprQuant(e.getVars(), terms);
00367 
00368 
00369   //  Expr inst = e.getBody().substExpr(e.getVars(), terms);
00370 
00371   Proof pf;
00372   if(withProof()) {
00373     vector<Proof> pfs;
00374     vector<Expr> es;
00375     pfs.push_back(t1.getProof());
00376     es.push_back(e);
00377     es.push_back(Expr(RAW_LIST,terms));
00378     //    es.insert(es.end(), terms.begin(), terms.end());
00379     es.push_back(inst);
00380     pf= newPf("universal_elimination3", es, pfs);
00381   }
00382 
00383   //   Expr inst = e.getBody().substExpr(e.getVars(), terms);
00384 
00385    Expr imp;
00386    if( typePred == tr ) //just for easy life, yeting, change this asap
00387      imp = inst;
00388    else
00389      imp = typePred.impExpr(inst);
00390    Theorem ret = newTheorem(imp, t1.getAssumptionsRef(), pf);
00391 
00392 
00393    unsigned thmLevel = t1.getQuantLevel();
00394    if(qlevel >= thmLevel) {
00395       ret.setQuantLevel(qlevel+1);
00396     }
00397     else{
00398       //      ret.setQuantLevel(thmLevel+1);
00399       ret.setQuantLevel(thmLevel+1);
00400     }
00401 
00402 
00403    //   ret.setQuantLevel(qlevel+1);
00404    return ret;
00405 }
00406 
00407 
00408 Theorem QuantTheoremProducer::partialUniversalInst(const Theorem& t1, const vector<Expr>& terms, int quantLevel){
00409   cout<<"error in partial inst" << endl;
00410   Expr e = t1.getExpr();
00411   const vector<Expr>& boundVars = e.getVars();
00412   if(CHECK_PROOFS) {
00413     CHECK_SOUND(boundVars.size() >= terms.size(),
00414     "Universal instantiation: size of terms array does "
00415     "not match quanitfied variables array size");
00416     CHECK_SOUND(e.isForall(),
00417     "universal instantiation: expr must be FORALL:\n"
00418     +e.toString());
00419     for(unsigned int i=0; i<terms.size(); i++){
00420       CHECK_SOUND(d_theoryQuant->getBaseType(boundVars[i]) ==
00421                   d_theoryQuant->getBaseType(terms[i]),
00422         "partial Universal instantiation: type mismatch");
00423     }
00424   }
00425 
00426   //build up a conjunction of type predicates for expression
00427   Expr tr = e.getEM()->trueExpr();
00428   Expr typePred = tr;
00429   for(unsigned int i=0; i<terms.size(); i++) {
00430     Expr p = d_theoryQuant->getTypePred(boundVars[i].getType(),terms[i]);
00431     if(p!=tr) {
00432       if(typePred==tr)
00433   typePred = p;
00434       else
00435   typePred = typePred.andExpr(p);
00436     }
00437   }
00438   Proof pf;
00439   if(withProof()) {
00440     vector<Proof> pfs;
00441     vector<Expr> es;
00442     pfs.push_back(t1.getProof());
00443     es.push_back(e);
00444     es.insert(es.end(), terms.begin(), terms.end());
00445     pf= newPf("partial_universal_instantiation", es, pfs);
00446   }
00447 
00448 
00449   if(terms.size() == boundVars.size()){
00450     Expr inst = e.getBody().substExpr(e.getVars(), terms);
00451     Expr imp;
00452     if(typePred == tr)
00453       imp = inst;
00454     else
00455       imp = typePred.impExpr(inst);
00456     return(newTheorem(imp, t1.getAssumptionsRef(), pf));
00457   }
00458   else{
00459     vector<Expr> newBoundVars;
00460     for(size_t i=0; i<terms.size(); i++) {
00461       newBoundVars.push_back(boundVars[i]);
00462     }
00463 
00464     vector<Expr>leftBoundVars;
00465     for(size_t i=terms.size(); i<boundVars.size(); i++) {
00466       leftBoundVars.push_back(boundVars[i]);
00467     }
00468 
00469     Expr tempinst = e.getBody().substExpr(newBoundVars, terms);
00470     Expr inst = d_theoryQuant->getEM()->newClosureExpr(FORALL, leftBoundVars, tempinst);
00471 
00472     Expr imp;
00473     if(typePred == tr)
00474       imp = inst;
00475     else
00476       imp = typePred.impExpr(inst);
00477 
00478     Theorem res = (newTheorem(imp, t1.getAssumptionsRef(), pf));
00479     int thmLevel = t1.getQuantLevel();
00480     if(quantLevel >= thmLevel) {
00481       res.setQuantLevel(quantLevel+1);
00482     }
00483     else{
00484       //k      ret.setQuantLevel(thmLevel+1);
00485       res.setQuantLevel(thmLevel);
00486     }
00487     return res;
00488 
00489   }
00490 }
00491 
00492 //! find all bound variables in e and maps them to true in boundVars
00493 void QuantTheoremProducer::recFindBoundVars(const Expr& e,
00494                ExprMap<bool> & boundVars, ExprMap<bool> &visited)
00495 {
00496   if(visited.count(e)>0)
00497     return;
00498   else
00499     visited[e] = true;
00500   if(e.getKind() == BOUND_VAR)
00501     boundVars[e] = true;
00502   if(e.getKind() == EXISTS || e.getKind() == FORALL)
00503     recFindBoundVars(e.getBody(), boundVars, visited);
00504   for(Expr::iterator it = e.begin(); it!=e.end(); ++it)
00505     recFindBoundVars(*it, boundVars, visited);
00506 
00507 }
00508 
00509 //!adjust the order of bound vars, newBvs begin first
00510 Theorem QuantTheoremProducer::adjustVarUniv(const Theorem& t1, const std::vector<Expr>& newBvs){
00511   const Expr e=t1.getExpr();
00512   const Expr body = e.getBody();
00513   if(CHECK_PROOFS) {
00514       CHECK_SOUND(e.isForall(),
00515     "adjustVarUniv: "
00516     +e.toString());
00517   }
00518 
00519   const vector<Expr>& origVars = e.getVars();
00520 
00521 
00522   ExprMap<bool> oldmap;
00523   for(vector<Expr>::const_iterator it = origVars.begin(),
00524   iend=origVars.end(); it!=iend; ++it)    {
00525     oldmap[*it]=true;
00526   }
00527 
00528   vector<Expr> quantVars;
00529   for(vector<Expr>::const_iterator it = newBvs.begin(),
00530   iend=newBvs.end(); it!=iend; ++it)    {
00531     if(oldmap.count(*it) > 0)
00532       quantVars.push_back(*it);
00533   }
00534 
00535   if(quantVars.size() == origVars.size())
00536     return t1;
00537 
00538   ExprMap<bool> newmap;
00539   for(vector<Expr>::const_iterator it = newBvs.begin(),
00540   iend=newBvs.end(); it!=iend; ++it)    {
00541     newmap[*it]=true;
00542   }
00543 
00544   for(vector<Expr>::const_iterator it = origVars.begin(),
00545   iend=origVars.end(); it!=iend; ++it)    {
00546     if(newmap.count(*it)<=0){
00547       quantVars.push_back(*it);
00548     };
00549   }
00550 
00551   Proof pf;
00552   if(withProof()) {
00553     vector<Expr> es;
00554     vector<Proof> pfs;
00555     es.push_back(e);
00556     es.insert(es.end(), quantVars.begin(), quantVars.end());
00557     pfs.push_back(t1.getProof());
00558     pf= newPf("adjustVarUniv", es, pfs);
00559   }
00560 
00561   Expr newQuantExpr;
00562   newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, quantVars, body);
00563 
00564   return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00565 }
00566 
00567 //!pack (forall (x) forall (y)) into (forall (x y))
00568 Theorem QuantTheoremProducer::packVar(const Theorem& t1){
00569   Expr out_forall =t1.getExpr();
00570 
00571   if(CHECK_PROOFS) {
00572       CHECK_SOUND(out_forall.isForall(),
00573     "packVar: "
00574     +out_forall.toString());
00575   }
00576 
00577   vector<Expr> bVars = out_forall.getVars();
00578 
00579   if(!out_forall.getBody().isForall()){
00580     return t1;
00581   }
00582 
00583   Expr cur_body = out_forall.getBody();
00584 
00585   while(cur_body.isForall()){
00586     vector<Expr> bVarsLeft = cur_body.getVars();
00587     for(vector<Expr>::iterator i=bVarsLeft.begin(), iend=bVarsLeft.end(); i!=iend; i++){
00588       bVars.push_back(*i);
00589     }
00590     cur_body=cur_body.getBody();
00591   }
00592 
00593   Proof pf;
00594   if(withProof()) {
00595     vector<Expr> es;
00596     vector<Proof> pfs;
00597     es.push_back(out_forall);
00598     es.insert(es.end(), bVars.begin(), bVars.end());
00599     pfs.push_back(t1.getProof());
00600     pf= newPf("packVar", es, pfs);
00601   }
00602 
00603   Expr newQuantExpr;
00604   newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, bVars, cur_body);
00605 
00606   return (newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00607   //  return (newRWTheorem(t1,newQuantExpr, t1.getAssumptionsRef(), pf));
00608 }
00609 
00610 //! convert (forall (x) ... forall (y)) into (forall (x y)...)
00611 //! convert (exists (x) ... exists (y)) into (exists (x y)...)
00612 Theorem QuantTheoremProducer::pullVarOut(const Theorem& t1){
00613   const Expr thm_expr=t1.getExpr();
00614   
00615   if(CHECK_PROOFS) {
00616     CHECK_SOUND(thm_expr.isForall() || thm_expr.isExists(),
00617     "pullVarOut: "
00618     +thm_expr.toString());
00619   }
00620 
00621   const Expr outBody = thm_expr.getBody();
00622 
00623 //   if(((outBody.isAnd() && outBody[1].isForall()) ||
00624 //        (outBody.isImpl() && outBody[1].isForall()) ||
00625 //        (outBody.isNot() && outBody[0].isAnd() && outBody[0][1].isExists()) )){
00626 //     return t1;
00627 //   }
00628 
00629   if (thm_expr.isForall()){
00630     if((outBody.isNot() && outBody[0].isAnd() && outBody[0][1].isExists())){
00631       
00632       vector<Expr> bVarsOut = thm_expr.getVars();
00633       
00634       const Expr innerExists =outBody[0][1];
00635       const Expr innerBody = innerExists.getBody();
00636       vector<Expr> bVarsIn = innerExists.getVars();
00637       
00638       for(vector<Expr>::iterator i=bVarsIn.begin(), iend=bVarsIn.end(); i!=iend; i++){
00639   bVarsOut.push_back(*i);
00640       }
00641       
00642       Proof pf;
00643       if(withProof()) {
00644   vector<Expr> es;
00645   vector<Proof> pfs;
00646   es.push_back(thm_expr);
00647   es.insert(es.end(), bVarsIn.begin(), bVarsIn.end());
00648   pfs.push_back(t1.getProof());
00649   pf= newPf("pullVarOut", es, pfs);
00650       }
00651       
00652       Expr newbody;
00653       
00654       newbody=(outBody[0][0].notExpr()).orExpr(innerBody.notExpr());
00655       
00656       Expr newQuantExpr;
00657       newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, bVarsOut, newbody);
00658       
00659       return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00660     }
00661     
00662     else if ((outBody.isAnd() && outBody[1].isForall()) ||
00663        (outBody.isImpl() && outBody[1].isForall())){
00664       
00665       vector<Expr> bVarsOut = thm_expr.getVars();
00666       
00667       const Expr innerForall=outBody[1];
00668       const Expr innerBody = innerForall.getBody();
00669       vector<Expr> bVarsIn = innerForall.getVars();
00670       
00671       for(vector<Expr>::iterator i=bVarsIn.begin(), iend=bVarsIn.end(); i!=iend; i++){
00672   bVarsOut.push_back(*i);
00673       }
00674       
00675       Proof pf;
00676       if(withProof()) {
00677   vector<Expr> es;
00678   vector<Proof> pfs;
00679   es.push_back(thm_expr);
00680   es.insert(es.end(), bVarsIn.begin(), bVarsIn.end());
00681   pfs.push_back(t1.getProof());
00682   pf= newPf("pullVarOut", es, pfs);
00683       }
00684       
00685       Expr newbody;
00686       if(outBody.isAnd()){
00687   newbody=outBody[0].andExpr(innerBody);
00688       }
00689       else if(outBody.isImpl()){
00690   newbody=outBody[0].impExpr(innerBody);
00691       }
00692       
00693       Expr newQuantExpr;
00694       newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, bVarsOut, newbody);
00695       
00696       return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00697     }
00698     return t1; // case cannot be handled now. 
00699   }
00700   
00701   else if (thm_expr.isExists()){
00702     if ((outBody.isAnd() && outBody[1].isExists()) ||
00703   (outBody.isImpl() && outBody[1].isExists())){
00704       
00705       vector<Expr> bVarsOut = thm_expr.getVars();
00706       
00707       const Expr innerExists = outBody[1];
00708       const Expr innerBody = innerExists.getBody();
00709       vector<Expr> bVarsIn = innerExists.getVars();
00710       
00711       for(vector<Expr>::iterator i=bVarsIn.begin(), iend=bVarsIn.end(); i!=iend; i++){
00712   bVarsOut.push_back(*i);
00713       }
00714       
00715       Proof pf;
00716       if(withProof()) {
00717   vector<Expr> es;
00718   vector<Proof> pfs;
00719   es.push_back(thm_expr);
00720   es.insert(es.end(), bVarsIn.begin(), bVarsIn.end());
00721   pfs.push_back(t1.getProof());
00722   pf= newPf("pullVarOut", es, pfs);
00723       }
00724       
00725       Expr newbody;
00726       if(outBody.isAnd()){
00727   newbody=outBody[0].andExpr(innerBody);
00728       }
00729       else if(outBody.isImpl()){
00730   newbody=outBody[0].impExpr(innerBody);
00731       }
00732       
00733       Expr newQuantExpr;
00734       newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(EXISTS, bVarsOut, newbody);
00735       
00736       return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00737     }
00738   }
00739   return t1; 
00740 }
00741 
00742 
00743 
00744 /*! @brief From T|- QUANTIFIER (vars): e we get T|-QUANTIFIER(vars') e
00745  * where vars' is obtained from vars by removing all bound variables
00746  *  not used in e. If vars' is empty the produced theorem is just T|-e
00747  */
00748 Theorem QuantTheoremProducer::boundVarElim(const Theorem& t1)
00749 {
00750   const Expr e=t1.getExpr();
00751   const Expr body = e.getBody();
00752   if(CHECK_PROOFS) {
00753       CHECK_SOUND(e.isForall() || e.isExists(),
00754     "bound var elimination: "
00755     +e.toString());
00756   }
00757   ExprMap<bool> boundVars; //a mapping of bound variables in the body to true
00758   ExprMap<bool> visited; //to make sure expressions aren't traversed
00759         //multiple times
00760   recFindBoundVars(body, boundVars, visited);
00761   vector<Expr> quantVars;
00762   const vector<Expr>& origVars = e.getVars();
00763   for(vector<Expr>::const_iterator it = origVars.begin(),
00764   iend=origVars.end(); it!=iend; ++it)
00765     {
00766     if(boundVars.count(*it) > 0)
00767       quantVars.push_back(*it);
00768     }
00769 
00770   // If all variables are used, just return the original theorem
00771   if(quantVars.size() == origVars.size())
00772     return t1;
00773 
00774   Proof pf;
00775   if(withProof()) {
00776     vector<Expr> es;
00777     vector<Proof> pfs;
00778     es.push_back(e);
00779     es.insert(es.end(), quantVars.begin(), quantVars.end());
00780     pfs.push_back(t1.getProof());
00781     pf= newPf("bound_variable_elimination", es, pfs);
00782   }
00783   if(quantVars.size() == 0)
00784     return(newTheorem(e.getBody(), t1.getAssumptionsRef(), pf));
00785 
00786   Expr newQuantExpr;
00787   if(e.isForall())
00788     newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, quantVars, body);
00789   else
00790     newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(EXISTS, quantVars, body);
00791 
00792   return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00793 }