/*! @brief From T|- QUANTIFIER (vars): e we get T|-QUANTIFIER(vars') e * where vars' is obtained from vars by removing all bound variables * not used in e. If vars' is empty the produced theorem is just T|-e */ Theorem QuantTheoremProducer::boundVarElim(const Theorem& t1) { const Expr e=t1.getExpr(); const Expr body = e.getBody(); if(CHECK_PROOFS) { CHECK_SOUND(e.isForall() || e.isExists(), "bound var elimination: " +e.toString()); } ExprMap<bool> boundVars; //a mapping of bound variables in the body to true ExprMap<bool> visited; //to make sure expressions aren't traversed //multiple times recFindBoundVars(body, boundVars, visited); vector<Expr> quantVars; const vector<Expr>& origVars = e.getVars(); for(vector<Expr>::const_iterator it = origVars.begin(), iend=origVars.end(); it!=iend; ++it) { if(boundVars.count(*it) > 0) quantVars.push_back(*it); } // If all variables are used, just return the original theorem if(quantVars.size() == origVars.size()) return t1; Proof pf; if(withProof()) { vector<Expr> es; vector<Proof> pfs; es.push_back(e); es.insert(es.end(), quantVars.begin(), quantVars.end()); pfs.push_back(t1.getProof()); pf= newPf("bound_variable_elimination", es, pfs); } if(quantVars.size() == 0) return(newTheorem(e.getBody(), t1.getAssumptionsRef(), pf)); Expr newQuantExpr; if(e.isForall()) newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, quantVars, body); else newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(EXISTS, quantVars, body); return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf)); }
//!adjust the order of bound vars, newBvs begin first Theorem QuantTheoremProducer::adjustVarUniv(const Theorem& t1, const std::vector<Expr>& newBvs){ const Expr e=t1.getExpr(); const Expr body = e.getBody(); if(CHECK_PROOFS) { CHECK_SOUND(e.isForall(), "adjustVarUniv: " +e.toString()); } const vector<Expr>& origVars = e.getVars(); ExprMap<bool> oldmap; for(vector<Expr>::const_iterator it = origVars.begin(), iend=origVars.end(); it!=iend; ++it) { oldmap[*it]=true; } vector<Expr> quantVars; for(vector<Expr>::const_iterator it = newBvs.begin(), iend=newBvs.end(); it!=iend; ++it) { if(oldmap.count(*it) > 0) quantVars.push_back(*it); } if(quantVars.size() == origVars.size()) return t1; ExprMap<bool> newmap; for(vector<Expr>::const_iterator it = newBvs.begin(), iend=newBvs.end(); it!=iend; ++it) { newmap[*it]=true; } for(vector<Expr>::const_iterator it = origVars.begin(), iend=origVars.end(); it!=iend; ++it) { if(newmap.count(*it)<=0){ quantVars.push_back(*it); }; } Proof pf; if(withProof()) { vector<Expr> es; vector<Proof> pfs; es.push_back(e); es.insert(es.end(), quantVars.begin(), quantVars.end()); pfs.push_back(t1.getProof()); pf= newPf("adjustVarUniv", es, pfs); } Expr newQuantExpr; newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, quantVars, body); return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf)); }
Theorem QuantTheoremProducer::normalizeQuant(const Expr& quant) { if(CHECK_PROOFS) { CHECK_SOUND(quant.isForall()||quant.isExists(), "normalizeQuant: expr must be FORALL or EXISTS\n" +quant.toString()); } std::map<Expr,int>::iterator typeIter; std::string base("_BD"); int counter(0); vector<Expr> newVars; const std::vector<Expr>& cur_vars = quant.getVars(); for(size_t j =0; j<cur_vars.size(); j++){ Type t = cur_vars[j].getType(); int typeIndex ; typeIter = d_typeFound.find(t.getExpr()); if(d_typeFound.end() == typeIter){ typeIndex = d_typeFound.size(); d_typeFound[t.getExpr()] = typeIndex; } else{ typeIndex = typeIter->second; } counter++; std::stringstream stringType; stringType << counter << "TY" << typeIndex ; std::string out_str = base + stringType.str(); Expr newExpr = d_theoryQuant->getEM()->newBoundVarExpr(out_str, int2string(counter)); newExpr.setType(t); newVars.push_back(newExpr); } vector<vector<Expr> > trigs = quant.getTriggers(); for(size_t i = 0 ; i < trigs.size(); i++){ for(size_t j = 0 ; j < trigs[i].size(); j++){ trigs[i][j] = trigs[i][j].substExpr(cur_vars,newVars); } } Expr normBody = quant.getBody().substExpr(cur_vars,newVars); Expr normQuant = d_theoryQuant->getEM()->newClosureExpr(quant.isForall()?FORALL:EXISTS, newVars, normBody, trigs); Proof pf; if(withProof()) pf = newPf("normalizeQuant", quant, normQuant); return newRWTheorem(quant, normQuant, Assumptions::emptyAssump(), pf); }
Expr VCCmd::skolemizeAx(const Expr& e) { vector<Expr>vars; const vector<Expr>boundVars = e.getVars(); for(unsigned int i=0; i<boundVars.size(); i++) { Expr skolV(e.skolemExpr(i)); vars.push_back(skolV); } Expr sub = e.getBody().substExpr(boundVars, vars); return e.iffExpr(sub); }
//! find all bound variables in e and maps them to true in boundVars void QuantTheoremProducer::recFindBoundVars(const Expr& e, ExprMap<bool> & boundVars, ExprMap<bool> &visited) { if(visited.count(e)>0) return; else visited[e] = true; if(e.getKind() == BOUND_VAR) boundVars[e] = true; if(e.getKind() == EXISTS || e.getKind() == FORALL) recFindBoundVars(e.getBody(), boundVars, visited); for(Expr::iterator it = e.begin(); it!=e.end(); ++it) recFindBoundVars(*it, boundVars, visited); }
void VCCmd::findAxioms(const Expr& e, ExprMap<bool>& skolemAxioms, ExprMap<bool>& visited) { if(visited.count(e)>0) return; else visited[e] = true; if(e.isSkolem()) { skolemAxioms.insert(e.getExistential(), true); return; } if(e.isClosure()) { findAxioms(e.getBody(), skolemAxioms, visited); } if(e.arity()>0) { Expr::iterator end = e.end(); for(Expr::iterator i = e.begin(); i!=end; ++i) findAxioms(*i, skolemAxioms, visited); } }
//! convert (forall (x) ... forall (y)) into (forall (x y)...) //! convert (exists (x) ... exists (y)) into (exists (x y)...) Theorem QuantTheoremProducer::pullVarOut(const Theorem& t1){ const Expr thm_expr=t1.getExpr(); if(CHECK_PROOFS) { CHECK_SOUND(thm_expr.isForall() || thm_expr.isExists(), "pullVarOut: " +thm_expr.toString()); } const Expr outBody = thm_expr.getBody(); // if(((outBody.isAnd() && outBody[1].isForall()) || // (outBody.isImpl() && outBody[1].isForall()) || // (outBody.isNot() && outBody[0].isAnd() && outBody[0][1].isExists()) )){ // return t1; // } if (thm_expr.isForall()){ if((outBody.isNot() && outBody[0].isAnd() && outBody[0][1].isExists())){ vector<Expr> bVarsOut = thm_expr.getVars(); const Expr innerExists =outBody[0][1]; const Expr innerBody = innerExists.getBody(); vector<Expr> bVarsIn = innerExists.getVars(); for(vector<Expr>::iterator i=bVarsIn.begin(), iend=bVarsIn.end(); i!=iend; i++){ bVarsOut.push_back(*i); } Proof pf; if(withProof()) { vector<Expr> es; vector<Proof> pfs; es.push_back(thm_expr); es.insert(es.end(), bVarsIn.begin(), bVarsIn.end()); pfs.push_back(t1.getProof()); pf= newPf("pullVarOut", es, pfs); } Expr newbody; newbody=(outBody[0][0].notExpr()).orExpr(innerBody.notExpr()); Expr newQuantExpr; newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, bVarsOut, newbody); return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf)); } else if ((outBody.isAnd() && outBody[1].isForall()) || (outBody.isImpl() && outBody[1].isForall())){ vector<Expr> bVarsOut = thm_expr.getVars(); const Expr innerForall=outBody[1]; const Expr innerBody = innerForall.getBody(); vector<Expr> bVarsIn = innerForall.getVars(); for(vector<Expr>::iterator i=bVarsIn.begin(), iend=bVarsIn.end(); i!=iend; i++){ bVarsOut.push_back(*i); } Proof pf; if(withProof()) { vector<Expr> es; vector<Proof> pfs; es.push_back(thm_expr); es.insert(es.end(), bVarsIn.begin(), bVarsIn.end()); pfs.push_back(t1.getProof()); pf= newPf("pullVarOut", es, pfs); } Expr newbody; if(outBody.isAnd()){ newbody=outBody[0].andExpr(innerBody); } else if(outBody.isImpl()){ newbody=outBody[0].impExpr(innerBody); } Expr newQuantExpr; newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, bVarsOut, newbody); return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf)); } return t1; // case cannot be handled now. } else if (thm_expr.isExists()){ if ((outBody.isAnd() && outBody[1].isExists()) || (outBody.isImpl() && outBody[1].isExists())){ vector<Expr> bVarsOut = thm_expr.getVars(); const Expr innerExists = outBody[1]; const Expr innerBody = innerExists.getBody(); vector<Expr> bVarsIn = innerExists.getVars(); for(vector<Expr>::iterator i=bVarsIn.begin(), iend=bVarsIn.end(); i!=iend; i++){ bVarsOut.push_back(*i); } Proof pf; if(withProof()) { vector<Expr> es; vector<Proof> pfs; es.push_back(thm_expr); es.insert(es.end(), bVarsIn.begin(), bVarsIn.end()); pfs.push_back(t1.getProof()); pf= newPf("pullVarOut", es, pfs); } Expr newbody; if(outBody.isAnd()){ newbody=outBody[0].andExpr(innerBody); } else if(outBody.isImpl()){ newbody=outBody[0].impExpr(innerBody); } Expr newQuantExpr; newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(EXISTS, bVarsOut, newbody); return(newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf)); } } return t1; }
Theorem QuantTheoremProducer::partialUniversalInst(const Theorem& t1, const vector<Expr>& terms, int quantLevel){ cout<<"error in partial inst" << endl; Expr e = t1.getExpr(); const vector<Expr>& boundVars = e.getVars(); if(CHECK_PROOFS) { CHECK_SOUND(boundVars.size() >= terms.size(), "Universal instantiation: size of terms array does " "not match quanitfied variables array size"); CHECK_SOUND(e.isForall(), "universal instantiation: expr must be FORALL:\n" +e.toString()); for(unsigned int i=0; i<terms.size(); i++){ CHECK_SOUND(d_theoryQuant->getBaseType(boundVars[i]) == d_theoryQuant->getBaseType(terms[i]), "partial Universal instantiation: type mismatch"); } } //build up a conjunction of type predicates for expression Expr tr = e.getEM()->trueExpr(); Expr typePred = tr; for(unsigned int i=0; i<terms.size(); i++) { Expr p = d_theoryQuant->getTypePred(boundVars[i].getType(),terms[i]); if(p!=tr) { if(typePred==tr) typePred = p; else typePred = typePred.andExpr(p); } } Proof pf; if(withProof()) { vector<Proof> pfs; vector<Expr> es; pfs.push_back(t1.getProof()); es.push_back(e); es.insert(es.end(), terms.begin(), terms.end()); pf= newPf("partial_universal_instantiation", es, pfs); } if(terms.size() == boundVars.size()){ Expr inst = e.getBody().substExpr(e.getVars(), terms); Expr imp; if(typePred == tr) imp = inst; else imp = typePred.impExpr(inst); return(newTheorem(imp, t1.getAssumptionsRef(), pf)); } else{ vector<Expr> newBoundVars; for(size_t i=0; i<terms.size(); i++) { newBoundVars.push_back(boundVars[i]); } vector<Expr>leftBoundVars; for(size_t i=terms.size(); i<boundVars.size(); i++) { leftBoundVars.push_back(boundVars[i]); } Expr tempinst = e.getBody().substExpr(newBoundVars, terms); Expr inst = d_theoryQuant->getEM()->newClosureExpr(FORALL, leftBoundVars, tempinst); Expr imp; if(typePred == tr) imp = inst; else imp = typePred.impExpr(inst); Theorem res = (newTheorem(imp, t1.getAssumptionsRef(), pf)); int thmLevel = t1.getQuantLevel(); if(quantLevel >= thmLevel) { res.setQuantLevel(quantLevel+1); } else{ //k ret.setQuantLevel(thmLevel+1); res.setQuantLevel(thmLevel); } return res; } }
Theorem QuantTheoremProducer::universalInst(const Theorem& t1, const vector<Expr>& terms){ Expr e = t1.getExpr(); const vector<Expr>& boundVars = e.getVars(); if(CHECK_PROOFS) { CHECK_SOUND(boundVars.size() == terms.size(), "Universal instantiation: size of terms array does " "not match quanitfied variables array size"); CHECK_SOUND(e.isForall(), "universal instantiation: expr must be FORALL:\n" +e.toString()); for(unsigned int i=0; i<terms.size(); i++) CHECK_SOUND(d_theoryQuant->getBaseType(boundVars[i]) == d_theoryQuant->getBaseType(terms[i]), "Universal instantiation: type mismatch"); } //build up a conjunction of type predicates for expression Expr tr = e.getEM()->trueExpr(); Expr typePred = tr; unsigned qlevel=0, qlevelMax = 0; for(unsigned int i=0; i<terms.size(); i++) { Expr p = d_theoryQuant->getTypePred(boundVars[i].getType(),terms[i]); if(p!=tr) { if(typePred==tr) typePred = p; else typePred = typePred.andExpr(p); } qlevel = d_theoryQuant->theoryCore()->getQuantLevelForTerm(terms[i]); if (qlevel > qlevelMax) qlevel = qlevelMax; } Expr inst = e.getBody().substExpr(e.getVars(), terms); // Expr inst = e.getBody().substExprQuant(e.getVars(), terms); // Expr inst = e.getBody().substExpr(e.getVars(), terms); Proof pf; if(withProof()) { vector<Proof> pfs; vector<Expr> es; pfs.push_back(t1.getProof()); es.push_back(e); es.push_back(Expr(RAW_LIST,terms)); // es.insert(es.end(), terms.begin(), terms.end()); es.push_back(inst); pf= newPf("universal_elimination3", es, pfs); } // Expr inst = e.getBody().substExpr(e.getVars(), terms); Expr imp; if( typePred == tr ) //just for easy life, yeting, change this asap imp = inst; else imp = typePred.impExpr(inst); Theorem ret = newTheorem(imp, t1.getAssumptionsRef(), pf); unsigned thmLevel = t1.getQuantLevel(); if(qlevel >= thmLevel) { ret.setQuantLevel(qlevel+1); } else{ // ret.setQuantLevel(thmLevel+1); ret.setQuantLevel(thmLevel+1); } // ret.setQuantLevel(qlevel+1); return ret; }