00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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 }