theory_datatype_lazy.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  *\file theory_datatype_lazy.cpp
00004  *
00005  * Author: Clark Barrett
00006  *
00007  * Created: Wed Dec  1 22:32:26 2004
00008  *
00009  * <hr>
00010  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00011  * Junior University and by New York University. 
00012  *
00013  * License to use, copy, modify, sell and/or distribute this software
00014  * and its documentation for any purpose is hereby granted without
00015  * royalty, subject to the terms and conditions defined in the \ref
00016  * LICENSE file provided with this distribution.  In particular:
00017  *
00018  * - The above copyright notice and this permission notice must appear
00019  * in all copies of the software and related documentation.
00020  *
00021  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00022  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00023  * 
00024  * <hr>
00025  * 
00026  */
00027 /*****************************************************************************/
00028 
00029 
00030 #include "theory_datatype_lazy.h"
00031 #include "datatype_proof_rules.h"
00032 #include "typecheck_exception.h"
00033 #include "parser_exception.h"
00034 #include "smtlib_exception.h"
00035 #include "theory_core.h"
00036 #include "theory_uf.h"
00037 #include "command_line_flags.h"
00038 
00039 
00040 using namespace std;
00041 using namespace CVCL;
00042 
00043 
00044 ///////////////////////////////////////////////////////////////////////////////
00045 // TheoryDatatypeLazy Public Methods                                             //
00046 ///////////////////////////////////////////////////////////////////////////////
00047 
00048 
00049 TheoryDatatypeLazy::TheoryDatatypeLazy(TheoryCore* core)
00050   : TheoryDatatype(core),
00051     d_processQueue(core->getCM()->getCurrentContext()),
00052     d_processQueueKind(core->getCM()->getCurrentContext()),
00053     d_processIndex(core->getCM()->getCurrentContext(), 0),
00054     d_typeComplete(core->getCM()->getCurrentContext(), false)
00055 { }
00056 
00057 
00058 void TheoryDatatypeLazy::instantiate(const Expr& e, const bigunsigned& u)
00059 {
00060   DebugAssert(e.hasFind() && findExpr(e) == e,
00061               "datatype: instantiate: Expected find(e)=e");
00062   if (isConstructor(e) || e.isTranslated()) return;
00063   DebugAssert(u != 0 && (u & (u-1)) == 0,
00064               "datatype: instantiate: Expected single label in u");
00065   DebugAssert(d_datatypes.find(e.getType().getExpr()) != d_datatypes.end(),
00066               "datatype: instantiate: Unexpected type: "+e.getType().toString()
00067               +"\n\n for expression: "+e.toString());
00068   ExprMap<unsigned>& c = d_datatypes[e.getType().getExpr()];
00069   ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00070   for (; c_it != c_end; ++c_it) {
00071     if (u & (1 << bigunsigned((*c_it).second))) break;
00072   }
00073   DebugAssert(c_it != c_end,
00074               "datatype: instantiate: couldn't find constructor");
00075   Expr cons = (*c_it).first;
00076 
00077   if (!cons.isFinite() && !e.isSelected()) return;
00078 
00079   Type consType = cons.getType();
00080   if (consType.arity() == 1) {
00081     d_processQueue.push_back(d_rules->dummyTheorem(d_facts, e.eqExpr(cons)));
00082     d_processQueueKind.push_back(ENQUEUE);
00083     return;
00084   }
00085   // create vars
00086   vector<Expr> vars;
00087   for (int i = 0; i < consType.arity()-1; ++i) {
00088     vars.push_back(getEM()->newBoundVarExpr(consType[i]));
00089   }
00090   Expr e2 = getEM()->newClosureExpr(EXISTS, vars,
00091                                     e.eqExpr(Expr(cons.mkOp(), vars)));
00092   d_processQueue.push_back(d_rules->dummyTheorem(d_facts, e2));
00093   d_processQueueKind.push_back(ENQUEUE);
00094   e.setTranslated();
00095 }
00096 
00097 
00098 void TheoryDatatypeLazy::initializeLabels(const Expr& e, const Type& t)
00099 {
00100   DebugAssert(findExpr(e) == e,
00101               "datatype: initializeLabels: Expected find(e)=e");
00102   DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
00103               "Unknown datatype: "+t.getExpr().toString());
00104   ExprMap<unsigned>& c = d_datatypes[t.getExpr()];
00105   DebugAssert(d_labels.find(e) == d_labels.end(),
00106               "datatype: initializeLabels: expected unlabeled expr");
00107   if (isConstructor(e)) {
00108     Expr cons = getConstructor(e);
00109     DebugAssert(c.find(cons) != c.end(),
00110                 "datatype: initializeLabels: Couldn't find constructor "
00111                 +cons.toString());
00112     bigunsigned position = c[cons];
00113     d_labels.insert(e,
00114       SmartCDO<bigunsigned>(theoryCore()->getCM()->getCurrentContext(),
00115                             1 << position, 0));
00116   }
00117   else {
00118     DebugAssert(c.size() > 0, "No constructors?");
00119     bigunsigned value = (1 << bigunsigned(c.size())) - 1;
00120     d_labels.insert(e,
00121       SmartCDO<bigunsigned>(theoryCore()->getCM()->getCurrentContext(),
00122                             value, 0));
00123     if (value == 1) instantiate(e, 1);
00124     else if (!d_typeComplete) {
00125       d_splitters.push_back(e);
00126     }
00127   }
00128 }
00129 
00130 
00131 void TheoryDatatypeLazy::mergeLabels(const Theorem& thm,
00132                                  const Expr& e1, const Expr& e2)
00133 {
00134   DebugAssert(e2.hasFind(),
00135               "datatype: mergeLabels: Expected hasFind(e2)");
00136   Theorem fthm = find(e2);
00137   const Expr& f = fthm.getRHS();
00138   DebugAssert(d_labels.find(e1) != d_labels.end() &&
00139               d_labels.find(f) != d_labels.end(),
00140               "mergeLabels: expr is not labeled");
00141   DebugAssert(e1.getType() == f.getType(), "Expected same type");
00142   bigunsigned u = d_labels[f].get().get();
00143   bigunsigned uNew = u & d_labels[e1].get().get();
00144   if (u != uNew) {
00145     if (e2 != f) d_facts.push_back(fthm);
00146     if (!thm.isNull()) d_facts.push_back(thm);
00147     d_labels[f].get().set(uNew);
00148     if (uNew == 0) {
00149       setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr()));
00150       return;
00151     }
00152   }
00153   if (uNew != 0 && ((uNew - 1) & uNew) == 0) {
00154     instantiate(f, uNew);
00155   }
00156 }
00157 
00158 
00159 void TheoryDatatypeLazy::mergeLabels(const Theorem& thm, const Expr& e,
00160                                  unsigned position, bool positive)
00161 {
00162   DebugAssert(e.hasFind(),
00163               "datatype: mergeLabels2: Expected hasFind(e)");
00164   Theorem fthm = find(e);
00165   const Expr& f = fthm.getRHS();
00166   DebugAssert(d_labels.find(f) != d_labels.end(),
00167               "mergeLabels2: expr is not labeled");
00168   bigunsigned u = d_labels[f].get().get();
00169   bigunsigned uNew = 1 << bigunsigned(position);
00170   if (positive) {
00171     uNew = u & uNew;
00172     if (u == uNew) return;
00173   } else if (u & uNew) uNew = u - uNew;
00174   else return;
00175   if (e != f) d_facts.push_back(fthm);
00176   d_facts.push_back(thm);
00177   d_labels[f].get().set(uNew);
00178   if (uNew == 0)
00179     setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr()));
00180   else if (((uNew - 1) & uNew) == 0) {
00181     instantiate(f, uNew);
00182   }
00183 }
00184 
00185 
00186 void TheoryDatatypeLazy::checkSat(bool fullEffort)
00187 {
00188   bool done = false;
00189   while (!done && d_splittersIndex < d_splitters.size()) {
00190     Expr e = d_splitters[d_splittersIndex];
00191     if (findExpr(e) == e) {
00192       DebugAssert(d_labels.find(e) != d_labels.end(),
00193                   "checkSat: expr is not labeled");
00194       bigunsigned u = d_labels[e].get().get();
00195       if ((u & (u-1)) != 0) {
00196         done = true;
00197         DebugAssert(!d_splitterAsserted || !fullEffort,
00198                     "splitter should have been resolved");
00199         if (!d_splitterAsserted) {
00200           DebugAssert
00201             (d_datatypes.find(e.getType().getExpr()) != d_datatypes.end(),
00202              "datatype: checkSat: Unexpected type: "+e.getType().toString()
00203              +"\n\n for expression: "+e.toString());
00204           ExprMap<unsigned>& c = d_datatypes[e.getType().getExpr()];
00205           ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00206           for (; c_it != c_end; ++c_it) {
00207             if (u & (1 << bigunsigned((*c_it).second))) break;
00208           }
00209           DebugAssert(c_it != c_end,
00210               "datatype: checkSat: couldn't find constructor");
00211           addSplitter(datatypeTestExpr((*c_it).first.getName(), e));
00212           d_splitterAsserted = true;
00213         }
00214       }
00215     }
00216     if (!done) {
00217       d_splitterAsserted = false;
00218       d_splittersIndex = d_splittersIndex + 1;
00219     }
00220   }
00221   while (!done && d_processIndex < d_processQueue.size()) {
00222     d_typeComplete = true;
00223     Theorem e = d_processQueue[d_processIndex];
00224     int kind = d_processQueueKind[d_processIndex];
00225     switch (kind) {
00226       case MERGE1: {
00227         break;
00228       }
00229       case ENQUEUE:
00230         done = true;
00231         enqueueFact(e);
00232         break;
00233       case MERGE2: {
00234         const Expr& lhs = e.getLHS();
00235         const Expr& rhs = e.getRHS();
00236         Theorem thm(e);
00237         if (lhs.isSelected() && !rhs.isSelected()) {
00238           d_facts.push_back(e);
00239           rhs.setSelected();
00240           thm = Theorem();
00241         }
00242         mergeLabels(thm, lhs, rhs);
00243         break;
00244       }
00245       default:
00246         DebugAssert(false, "Unknown case");
00247     }
00248     d_processIndex = d_processIndex + 1;
00249   }
00250 }
00251 
00252 
00253 
00254 void TheoryDatatypeLazy::setup(const Expr& e)
00255 {
00256   if (e.getType().getExpr().getKind() == DATATYPE &&
00257       d_labels.find(e) == d_labels.end()) {
00258     initializeLabels(e, e.getType());
00259     e.addToNotify(this, Expr());
00260   }
00261   if (e.getKind() != APPLY) return;
00262   if (isConstructor(e) && e.arity() > 0) {
00263     d_processQueue.push_back(d_rules->noCycle(e));
00264     d_processQueueKind.push_back(ENQUEUE);
00265   }
00266   if (isSelector(e)) {
00267     e[0].setSelected();
00268     d_processQueue.push_back(reflexivityRule(e[0]));
00269     d_processQueueKind.push_back(MERGE2);
00270   }
00271   setupCC(e);
00272 }
00273 
00274 
00275 void TheoryDatatypeLazy::update(const Theorem& e, const Expr& d)
00276 {
00277   if (d.isNull()) {
00278     const Expr& lhs = e.getLHS();
00279     const Expr& rhs = e.getRHS();
00280     if (isConstructor(lhs) && isConstructor(rhs) &&
00281         lhs.isApply() && rhs.isApply() &&
00282         lhs.getOpExpr() == rhs.getOpExpr()) {
00283       d_processQueue.push_back(d_rules->decompose(e));
00284       d_processQueueKind.push_back(ENQUEUE);
00285     }
00286     else {
00287       d_processQueue.push_back(e);
00288       d_processQueueKind.push_back(MERGE2);
00289     }
00290   }
00291   else {
00292     const Theorem& dEQdsig = d.getSig();
00293     if (!dEQdsig.isNull()) {
00294       const Expr& dsig = dEQdsig.getRHS();
00295       Theorem thm = updateHelper(d);
00296       const Expr& sigNew = thm.getRHS();
00297       if (sigNew == dsig) return;
00298       dsig.setRep(Theorem());
00299       if (isSelector(sigNew) && canCollapse(sigNew)) {
00300         d.setSig(Theorem());
00301         d_processQueue.push_back(transitivityRule(thm, d_rules->rewriteSelCons(d_facts, sigNew)));
00302         d_processQueueKind.push_back(ENQUEUE);
00303       }
00304       else if (isTester(sigNew) && isConstructor(sigNew[0])) {
00305         d.setSig(Theorem());
00306         d_processQueue.push_back(transitivityRule(thm, d_rules->rewriteTestCons(sigNew)));
00307         d_processQueueKind.push_back(ENQUEUE);
00308       }
00309       else {
00310         const Theorem& repEQsigNew = sigNew.getRep();
00311         if (!repEQsigNew.isNull()) {
00312           d.setSig(Theorem());
00313           d_processQueue.push_back(transitivityRule(repEQsigNew, symmetryRule(thm)));
00314           d_processQueueKind.push_back(ENQUEUE);
00315         }
00316         else {
00317           int k, ar(d.arity());
00318           for (k = 0; k < ar; ++k) {
00319             if (sigNew[k] != dsig[k]) {
00320               sigNew[k].addToNotify(this, d);
00321             }
00322           }
00323           d.setSig(thm);
00324           sigNew.setRep(thm);
00325         }
00326       }
00327     }
00328   }
00329 }

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