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 #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
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
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
00089
00090
00091
00092
00093
00094
00095
00096
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
00110
00111
00112
00113 }
00114
00115
00116 Expr tr = e.getEM()->trueExpr();
00117 Expr typePred = tr;
00118
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
00128
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
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
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
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
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
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
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
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();
00486 }
00487
00488
00489
00490
00491
00492
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;
00504 ExprMap<bool> visited;
00505
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
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 }