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 
00072 //! ==> NOT EXISTS (vars): e  IFF FORALL (vars) NOT e
00073 Theorem
00074 QuantTheoremProducer::rewriteNotExists(const Expr& e) {
00075   if(CHECK_PROOFS) {
00076     CHECK_SOUND(e.isNot() && e[0].isExists(),
00077     "rewriteNotExists: expr must be NOT FORALL:\n"
00078     +e.toString());
00079   }
00080   Proof pf;
00081   if(withProof())
00082     pf = newPf("rewrite_not_exists", e);
00083   return newRWTheorem(e, e.getEM()->newClosureExpr(FORALL, e[0].getVars(),
00084                                                    !e[0].getBody()),
00085                       Assumptions::emptyAssump(), pf);
00086 }
00087 
00088 //! Instantiate a  universally quantified formula
00089 /*! From T|-FORALL(var): e generate T|-psi => e' where e' is obtained
00090  * from e by instantiating bound variables with terms in
00091  * vector<Expr>& terms.  The vector of terms should be the same
00092  * size as the vector of bound variables in e. Also elements in
00093  * each position i need to have matching base types. psi is the conjunction of 
00094  * subtype predicates for the bound variables of the quanitfied expression.
00095  * \param t1 is the quantifier (a Theorem)
00096  * \param terms are the terms to instantiate.
00097  */
00098 Theorem QuantTheoremProducer::universalInst(const Theorem& t1, const  vector<Expr>& terms, int quantLevel){
00099   
00100   Expr e = t1.getExpr();
00101   const vector<Expr>& boundVars = e.getVars();
00102   if(CHECK_PROOFS) {
00103     CHECK_SOUND(boundVars.size() == terms.size(), 
00104     "Universal instantiation: size of terms array does "
00105     "not match quanitfied variables array size");
00106     CHECK_SOUND(e.isForall(),
00107     "universal instantiation: expr must be FORALL:\n"
00108     +e.toString());
00109 //     for(unsigned int i=0; i<terms.size(); i++)
00110 //       CHECK_SOUND(d_theoryQuant->getBaseType(boundVars[i]) ==
00111 //                   d_theoryQuant->getBaseType(terms[i]),
00112 //        "Universal instantiation: type mismatch");
00113   }
00114 
00115   //build up a conjunction of type predicates for expression
00116   Expr tr = e.getEM()->trueExpr();
00117   Expr typePred = tr;
00118   //  unsigned qlevel, qlevelMax = 0;
00119   for(unsigned int i=0; i<terms.size(); i++) {
00120     Expr p = d_theoryQuant->getTypePred(boundVars[i].getType(),terms[i]);
00121     if(p!=tr) {
00122       if(typePred==tr)
00123   typePred = p;
00124       else
00125   typePred = typePred.andExpr(p);
00126     }
00127     //    qlevel = d_theoryQuant->theoryCore()->getQuantLevelForTerm(terms[i]);
00128     //    if (qlevel > qlevelMax) qlevel = qlevelMax;
00129   }
00130   Proof pf;
00131   if(withProof()) {
00132     vector<Proof> pfs;
00133     vector<Expr> es;
00134     pfs.push_back(t1.getProof());
00135     es.push_back(e);
00136     es.insert(es.end(), terms.begin(), terms.end());
00137     pf= newPf("universal_elimination", es, pfs);
00138   }
00139    Expr inst = e.getBody().substExpr(e.getVars(), terms);
00140    Expr imp;
00141    if(typePred == tr)
00142      imp = inst;
00143    else
00144      imp = typePred.impExpr(inst); 
00145    Theorem ret = newTheorem(imp, t1.getAssumptionsRef(), pf);
00146    //   ret.setQuantLevel(qlevel+1);
00147    ret.setQuantLevel(quantLevel+1);
00148    return ret;
00149 }
00150 
00151 Theorem QuantTheoremProducer::universalInst(const Theorem& t1, const  vector<Expr>& terms){
00152 
00153   Expr e = t1.getExpr();
00154   const vector<Expr>& boundVars = e.getVars();
00155   if(CHECK_PROOFS) {
00156     CHECK_SOUND(boundVars.size() == terms.size(), 
00157     "Universal instantiation: size of terms array does "
00158     "not match quanitfied variables array size");
00159     CHECK_SOUND(e.isForall(),
00160     "universal instantiation: expr must be FORALL:\n"
00161     +e.toString());
00162     for(unsigned int i=0; i<terms.size(); i++)
00163       CHECK_SOUND(d_theoryQuant->getBaseType(boundVars[i]) ==
00164                   d_theoryQuant->getBaseType(terms[i]),
00165         "Universal instantiation: type mismatch");
00166   }
00167 
00168   //build up a conjunction of type predicates for expression
00169   Expr tr = e.getEM()->trueExpr();
00170   Expr typePred = tr;
00171   unsigned qlevel=0, qlevelMax = 0;
00172   for(unsigned int i=0; i<terms.size(); i++) {
00173     Expr p = d_theoryQuant->getTypePred(boundVars[i].getType(),terms[i]);
00174     if(p!=tr) {
00175       if(typePred==tr)
00176   typePred = p;
00177       else
00178   typePred = typePred.andExpr(p);
00179     }
00180     qlevel = d_theoryQuant->theoryCore()->getQuantLevelForTerm(terms[i]);
00181     if (qlevel > qlevelMax) qlevel = qlevelMax;
00182   }
00183   Proof pf;
00184   if(withProof()) {
00185     vector<Proof> pfs;
00186     vector<Expr> es;
00187     pfs.push_back(t1.getProof());
00188     es.push_back(e);
00189     es.insert(es.end(), terms.begin(), terms.end());
00190     pf= newPf("universal_elimination", es, pfs);
00191   }
00192    Expr inst = e.getBody().substExpr(e.getVars(), terms);
00193    Expr imp;
00194    if(typePred == tr)
00195      imp = inst;
00196    else
00197      imp = typePred.impExpr(inst); 
00198    Theorem ret = newTheorem(imp, t1.getAssumptionsRef(), pf);
00199    ret.setQuantLevel(qlevel+1);
00200    return ret;
00201 }
00202 
00203 
00204 Theorem QuantTheoremProducer::partialUniversalInst(const Theorem& t1, const vector<Expr>& terms, int quantLevel){
00205   Expr e = t1.getExpr();
00206   const vector<Expr>& boundVars = e.getVars();
00207   if(CHECK_PROOFS) {
00208     CHECK_SOUND(boundVars.size() >= terms.size(), 
00209     "Universal instantiation: size of terms array does "
00210     "not match quanitfied variables array size");
00211     CHECK_SOUND(e.isForall(),
00212     "universal instantiation: expr must be FORALL:\n"
00213     +e.toString());
00214     for(unsigned int i=0; i<terms.size(); i++){
00215       CHECK_SOUND(d_theoryQuant->getBaseType(boundVars[i]) ==
00216                   d_theoryQuant->getBaseType(terms[i]),
00217         "partial Universal instantiation: type mismatch");
00218     }
00219   }
00220 
00221   //build up a conjunction of type predicates for expression
00222   Expr tr = e.getEM()->trueExpr();
00223   Expr typePred = tr;
00224   for(unsigned int i=0; i<terms.size(); i++) {
00225     Expr p = d_theoryQuant->getTypePred(boundVars[i].getType(),terms[i]);
00226     if(p!=tr) {
00227       if(typePred==tr)
00228   typePred = p;
00229       else
00230   typePred = typePred.andExpr(p);
00231     }
00232   }
00233   Proof pf;
00234   if(withProof()) {
00235     vector<Proof> pfs;
00236     vector<Expr> es;
00237     pfs.push_back(t1.getProof());
00238     es.push_back(e);
00239     es.insert(es.end(), terms.begin(), terms.end());
00240     pf= newPf("partial_universal_instantiation", es, pfs);
00241   }
00242    
00243 
00244   if(terms.size() == boundVars.size()){
00245     Expr inst = e.getBody().substExpr(e.getVars(), terms);
00246     Expr imp;
00247     if(typePred == tr)
00248       imp = inst;
00249     else
00250       imp = typePred.impExpr(inst); 
00251     return(newTheorem(imp, t1.getAssumptionsRef(), pf));
00252   }
00253   else{
00254     vector<Expr> newBoundVars;
00255     for(size_t i=0; i<terms.size(); i++) {
00256       newBoundVars.push_back(boundVars[i]);
00257     }
00258     
00259     vector<Expr>leftBoundVars;
00260     for(size_t i=terms.size(); i<boundVars.size(); i++) {
00261       leftBoundVars.push_back(boundVars[i]);
00262     }
00263     
00264     Expr tempinst = e.getBody().substExpr(newBoundVars, terms);
00265     Expr inst = d_theoryQuant->getEM()->newClosureExpr(FORALL, leftBoundVars, tempinst);
00266 
00267     Expr imp;
00268     if(typePred == tr)
00269       imp = inst;
00270     else
00271       imp = typePred.impExpr(inst);
00272     
00273     Theorem res = (newTheorem(imp, t1.getAssumptionsRef(), pf));
00274     res.setQuantLevel(quantLevel+1);
00275     return res;
00276     
00277   }
00278 }
00279 
00280 //! find all bound variables in e and maps them to true in boundVars
00281 void QuantTheoremProducer::recFindBoundVars(const Expr& e, 
00282                ExprMap<bool> & boundVars, ExprMap<bool> &visited) 
00283 {
00284   if(visited.count(e)>0)
00285     return;
00286   else
00287     visited[e] = true;
00288   if(e.getKind() == BOUND_VAR)
00289     boundVars[e] = true;
00290   if(e.getKind() == EXISTS || e.getKind() == FORALL)
00291     recFindBoundVars(e.getBody(), boundVars, visited);
00292   for(Expr::iterator it = e.begin(); it!=e.end(); ++it)
00293     recFindBoundVars(*it, boundVars, visited);
00294   
00295 }
00296 
00297 //!adjust the order of bound vars, newBvs begin first
00298 Theorem QuantTheoremProducer::adjustVarUniv(const Theorem& t1, const std::vector<Expr>& newBvs){
00299   const Expr e=t1.getExpr();
00300   const Expr body = e.getBody();
00301   if(CHECK_PROOFS) {
00302       CHECK_SOUND(e.isForall(),
00303     "adjustVarUniv: "
00304     +e.toString());
00305   }
00306 
00307   const vector<Expr>& origVars = e.getVars();
00308 
00309  
00310   ExprMap<bool> oldmap; 
00311   for(vector<Expr>::const_iterator it = origVars.begin(), 
00312   iend=origVars.end(); it!=iend; ++it)    {
00313     oldmap[*it]=true;
00314   }
00315   
00316   vector<Expr> quantVars;
00317   for(vector<Expr>::const_iterator it = newBvs.begin(), 
00318   iend=newBvs.end(); it!=iend; ++it)    {
00319     if(oldmap.count(*it) > 0)
00320       quantVars.push_back(*it);
00321   }
00322   
00323   if(quantVars.size() == origVars.size())
00324     return t1;
00325 
00326   ExprMap<bool> newmap; 
00327   for(vector<Expr>::const_iterator it = newBvs.begin(), 
00328   iend=newBvs.end(); it!=iend; ++it)    {
00329     newmap[*it]=true;
00330   }
00331 
00332   for(vector<Expr>::const_iterator it = origVars.begin(), 
00333   iend=origVars.end(); it!=iend; ++it)    {
00334     if(newmap.count(*it)<=0){
00335       quantVars.push_back(*it);
00336     };
00337   }
00338 
00339   Proof pf;
00340   if(withProof()) {
00341     vector<Expr> es;
00342     vector<Proof> pfs;
00343     es.push_back(e);
00344     es.insert(es.end(), quantVars.begin(), quantVars.end());
00345     pfs.push_back(t1.getProof());
00346     pf= newPf("adjustVarUniv", es, pfs);
00347   }
00348   
00349   Expr newQuantExpr;
00350   newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, quantVars, body);
00351 
00352   return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00353 }
00354 
00355 //!pack (forall (x) forall (y)) into (forall (x y))
00356 Theorem QuantTheoremProducer::packVar(const Theorem& t1){
00357   Expr out_forall =t1.getExpr();
00358 
00359   if(CHECK_PROOFS) {
00360       CHECK_SOUND(out_forall.isForall(),
00361     "packVar: "
00362     +out_forall.toString());
00363   }
00364 
00365   vector<Expr> bVars = out_forall.getVars();
00366   
00367   if(!out_forall.getBody().isForall()){
00368     return t1;
00369   } 
00370   
00371   Expr cur_body = out_forall.getBody();
00372 
00373   while(cur_body.isForall()){
00374     vector<Expr> bVarsLeft = cur_body.getVars();
00375     for(vector<Expr>::iterator i=bVarsLeft.begin(), iend=bVarsLeft.end(); i!=iend; i++){
00376       bVars.push_back(*i);
00377     }
00378     cur_body=cur_body.getBody();
00379   }
00380 
00381   Proof pf;
00382   if(withProof()) {
00383     vector<Expr> es;
00384     vector<Proof> pfs;
00385     es.push_back(out_forall);
00386     es.insert(es.end(), bVars.begin(), bVars.end());
00387     pfs.push_back(t1.getProof());
00388     pf= newPf("packVar", es, pfs);
00389   }
00390   
00391   Expr newQuantExpr;
00392   newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, bVars, cur_body);
00393 
00394   return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00395 }
00396 
00397 //!pack (forall (x) ... forall (y)) into (forall (x y)...)
00398 Theorem QuantTheoremProducer::pullVarOut(const Theorem& t1){
00399   const Expr outForall=t1.getExpr();
00400 
00401   if(CHECK_PROOFS) {
00402       CHECK_SOUND(outForall.isForall(),
00403     "pullVarOut: "
00404     +outForall.toString());
00405   }
00406 
00407   const Expr outBody = outForall.getBody();
00408   
00409   if(!((outBody.isAnd() && outBody[1].isForall()) || 
00410        (outBody.isImpl() && outBody[1].isForall()) ||
00411        (outBody.isNot() && outBody[0].isAnd() && outBody[0][1].isExists()) )){
00412     return t1;
00413   }
00414   
00415   if((outBody.isNot() && outBody[0].isAnd() && outBody[0][1].isExists())){
00416 
00417     vector<Expr> bVarsOut = outForall.getVars();
00418     
00419     const Expr innerExists =outBody[0][1];
00420     const Expr innerBody = innerExists.getBody();
00421     vector<Expr> bVarsIn = innerExists.getVars();
00422         
00423     for(vector<Expr>::iterator i=bVarsIn.begin(), iend=bVarsIn.end(); i!=iend; i++){
00424       bVarsOut.push_back(*i);
00425     }
00426     
00427     Proof pf;
00428     if(withProof()) {
00429       vector<Expr> es;
00430       vector<Proof> pfs;
00431       es.push_back(outForall);
00432       es.insert(es.end(), bVarsIn.begin(), bVarsIn.end());
00433       pfs.push_back(t1.getProof());
00434       pf= newPf("pullVarOut", es, pfs);
00435     }
00436     
00437     Expr newbody;
00438     
00439     
00440     newbody=(outBody[0][0].notExpr()).orExpr(innerBody.notExpr());
00441         
00442     Expr newQuantExpr;
00443     newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, bVarsOut, newbody);
00444 
00445     return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00446   }
00447   else if ((outBody.isAnd() && outBody[1].isForall()) || 
00448      (outBody.isImpl() && outBody[1].isForall())){
00449     
00450     vector<Expr> bVarsOut = outForall.getVars();
00451     
00452     const Expr innerForall=outBody[1];
00453     const Expr innerBody = innerForall.getBody();
00454     vector<Expr> bVarsIn = innerForall.getVars();
00455     
00456     for(vector<Expr>::iterator i=bVarsIn.begin(), iend=bVarsIn.end(); i!=iend; i++){
00457       bVarsOut.push_back(*i);
00458     }
00459     
00460     Proof pf;
00461     if(withProof()) {
00462       vector<Expr> es;
00463       vector<Proof> pfs;
00464       es.push_back(outForall);
00465       es.insert(es.end(), bVarsIn.begin(), bVarsIn.end());
00466       pfs.push_back(t1.getProof());
00467       pf= newPf("pullVarOut", es, pfs);
00468     }
00469     
00470     Expr newbody;
00471     if(outBody.isAnd()){
00472       newbody=outBody[0].andExpr(innerBody);
00473     }
00474     else if(outBody.isImpl()){
00475       newbody=outBody[0].impExpr(innerBody);
00476     }
00477     
00478     
00479     Expr newQuantExpr;
00480     newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, bVarsOut, newbody);
00481     
00482     return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00483   }
00484   FatalAssert(false, "Should be unreachable");
00485   return Theorem(); // to disable compiler warning
00486 }
00487 
00488 
00489 
00490 /*! @brief From T|- QUANTIFIER (vars): e we get T|-QUANTIFIER(vars') e
00491  * where vars' is obtained from vars by removing all bound variables
00492  *  not used in e. If vars' is empty the produced theorem is just T|-e
00493  */
00494 Theorem QuantTheoremProducer::boundVarElim(const Theorem& t1)
00495 {
00496   const Expr e=t1.getExpr();
00497   const Expr body = e.getBody();
00498   if(CHECK_PROOFS) {
00499       CHECK_SOUND(e.isForall() || e.isExists(),
00500     "bound var elimination: "
00501     +e.toString());
00502   }
00503   ExprMap<bool> boundVars; //a mapping of bound variables in the body to true
00504   ExprMap<bool> visited; //to make sure expressions aren't traversed
00505         //multiple times
00506   recFindBoundVars(body, boundVars, visited);
00507   vector<Expr> quantVars;
00508   const vector<Expr>& origVars = e.getVars();
00509   for(vector<Expr>::const_iterator it = origVars.begin(), 
00510   iend=origVars.end(); it!=iend; ++it)
00511     {
00512     if(boundVars.count(*it) > 0)
00513       quantVars.push_back(*it);
00514     }
00515 
00516   // If all variables are used, just return the original theorem
00517   if(quantVars.size() == origVars.size())
00518     return t1;
00519 
00520   Proof pf;
00521   if(withProof()) {
00522     vector<Expr> es;
00523     vector<Proof> pfs;
00524     es.push_back(e);
00525     es.insert(es.end(), quantVars.begin(), quantVars.end());
00526     pfs.push_back(t1.getProof());
00527     pf= newPf("bound_variable_elimination", es, pfs);
00528   }
00529   if(quantVars.size() == 0)
00530     return(newTheorem(e.getBody(), t1.getAssumptionsRef(), pf));
00531   
00532   Expr newQuantExpr;
00533   if(e.isForall())
00534     newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, quantVars, body);
00535   else
00536     newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(EXISTS, quantVars, body);
00537 
00538   return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf));
00539 }

Generated on Tue Jul 3 14:33:38 2007 for CVC3 by  doxygen 1.5.1