cnf_manager.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  *\file cnf_manager.cpp
00004  *\brief Implementation of CNF_Manager
00005  *
00006  * Author: Clark Barrett
00007  *
00008  * Created: Thu Jan  5 02:30:02 2006
00009  *
00010  * <hr>
00011  * Copyright (C) 2006 by the Board of Trustees of Leland Stanford
00012  * Junior University and by New York University. 
00013  *
00014  * License to use, copy, modify, sell and/or distribute this software
00015  * and its documentation for any purpose is hereby granted without
00016  * royalty, subject to the terms and conditions defined in the \ref
00017  * LICENSE file provided with this distribution.  In particular:
00018  *
00019  * - The above copyright notice and this permission notice must appear
00020  * in all copies of the software and related documentation.
00021  *
00022  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00023  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00024  * 
00025  * <hr>
00026  */
00027 /*****************************************************************************/
00028 
00029 
00030 #include "cnf_manager.h"
00031 #include "cnf_rules.h"
00032 #include "common_proof_rules.h"
00033 #include "theorem_manager.h"
00034 
00035 
00036 using namespace std;
00037 using namespace CVCL;
00038 using namespace SAT;
00039 
00040 
00041 CNF_Manager::CNF_Manager(TheoremManager* tm)
00042   : d_commonRules(tm->getRules()),
00043     d_theorems(tm->getCM()->getCurrentContext()),
00044     d_clauseIdNext(0),
00045     //    d_translated(tm->getCM()->getCurrentContext()),
00046     d_bottomScope(-1)
00047 {
00048   d_rules = createProofRules(tm);
00049   // Push dummy varinfo onto d_varInfo since Var's are indexed from 1 not 0
00050   Varinfo v;
00051   d_varInfo.push_back(v);
00052 }
00053 
00054 
00055 CNF_Manager::~CNF_Manager()
00056 {
00057   delete d_rules;
00058 }
00059 
00060 
00061 Theorem CNF_Manager::replaceITErec(const Expr& e, Var v, bool translateOnly)
00062 {
00063   // Quick exit for atomic expressions
00064   if (e.isAtomic()) return d_commonRules->reflexivityRule(e);
00065 
00066   // Check cache
00067   Theorem thm;
00068   bool foundInCache = false;
00069   ExprMap<Theorem>::iterator iMap = d_iteMap.find(e);
00070   if (iMap != d_iteMap.end()) {
00071     thm = (*iMap).second;
00072     foundInCache = true;
00073   }
00074 
00075   if (e.getKind() == ITE) {
00076     // Replace non-Bool ITE expressions
00077     DebugAssert(!e.getType().isBool(), "Expected non-Bool ITE");
00078     // generate e = x for new x
00079     if (!foundInCache) thm = d_commonRules->varIntroSkolem(e);
00080     Theorem thm2 = d_commonRules->symmetryRule(thm);
00081     thm2 = d_commonRules->iffMP(thm2, d_rules->ifLiftRule(thm2.getExpr(), 1));
00082     d_translateQueueVars.push_back(v);
00083     d_translateQueueThms.push_back(thm2);
00084     d_translateQueueFlags.push_back(translateOnly);
00085   }
00086   else {
00087     // Recursively traverse, replacing ITE's
00088     vector<Theorem> thms;
00089     vector<unsigned> changed;
00090     unsigned index = 0;
00091     Expr::iterator i, iend;
00092     if (foundInCache) {
00093       for(i = e.begin(), iend = e.end(); i!=iend; ++i, ++index) {
00094         replaceITErec(*i, v, translateOnly);
00095       }
00096     }
00097     else {
00098       for(i = e.begin(), iend = e.end(); i!=iend; ++i, ++index) {
00099         thm = replaceITErec(*i, v, translateOnly);
00100         if(thm.getLHS() != thm.getRHS()) {
00101           thms.push_back(thm);
00102           changed.push_back(index);
00103         }
00104       }
00105       if(changed.size() > 0) {
00106         thm = d_commonRules->substitutivityRule(e, changed, thms);
00107       }
00108       else thm = d_commonRules->reflexivityRule(e);
00109     }
00110   }
00111 
00112   // Update cache and return
00113   if (!foundInCache) d_iteMap[e] = thm;
00114   return thm;
00115 }
00116 
00117 
00118 Lit CNF_Manager::translateExprRec(const Expr& e, CNF_Formula& cnf)
00119 {
00120   if (e.isFalse()) return Lit::getFalse();
00121   if (e.isTrue()) return Lit::getTrue();
00122   if (e.isNot()) return !translateExprRec(e[0], cnf);
00123 
00124   ExprMap<Var>::iterator iMap = d_cnfVars.find(e);
00125 
00126   if (e.isTranslated()) {
00127     DebugAssert(iMap != d_cnfVars.end(), "Translated expr should be in map");
00128     return Lit((*iMap).second);
00129   }
00130   else e.setTranslated(d_bottomScope);
00131 
00132   Var v(int(d_varInfo.size()));
00133   bool translateOnly = false;
00134 
00135   if (iMap != d_cnfVars.end()) {
00136     v = (*iMap).second;
00137     translateOnly = true;
00138     d_varInfo[v].fanouts.clear();
00139   }
00140   else {
00141     d_varInfo.resize(v+1);
00142     d_varInfo.back().expr = e;
00143     d_cnfVars[e] = v;
00144   }
00145 
00146   Expr::iterator i, iend;
00147 
00148   bool isAnd = false;
00149   switch (e.getKind()) {
00150     case AND:
00151       isAnd = true;
00152     case OR: {
00153       vector<Lit> lits;
00154       unsigned idx;
00155       for (i = e.begin(), iend = e.end(); i != iend; ++i) {
00156         lits.push_back(translateExprRec(*i, cnf));
00157       }
00158       for (idx = 0; idx < lits.size(); ++idx) {
00159         cnf.newClause();
00160         cnf.addLiteral(v,isAnd);
00161         cnf.addLiteral(lits[idx], !isAnd);
00162       }
00163       cnf.newClause();
00164       cnf.addLiteral(v,!isAnd);
00165       for (idx = 0; idx < lits.size(); ++idx) {
00166         cnf.addLiteral(lits[idx], isAnd);
00167       }
00168       break;
00169     }
00170     case IMPLIES: {
00171       Lit arg0 = translateExprRec(e[0], cnf);
00172       Lit arg1 = translateExprRec(e[1], cnf);
00173 
00174       cnf.newClause();
00175       cnf.addLiteral(v);
00176       cnf.addLiteral(arg0);
00177 
00178       cnf.newClause();
00179       cnf.addLiteral(v);
00180       cnf.addLiteral(arg1,true);
00181 
00182       cnf.newClause();
00183       cnf.addLiteral(v,true);
00184       cnf.addLiteral(arg0,true);
00185       cnf.addLiteral(arg1);
00186       break;
00187     }
00188     case IFF: {
00189       Lit arg0 = translateExprRec(e[0], cnf);
00190       Lit arg1 = translateExprRec(e[1], cnf);
00191 
00192       cnf.newClause();
00193       cnf.addLiteral(v);
00194       cnf.addLiteral(arg0);
00195       cnf.addLiteral(arg1);
00196 
00197       cnf.newClause();
00198       cnf.addLiteral(v);
00199       cnf.addLiteral(arg0,true);
00200       cnf.addLiteral(arg1,true);
00201 
00202       cnf.newClause();
00203       cnf.addLiteral(v,true);
00204       cnf.addLiteral(arg0,true);
00205       cnf.addLiteral(arg1);
00206 
00207       cnf.newClause();
00208       cnf.addLiteral(v,true);
00209       cnf.addLiteral(arg0);
00210       cnf.addLiteral(arg1,true);
00211       break;
00212     }
00213     case XOR: {
00214       Lit arg0 = translateExprRec(e[0], cnf);
00215       Lit arg1 = translateExprRec(e[1], cnf);
00216 
00217       cnf.newClause();
00218       cnf.addLiteral(v,true);
00219       cnf.addLiteral(arg0);
00220       cnf.addLiteral(arg1);
00221 
00222       cnf.newClause();
00223       cnf.addLiteral(v,true);
00224       cnf.addLiteral(arg0,true);
00225       cnf.addLiteral(arg1,true);
00226 
00227       cnf.newClause();
00228       cnf.addLiteral(v);
00229       cnf.addLiteral(arg0,true);
00230       cnf.addLiteral(arg1);
00231 
00232       cnf.newClause();
00233       cnf.addLiteral(v);
00234       cnf.addLiteral(arg0);
00235       cnf.addLiteral(arg1,true);
00236       break;
00237     }
00238     case ITE:
00239     {
00240       Lit arg0 = translateExprRec(e[0], cnf);
00241       Lit arg1 = translateExprRec(e[1], cnf);
00242       Lit arg2 = translateExprRec(e[2], cnf);
00243 
00244       cnf.newClause();
00245       cnf.addLiteral(v,true);
00246       cnf.addLiteral(arg0);
00247       cnf.addLiteral(arg2);
00248 
00249       cnf.newClause();
00250       cnf.addLiteral(v);
00251       cnf.addLiteral(arg0);
00252       cnf.addLiteral(arg2,true);
00253 
00254       cnf.newClause();
00255       cnf.addLiteral(v);
00256       cnf.addLiteral(arg0,true);
00257       cnf.addLiteral(arg1,true);
00258 
00259       cnf.newClause();
00260       cnf.addLiteral(v,true);
00261       cnf.addLiteral(arg0,true);
00262       cnf.addLiteral(arg1);
00263 
00264       cnf.newClause();
00265       cnf.addLiteral(v);
00266       cnf.addLiteral(arg1,true);
00267       cnf.addLiteral(arg2,true);
00268 
00269       cnf.newClause();
00270       cnf.addLiteral(v,true);
00271       cnf.addLiteral(arg1);
00272       cnf.addLiteral(arg2);
00273       break;
00274     }
00275     default:
00276       DebugAssert(!e.isAbsAtomicFormula() || d_varInfo[v].expr == e,
00277                   "Corrupted Varinfo");
00278       if (e.isAbsAtomicFormula()) return v;
00279       Theorem thm = replaceITErec(e, v, translateOnly);
00280       const Expr& e2 = thm.getRHS();
00281       DebugAssert(e2.isAbsAtomicFormula(), "Expected AbsAtomicFormula");
00282       if (e2.isTranslated()) {
00283         // Ugly corner case: we happen to create an expression that has been
00284         // created before.  We remove the current variable and fix up the
00285         // translation stack.
00286         DebugAssert(!translateOnly, "Expected translateOnly = false");
00287         d_varInfo.resize(v-1);
00288         while (d_translateQueueVars.back() == v) {
00289           d_translateQueueVars.pop_back();
00290         }
00291         DebugAssert(d_cnfVars.find(e2) != d_cnfVars.end(),
00292                     "Expected existing literal");
00293         v = d_cnfVars[e2];
00294         while (d_translateQueueVars.size() < d_translateQueueThms.size()) {
00295           d_translateQueueVars.push_back(v);
00296         }
00297       }
00298       else {
00299         e2.setTranslated(d_bottomScope);
00300         if (!translateOnly) {
00301           DebugAssert(d_cnfVars.find(e2) == d_cnfVars.end(),
00302                       "Expected new literal");
00303           d_varInfo[v].expr = e2;
00304           d_cnfVars[e2] = v;
00305         }
00306       }
00307       return v;
00308   }
00309 
00310   // Record fanins / fanouts
00311   Lit l;
00312   for (i = e.begin(), iend = e.end(); i != iend; ++i) {
00313     l = getCNFLit(*i);
00314     DebugAssert(!l.isNull(), "Expected non-null literal");
00315     if (!translateOnly) d_varInfo[v].fanins.push_back(l);
00316     if (l.isVar()) d_varInfo[l.getVar()].fanouts.push_back(v);
00317   }
00318   return v;
00319 }
00320 
00321 
00322 Lit CNF_Manager::translateExpr(const Expr& e, CNF_Formula& cnf)
00323 {
00324   Lit l;
00325   Var v;
00326   Theorem thm;
00327   bool translateOnly;
00328 
00329   Lit ret = translateExprRec(e, cnf);
00330 
00331   while (d_translateQueueVars.size()) {
00332     v = d_translateQueueVars.front();
00333     d_translateQueueVars.pop_front();
00334     thm = d_translateQueueThms.front();
00335     d_translateQueueThms.pop_front();
00336     translateOnly = d_translateQueueFlags.front();
00337     d_translateQueueFlags.pop_front();
00338     l = translateExprRec(thm.getExpr(), cnf);
00339     cnf.newClause();
00340     cnf.addLiteral(l);
00341     cnf.registerUnit();
00342     d_theorems.insert(d_clauseIdNext, thm);
00343     cnf.getCurrentClause().setId(d_clauseIdNext++);
00344     FatalAssert(d_clauseIdNext != 0, "Overflow of clause id's");
00345     if (!translateOnly) d_varInfo[v].fanins.push_back(l);
00346     d_varInfo[l.getVar()].fanouts.push_back(v);
00347   }
00348   return ret;
00349 }
00350 
00351 
00352 void CNF_Manager::convertLemma(const Theorem& thm, Clause& c)
00353 {
00354   DebugAssert(c.size() == 0, "Expected empty clause");
00355   Theorem clause = d_rules->learnedClause(thm);
00356 
00357   const Expr& e = clause.getExpr();
00358   if (!e.isOr()) {
00359     DebugAssert(!getCNFLit(e).isNull(), "Unknown literal");
00360     c.addLiteral(getCNFLit(e));
00361   }
00362   else {
00363     Expr::iterator iend = e.end();
00364     for (Expr::iterator i = e.begin(); i != iend; ++i) {
00365       DebugAssert(!getCNFLit(*i).isNull(), "Unknown literal");
00366       c.addLiteral(getCNFLit(*i));
00367     }
00368   }
00369   if (c.size() == 1) c.setUnit();
00370 
00371   d_theorems.insert(d_clauseIdNext, clause);
00372   c.setId(d_clauseIdNext++);
00373   FatalAssert(d_clauseIdNext != 0, "Overflow of clause id's");
00374 }
00375 
00376 
00377 Lit CNF_Manager::addAssumption(const Theorem& thm, CNF_Formula& cnf)
00378 {
00379   Lit l = translateExpr(thm.getExpr(), cnf);
00380   cnf.newClause();
00381   cnf.addLiteral(l);
00382   cnf.registerUnit();
00383 
00384   d_theorems[d_clauseIdNext] = thm;
00385   cnf.getCurrentClause().setId(d_clauseIdNext++);
00386   FatalAssert(d_clauseIdNext != 0, "Overflow of clause id's");
00387 
00388   return l;
00389 }
00390 
00391 
00392 Lit CNF_Manager::addLemma(const Theorem& thm, CNF_Formula& cnf)
00393 {
00394   Theorem clause = d_rules->learnedClause(thm);
00395 
00396   Lit l = translateExpr(clause.getExpr(), cnf);
00397   cnf.newClause();
00398   cnf.addLiteral(l);
00399   cnf.registerUnit();
00400 
00401   d_theorems.insert(d_clauseIdNext, clause);
00402   cnf.getCurrentClause().setId(d_clauseIdNext++);
00403   FatalAssert(d_clauseIdNext != 0, "Overflow of clause id's");
00404 
00405   return l;
00406 }

Generated on Thu Apr 13 16:57:30 2006 for CVC Lite by  doxygen 1.4.4