//!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 CNF_Manager::replaceITErec(const Expr& e, Var v, bool translateOnly) { // Quick exit for atomic expressions if (e.isAtomic()) return d_commonRules->reflexivityRule(e); // Check cache Theorem thm; bool foundInCache = false; ExprHashMap<Theorem>::iterator iMap = d_iteMap.find(e); if (iMap != d_iteMap.end()) { thm = (*iMap).second; foundInCache = true; } if (e.getKind() == ITE) { // Replace non-Bool ITE expressions DebugAssert(!e.getType().isBool(), "Expected non-Bool ITE"); // generate e = x for new x if (!foundInCache) thm = d_commonRules->varIntroSkolem(e); Theorem thm2 = d_commonRules->symmetryRule(thm); thm2 = d_commonRules->iffMP(thm2, d_rules->ifLiftRule(thm2.getExpr(), 1)); d_translateQueueVars.push_back(v); d_translateQueueThms.push_back(thm2); d_translateQueueFlags.push_back(translateOnly); } else { // Recursively traverse, replacing ITE's vector<Theorem> thms; vector<unsigned> changed; unsigned index = 0; Expr::iterator i, iend; if (foundInCache) { for(i = e.begin(), iend = e.end(); i!=iend; ++i, ++index) { replaceITErec(*i, v, translateOnly); } } else { for(i = e.begin(), iend = e.end(); i!=iend; ++i, ++index) { thm = replaceITErec(*i, v, translateOnly); if (!thm.isRefl()) { thms.push_back(thm); changed.push_back(index); } } if(changed.size() > 0) { thm = d_commonRules->substitutivityRule(e, changed, thms); } else thm = d_commonRules->reflexivityRule(e); } } // Update cache and return if (!foundInCache) d_iteMap[e] = thm; return thm; }
/*! @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)); }
//!pack (forall (x) forall (y)) into (forall (x y)) Theorem QuantTheoremProducer::packVar(const Theorem& t1){ Expr out_forall =t1.getExpr(); if(CHECK_PROOFS) { CHECK_SOUND(out_forall.isForall(), "packVar: " +out_forall.toString()); } vector<Expr> bVars = out_forall.getVars(); if(!out_forall.getBody().isForall()){ return t1; } Expr cur_body = out_forall.getBody(); while(cur_body.isForall()){ vector<Expr> bVarsLeft = cur_body.getVars(); for(vector<Expr>::iterator i=bVarsLeft.begin(), iend=bVarsLeft.end(); i!=iend; i++){ bVars.push_back(*i); } cur_body=cur_body.getBody(); } Proof pf; if(withProof()) { vector<Expr> es; vector<Proof> pfs; es.push_back(out_forall); es.insert(es.end(), bVars.begin(), bVars.end()); pfs.push_back(t1.getProof()); pf= newPf("packVar", es, pfs); } Expr newQuantExpr; newQuantExpr = d_theoryQuant->getEM()->newClosureExpr(FORALL, bVars, cur_body); return (newTheorem(newQuantExpr, t1.getAssumptionsRef(), pf)); // return (newRWTheorem(t1,newQuantExpr, t1.getAssumptionsRef(), pf)); }
Theorem TheoryArith::canonRec(const Expr& e) { if (isLeaf(e)) return reflexivityRule(e); int ar = e.arity(); if (ar > 0) { vector<Theorem> newChildrenThm; vector<unsigned> changed; for(int k = 0; k < ar; ++k) { // Recursively canonize the kids Theorem thm = canonRec(e[k]); if (thm.getLHS() != thm.getRHS()) { newChildrenThm.push_back(thm); changed.push_back(k); } } if(changed.size() > 0) { return canonThm(substitutivityRule(e, changed, newChildrenThm)); } } return canon(e); }
Lit CNF_Manager::translateExpr(const Theorem& thmIn, CNF_Formula& cnf) { Lit l; Var v; Expr e = thmIn.getExpr(); Theorem thm; bool translateOnly; Lit ret = translateExprRec(e, cnf, thmIn); while (d_translateQueueVars.size()) { v = d_translateQueueVars.front(); d_translateQueueVars.pop_front(); thm = d_translateQueueThms.front(); d_translateQueueThms.pop_front(); translateOnly = d_translateQueueFlags.front(); d_translateQueueFlags.pop_front(); l = translateExprRec(thm.getExpr(), cnf, thmIn); cnf.newClause(); cnf.addLiteral(l); cnf.registerUnit(); Theorem newThm = d_rules->CNFAddUnit(thm); // d_theorems.insert(d_clauseIdNext, thm); // cnf.getCurrentClause().setClauseTheorem(thmIn); // by yeting cnf.getCurrentClause().setClauseTheorem(newThm); // by yeting /* cout<<"set clause theorem 1" << thm << endl; cout<<"set clause theorem 2 " << thmIn << endl; cout<<"set clause print" ; cnf.getCurrentClause().print() ; cout<<endl; cout<<"set clause id " << d_clauseIdNext << endl; */ if (!translateOnly) d_varInfo[v].fanins.push_back(l); d_varInfo[l.getVar()].fanouts.push_back(v); } return ret; }
Theorem TheoryArith::canonSimp(const Expr& e) { DebugAssert(canonRec(e).getRHS() == e, "canonSimp expects input to be canonized"); int ar = e.arity(); if (isLeaf(e)) return find(e); if (ar > 0) { vector<Theorem> newChildrenThm; vector<unsigned> changed; Theorem thm; for (int k = 0; k < ar; ++k) { thm = canonSimp(e[k]); if (thm.getLHS() != thm.getRHS()) { newChildrenThm.push_back(thm); changed.push_back(k); } } if(changed.size() > 0) { thm = canonThm(substitutivityRule(e, changed, newChildrenThm)); return transitivityRule(thm, find(thm.getRHS())); } else return find(e); } return find(e); }
//! 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; }
Lit CNF_Manager::translateExprRec(const Expr& e, CNF_Formula& cnf, const Theorem& thmIn) { if (e.isFalse()) return Lit::getFalse(); if (e.isTrue()) return Lit::getTrue(); if (e.isNot()) return !translateExprRec(e[0], cnf, thmIn); ExprHashMap<Var>::iterator iMap = d_cnfVars.find(e); if (e.isTranslated()) { DebugAssert(iMap != d_cnfVars.end(), "Translated expr should be in map"); return Lit((*iMap).second); } else e.setTranslated(d_bottomScope); Var v(int(d_varInfo.size())); bool translateOnly = false; if (iMap != d_cnfVars.end()) { v = (*iMap).second; translateOnly = true; d_varInfo[v].fanouts.clear(); } else { d_varInfo.resize(v+1); d_varInfo.back().expr = e; d_cnfVars[e] = v; } Expr::iterator i, iend; bool isAnd = false; switch (e.getKind()) { case AND: isAnd = true; case OR: { vector<Lit> lits; unsigned idx; for (i = e.begin(), iend = e.end(); i != iend; ++i) { lits.push_back(translateExprRec(*i, cnf, thmIn)); } // DebugAssert(concreteExpr(e,Lit(v)) == e,"why here"); for (idx = 0; idx < lits.size(); ++idx) { cnf.newClause(); cnf.addLiteral(Lit(v),isAnd); cnf.addLiteral(lits[idx], !isAnd); // DebugAssert(concreteExpr(e[idx],lits[idx]) == e[idx], "why here"); std::string reasonStr = (isAnd ? "and_mid" : "or_mid"); Expr after = e[idx] ; cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, after, reasonStr, idx)); // by yeting } cnf.newClause(); cnf.addLiteral(Lit(v),!isAnd); for (idx = 0; idx < lits.size(); ++idx) { cnf.addLiteral(lits[idx], isAnd); } std::string reasonStr = (isAnd ? "and_final" : "or_final") ; Expr after = e ; cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, after, reasonStr, 0)); // by yeting break; } case IMPLIES: { Lit arg0 = translateExprRec(e[0], cnf, thmIn); Lit arg1 = translateExprRec(e[1], cnf, thmIn); // DebugAssert(concreteExpr(e, Lit(v)) == e, "why here"); // DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here"); // DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here"); cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0); cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 0)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 1)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 2)); // by yeting break; } case IFF: { Lit arg0 = translateExprRec(e[0], cnf, thmIn); Lit arg1 = translateExprRec(e[1], cnf, thmIn); // DebugAssert(concreteExpr(e, Lit(v)) == e, "why here"); // DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here"); // DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here"); cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 0)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 1)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 2)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 3)); // by yeting break; } case XOR: { Lit arg0 = translateExprRec(e[0], cnf, thmIn); Lit arg1 = translateExprRec(e[1], cnf, thmIn); // DebugAssert(concreteExpr(e, Lit(v)) == e, "why here"); // DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here"); // DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here"); cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 0)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 1)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 2)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 3)); // by yeting break; } case ITE: { Lit arg0 = translateExprRec(e[0], cnf, thmIn); Lit arg1 = translateExprRec(e[1], cnf, thmIn); Lit arg2 = translateExprRec(e[2], cnf, thmIn); Expr aftere0 = concreteExpr(e[0], arg0); Expr aftere1 = concreteExpr(e[1], arg1); Expr aftere2 = concreteExpr(e[2], arg2); vector<Expr> after ; after.push_back(aftere0); after.push_back(aftere1); after.push_back(aftere2); Theorem e0thm; Theorem e1thm; Theorem e2thm; { e0thm = d_iteMap[e[0]]; if (e0thm.isNull()) e0thm = d_commonRules->reflexivityRule(e[0]); e1thm = d_iteMap[e[1]]; if (e1thm.isNull()) e1thm = d_commonRules->reflexivityRule(e[1]); e2thm = d_iteMap[e[2]]; if (e2thm.isNull()) e2thm = d_commonRules->reflexivityRule(e[2]); } vector<Theorem> thms ; thms.push_back(e0thm); thms.push_back(e1thm); thms.push_back(e2thm); cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0); cnf.addLiteral(arg2); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 1)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0); cnf.addLiteral(arg2,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 2)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 3)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 4)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg1,true); cnf.addLiteral(arg2,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 5)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg1); cnf.addLiteral(arg2); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 6)); // by yeting break; } default: { DebugAssert(!e.isAbsAtomicFormula() || d_varInfo[v].expr == e, "Corrupted Varinfo"); if (e.isAbsAtomicFormula()) { registerAtom(e, thmIn); return Lit(v); } Theorem thm = replaceITErec(e, v, translateOnly); const Expr& e2 = thm.getRHS(); DebugAssert(e2.isAbsAtomicFormula(), "Expected AbsAtomicFormula"); if (e2.isTranslated()) { // Ugly corner case: we happen to create an expression that has been // created before. We remove the current variable and fix up the // translation stack. if (translateOnly) { DebugAssert(v == d_cnfVars[e2], "Expected literal match"); } else { d_varInfo.resize(v); while (!d_translateQueueVars.empty() && d_translateQueueVars.back() == v) { d_translateQueueVars.pop_back(); } DebugAssert(d_cnfVars.find(e2) != d_cnfVars.end(), "Expected existing literal"); v = d_cnfVars[e2]; d_cnfVars[e] = v; while (d_translateQueueVars.size() < d_translateQueueThms.size()) { d_translateQueueVars.push_back(v); } } } else { e2.setTranslated(d_bottomScope); // Corner case: don't register reflexive equality if (!e2.isEq() || e2[0] != e2[1]) registerAtom(e2, thmIn); if (!translateOnly) { if (d_cnfVars.find(e2) == d_cnfVars.end()) { d_varInfo[v].expr = e2; d_cnfVars[e2] = v; } else { // Same corner case in an untranslated expr d_varInfo.resize(v); while (!d_translateQueueVars.empty() && d_translateQueueVars.back() == v) { d_translateQueueVars.pop_back(); } v = d_cnfVars[e2]; d_cnfVars[e] = v; while (d_translateQueueVars.size() < d_translateQueueThms.size()) { d_translateQueueVars.push_back(v); } } } } return Lit(v); } } // Record fanins / fanouts Lit l; for (i = e.begin(), iend = e.end(); i != iend; ++i) { l = getCNFLit(*i); DebugAssert(!l.isNull(), "Expected non-null literal"); if (!translateOnly) d_varInfo[v].fanins.push_back(l); if (l.isVar()) d_varInfo[l.getVar()].fanouts.push_back(v); } return Lit(v); }
void TheoryUF::assertFact(const Theorem& e) { const Expr& expr = e.getExpr(); switch (expr.getKind()) { case NOT: break; case APPLY: if (expr.getOpExpr().computeTransClosure()) { enqueueFact(d_rules->relToClosure(e)); } else if (expr.getOpKind() == TRANS_CLOSURE) { // const Expr& rel = expr.getFun(); DebugAssert(expr.isApply(), "Should be apply"); Expr rel = resolveID(expr.getOpExpr().getName()); DebugAssert(!rel.isNull(), "Expected known identifier"); DebugAssert(rel.isSymbol() && rel.getKind()==UFUNC && expr.arity()==2, "Unexpected use of transitive closure: "+expr.toString()); // Insert into transitive closure table ExprMap<TCMapPair*>::iterator i = d_transClosureMap.find(rel); TCMapPair* pTable; if (i == d_transClosureMap.end()) { pTable = new TCMapPair(); d_transClosureMap[rel] = pTable; } else { pTable = (*i).second; } ExprMap<CDList<Theorem>*>::iterator i2 = pTable->appearsFirstMap.find(expr[0]); CDList<Theorem>* pList; if (i2 == pTable->appearsFirstMap.end()) { pList = new(true) CDList<Theorem>(theoryCore()->getCM()->getCurrentContext()); pTable->appearsFirstMap[expr[0]] = pList; } else { pList = (*i2).second; } pList->push_back(e); i2 = pTable->appearsSecondMap.find(expr[1]); if (i2 == pTable->appearsSecondMap.end()) { pList = new(true) CDList<Theorem>(theoryCore()->getCM()->getCurrentContext()); pTable->appearsSecondMap[expr[1]] = pList; } else { pList = (*i2).second; } pList->push_back(e); // Compute transitive closure with existing relations size_t s,l; i2 = pTable->appearsFirstMap.find(expr[1]); if (i2 != pTable->appearsFirstMap.end()) { pList = (*i2).second; s = pList->size(); for (l = 0; l < s; ++l) { enqueueFact(d_rules->relTrans(e,(*pList)[l])); } } i2 = pTable->appearsSecondMap.find(expr[0]); if (i2 != pTable->appearsSecondMap.end()) { pList = (*i2).second; s = pList->size(); for (l = 0; l < s; ++l) { enqueueFact(d_rules->relTrans((*pList)[l],e)); } } } break; default: break; } }