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; }
// For debugging: there are missing cases: user-defined types, symbols inside of quantifiers, etc. void VCCmd::printSymbols(Expr e, ExprMap<bool>& cache) { if (cache.find(e) != cache.end()) return; switch (e.getKind()) { case SKOLEM_VAR: case UCONST: { cout << e << " : "; ExprStream os(d_vc->getEM()); os.dagFlag(false); os << e.getType().getExpr(); cout << ";" << endl; break; } case APPLY: { Expr op = e.getOpExpr(); if ((op.getKind() == UFUNC) && (cache.find(op) == cache.end())) { cout << op << " : "; ExprStream os(d_vc->getEM()); os.dagFlag(false); os << op.getType().getExpr(); cout << ";" << endl; cache[op] = true; } // fall through } default: { Expr::iterator i = e.begin(), iend = e.end(); for (; i != iend; ++i) { printSymbols(*i, cache); } break; } } cache[e] = true; }
void Tptp::checkLetBinding(const std::vector<Expr>& bvlist, Expr lhs, Expr rhs, bool formula) { if (lhs.getKind() != CVC4::kind::APPLY_UF) { parseError("malformed let: LHS must be a flat function application"); } const std::multiset<CVC4::Expr> vars{lhs.begin(), lhs.end()}; if(formula && !lhs.getType().isBoolean()) { parseError("malformed let: LHS must be formula"); } for (const CVC4::Expr& var : vars) { if (var.hasOperator()) { parseError("malformed let: LHS must be flat, illegal child: " + var.toString()); } } // ensure all let-bound variables appear on the LHS, and appear only once for (const Expr& bound_var : bvlist) { const size_t count = vars.count(bound_var); if (count == 0) { parseError( "malformed let: LHS must make use of all quantified variables, " "missing `" + bound_var.toString() + "'"); } else if (count >= 2) { parseError("malformed let: LHS cannot use same bound variable twice: " + bound_var.toString()); } } }
void CNF_Manager::convertLemma(const Theorem& thm, CNF_Formula& cnf) { DebugAssert(cnf.empty(), "Expected empty cnf"); vector<Theorem> clauses; d_rules->learnedClauses(thm, clauses, false); vector<Theorem>::iterator i = clauses.begin(), iend = clauses.end(); for (; i < iend; ++i) { // for dumping lemmas: // cerr << "QUERY " << (*i).getExpr() << ";" << endl; cnf.newClause(); Expr e = (*i).getExpr(); if (!e.isOr()) { DebugAssert(!getCNFLit(e).isNull(), "Unknown literal"); cnf.addLiteral(getCNFLit(e)); cnf.registerUnit(); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFAddUnit(*i)); } else { Expr::iterator jend = e.end(); for (Expr::iterator j = e.begin(); j != jend; ++j) { DebugAssert(!getCNFLit(*j).isNull(), "Unknown literal"); cnf.addLiteral(getCNFLit(*j)); } cnf.getCurrentClause().setClauseTheorem(d_rules->CNFConvert(e, *i)); } } }
bool TheoryArith::recursiveCanonSimpCheck(const Expr& e) { if (e.hasFind()) return true; if (e != canonSimp(e).getRHS()) return false; Expr::iterator i = e.begin(), iend = e.end(); for (; i != iend; ++i) if (!recursiveCanonSimpCheck(*i)) return false; return true; }
//! 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 prefixPrintGetValue(SmtEngine& smt, Expr e, int level = 0){ for(int i = 0; i < level; ++i){ cout << '-'; } cout << "smt.getValue(" << e << ") -> " << smt.getValue(e) << endl; if(e.hasOperator()){ prefixPrintGetValue(smt, e.getOperator(), level + 1); } for(Expr::const_iterator term_i = e.begin(), term_end = e.end(); term_i != term_end; ++term_i) { Expr curr = *term_i; prefixPrintGetValue(smt, curr, level + 1); } }
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); } }
void BCPattern::matchAnchored(const Expr& pattern, PC start, PC end, Result& result) { auto pos = pattern.begin(); for (auto inst = start; inst != end; ) { // Detect a match. if (pos == pattern.end()) { result.m_start = start; result.m_end = inst; return; } auto const op = peek_op(inst); // Skip pattern-globally ignored opcodes. if (m_ignores.count(op)) { inst = next(inst); continue; } // Check for alternations whenever we fail to match. auto nomatch = [&] { if (!pos->hasAlt()) return result.erase(); // Pop the capture if we made one. if (pos->shouldCapture()) { result.m_captures.pop_back(); } for (auto const& atom : pos->getAlt()) { // Construct the full alternate pattern. auto alt = Expr { atom }; alt.insert(alt.end(), std::next(pos), pattern.end()); auto res = result; // Match on the alternate. matchAnchored(alt, inst, end, res); if (res.found()) { result = res; result.m_start = start; return; } } return result.erase(); }; // Capture the atom if desired. if (pos->shouldCapture()) { result.m_captures.push_back(inst); } // Check for shallow match. if (pos->op() != op) { return nomatch(); } auto filter = pos->getFilter(); // Check for deep match if desired. if (filter && !filter(inst, result.m_captures)) { return nomatch(); } if ((pos->op() == Op::JmpZ || pos->op() == Op::JmpNZ)) { // Match the taken block, if there is one. auto off = instrJumpOffset(inst); assert(off); auto res = result; matchAnchored(pos->getTaken(), inst + *off, end, res); if (!res.found()) { return nomatch(); } // Grab the captures. result.m_captures = res.m_captures; } if (pos->hasSeq()) { // Match the subsequence if we have one. auto res = result; matchAnchored(pos->getSeq(), next(inst), end, res); if (!res.found()) { return nomatch(); } // Set the PC. result.m_captures = res.m_captures; inst = res.m_end; } else { // Step the PC. inst = next(inst); } // Step the pattern. ++pos; } // Detect a terminal match. if (pos == pattern.end()) { result.m_start = start; result.m_end = end; } }
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); }