expr_transform.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file expr_transform.cpp
00004  * 
00005  * Author: Ying Hu, Clark Barrett
00006  * 
00007  * Created: Jun 05 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  */
00019 /*****************************************************************************/
00020 
00021 
00022 #include "expr_transform.h"
00023 #include "theory_core.h"
00024 #include "command_line_flags.h"
00025 #include "core_proof_rules.h"
00026 
00027 
00028 using namespace std;
00029 using namespace CVC3;
00030 
00031 
00032 ExprTransform::ExprTransform(TheoryCore* core) : d_core(core)
00033 {
00034   d_commonRules = d_core->getCommonRules();  
00035   d_rules = d_core->getCoreRules();
00036 }
00037 
00038 
00039 Theorem ExprTransform::smartSimplify(const Expr& e, ExprMap<bool>& cache)
00040 {
00041   ExprMap<bool>::iterator it;
00042   vector<Expr> operatorStack;
00043   vector<int> childStack;
00044   Expr e2;
00045 
00046   operatorStack.push_back(e);
00047   childStack.push_back(0);
00048 
00049   while (!operatorStack.empty()) {
00050     DebugAssert(operatorStack.size() == childStack.size(), "Invariant violated");
00051     if (childStack.back() < operatorStack.back().arity()) {
00052       e2 = operatorStack.back()[childStack.back()++];
00053       it = cache.find(e2);
00054       if (it != cache.end() || e2.hasFind() ||
00055           e2.validSimpCache() || e2.arity() == 0) continue;
00056       if (operatorStack.size() >= 5000) {
00057         smartSimplify(e2, cache);
00058         cache[e2] = true;
00059       }
00060       else {
00061         operatorStack.push_back(e2);
00062         childStack.push_back(0);
00063       }
00064     }
00065     else {
00066       cache[operatorStack.back()] = true;
00067       operatorStack.pop_back();
00068       childStack.pop_back();
00069     }
00070   }
00071   DebugAssert(childStack.empty(), "Invariant violated");
00072   return d_core->simplify(e);
00073 }
00074 
00075 
00076 Theorem ExprTransform::preprocess(const Expr& e)
00077 {
00078   Theorem thm1;
00079   if (d_core->getFlags()["pp-pushneg"].getBool())
00080     thm1 = pushNegation(e);
00081   else
00082     thm1 = d_commonRules->reflexivityRule(e);
00083   ExprMap<bool> cache;
00084   thm1 = d_commonRules->transitivityRule(thm1, smartSimplify(thm1.getRHS(), cache));
00085   return thm1;
00086 }
00087 
00088 
00089 Theorem ExprTransform::preprocess(const Theorem& thm)
00090 {
00091   return d_commonRules->iffMP(thm, preprocess(thm.getExpr()));
00092 }
00093 
00094 
00095 // We assume that the cache is initially empty
00096 Theorem ExprTransform::pushNegation(const Expr& e) {
00097   if(e.isTerm()) return d_commonRules->reflexivityRule(e);
00098   Theorem res(pushNegationRec(e, false));
00099   d_pushNegCache.clear();
00100   return res;
00101 }
00102 
00103 
00104 // Recursively descend into the expression e, keeping track of whether
00105 // we are under even or odd number of negations ('neg' == true means
00106 // odd, the context is "negative").
00107 
00108 // Produce a proof of e <==> e' or !e <==> e', depending on whether
00109 // neg is false or true, respectively.
00110 Theorem ExprTransform::pushNegationRec(const Expr& e, bool neg) {
00111   TRACE("pushNegation", "pushNegationRec(", e,
00112   ", neg=" + string(neg? "true":"false") + ") {");
00113   DebugAssert(!e.isTerm(), "pushNegationRec: not boolean e = "+e.toString());
00114   ExprMap<Theorem>::iterator i = d_pushNegCache.find(neg? !e : e);
00115   if(i != d_pushNegCache.end()) { // Found cached result
00116     TRACE("pushNegation", "pushNegationRec [cached] => ", (*i).second, "}");
00117     return (*i).second;
00118   }
00119   // By default, do not rewrite
00120   Theorem res(d_core->reflexivityRule((neg)? !e : e));
00121   if(neg) {
00122     switch(e.getKind()) {
00123       case TRUE_EXPR: res = d_commonRules->rewriteNotTrue(!e); break;
00124       case FALSE_EXPR: res = d_commonRules->rewriteNotFalse(!e); break;
00125       case NOT: 
00126         res = pushNegationRec(d_commonRules->rewriteNotNot(!e), false);
00127         break;
00128       case AND:
00129         res = pushNegationRec(d_rules->rewriteNotAnd(!e), false);
00130         break;
00131       case OR: 
00132         res = pushNegationRec(d_rules->rewriteNotOr(!e), false);
00133         break;
00134       case IMPLIES: {
00135         vector<Theorem> thms;
00136         thms.push_back(d_rules->rewriteImplies(e));
00137         res = pushNegationRec
00138           (d_commonRules->substitutivityRule(NOT, thms), true);
00139         break;
00140       }
00141 //       case IFF:
00142 //  // Preserve equivalences to explore structural similarities
00143 //  if(e[0].getKind() == e[1].getKind())
00144 //    res = d_commonRules->reflexivityRule(!e);
00145 //  else
00146 //    res = pushNegationRec(d_commonRules->rewriteNotIff(!e), false);
00147 //         break;
00148       case ITE:
00149         res = pushNegationRec(d_rules->rewriteNotIte(!e), false);
00150         break;
00151 
00152       // Replace LETDECL with its definition.  The
00153       // typechecker makes sure it's type-safe to do so.
00154       case LETDECL: {
00155         vector<Theorem> thms;
00156         thms.push_back(d_rules->rewriteLetDecl(e));
00157         res = pushNegationRec
00158           (d_commonRules->substitutivityRule(NOT, thms), true);
00159         break;
00160       }
00161       default:
00162         res = d_commonRules->reflexivityRule(!e);
00163     } // end of switch(e.getKind())
00164   } else { // if(!neg)
00165     switch(e.getKind()) {
00166       case NOT: res = pushNegationRec(e[0], true); break;
00167       case AND:
00168       case OR:
00169       case IFF:
00170       case ITE: {
00171         Op op = e.getOp();
00172         vector<Theorem> thms;
00173         for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
00174           thms.push_back(pushNegationRec(*i, false));
00175         res = d_commonRules->substitutivityRule(op, thms);
00176         break;
00177       }
00178       case IMPLIES:
00179         res = pushNegationRec(d_rules->rewriteImplies(e), false);
00180         break;
00181       case LETDECL:
00182         res = pushNegationRec(d_rules->rewriteLetDecl(e), false);
00183         break;
00184       default:
00185         res = d_commonRules->reflexivityRule(e);
00186     } // end of switch(e.getKind())
00187   }
00188   TRACE("pushNegation", "pushNegationRec => ", res, "}");
00189   d_pushNegCache[neg? !e : e] = res;
00190   return res;
00191 }
00192 
00193 
00194 Theorem ExprTransform::pushNegationRec(const Theorem& thm, bool neg) {
00195   DebugAssert(thm.isRewrite(), "pushNegationRec(Theorem): bad theorem: "
00196         + thm.toString());
00197   Expr e(thm.getRHS());
00198   if(neg) {
00199     DebugAssert(e.isNot(), 
00200     "pushNegationRec(Theorem, neg = true): bad Theorem: "
00201     + thm.toString());
00202     e = e[0];
00203   }
00204   return d_commonRules->transitivityRule(thm, pushNegationRec(e, neg));
00205 }
00206 
00207 
00208 Theorem ExprTransform::pushNegation1(const Expr& e) {
00209   TRACE("pushNegation1", "pushNegation1(", e, ") {");
00210   DebugAssert(e.isNot(), "pushNegation1("+e.toString()+")");
00211   Theorem res;
00212   switch(e[0].getKind()) {
00213     case TRUE_EXPR: res = d_commonRules->rewriteNotTrue(e); break;
00214     case FALSE_EXPR: res = d_commonRules->rewriteNotFalse(e); break;
00215     case NOT: 
00216       res = d_commonRules->rewriteNotNot(e);
00217       break;
00218     case AND:
00219       res = d_rules->rewriteNotAnd(e);
00220       break;
00221     case OR: 
00222       res = d_rules->rewriteNotOr(e);
00223       break;
00224     case IMPLIES: {
00225       vector<Theorem> thms;
00226       thms.push_back(d_rules->rewriteImplies(e[0]));
00227       res = d_commonRules->substitutivityRule(e.getOp(), thms);
00228       res = d_commonRules->transitivityRule(res, d_rules->rewriteNotOr(res.getRHS()));
00229       break;
00230     }
00231     case ITE:
00232       res = d_rules->rewriteNotIte(e);
00233       break;
00234       // Replace LETDECL with its definition.  The
00235       // typechecker makes sure it's type-safe to do so.
00236     case LETDECL: {
00237       vector<Theorem> thms;
00238       thms.push_back(d_rules->rewriteLetDecl(e[0]));
00239       res = d_commonRules->substitutivityRule(e.getOp(), thms);
00240       res = d_commonRules->transitivityRule(res, pushNegation1(res.getRHS()));
00241       break;
00242     }
00243     default:
00244       res = d_commonRules->reflexivityRule(e);
00245   }
00246   TRACE("pushNegation1", "pushNegation1 => ", res.getExpr(), " }");
00247   return res;
00248 }

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