// 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; }
unsigned compute_degree(ExprManager& exprManager, const Expr& term) { unsigned n = term.getNumChildren(); unsigned degree = 0; // boolean stuff if (term.getType() == exprManager.booleanType()) { for (unsigned i = 0; i < n; ++ i) { degree = std::max(degree, compute_degree(exprManager, term[i])); } return degree; } // terms if (n == 0) { if (term.getKind() == kind::CONST_RATIONAL) { return 0; } else { return 1; } } else { unsigned degree = 0; if (term.getKind() == kind::MULT) { for (unsigned i = 0; i < n; ++ i) { degree += std::max(degree, compute_degree(exprManager, term[i])); } } else { for (unsigned i = 0; i < n; ++ i) { degree = std::max(degree, compute_degree(exprManager, term[i])); } } return degree; } }
//! 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 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()); } } }
bool TheoryArith::isSyntacticRational(const Expr& e, Rational& r) { if (e.getKind() == REAL_CONST) { r = e[0].getRational(); return true; } else if (e.isRational()) { r = e.getRational(); return true; } else if (isUMinus(e)) { if (isSyntacticRational(e[0], r)) { r = -r; return true; } } else if (isDivide(e)) { Rational num; if (isSyntacticRational(e[0], num)) { Rational den; if (isSyntacticRational(e[1], den)) { if (den != 0) { r = num / den; return true; } } } } return false; }
// returns 0 if b is structurally equal to *this int Expr::compare(const Expr &b, ExprEquivSet &equivs) const { if (this == &b) return 0; const Expr *ap, *bp; if (this < &b) { ap = this; bp = &b; } else { ap = &b; bp = this; } if (equivs.count(std::make_pair(ap, bp))) return 0; Kind ak = getKind(), bk = b.getKind(); if (ak!=bk) return (ak < bk) ? -1 : 1; if (hashValue != b.hashValue) return (hashValue < b.hashValue) ? -1 : 1; if (int res = compareContents(b)) return res; unsigned aN = getNumKids(); for (unsigned i=0; i<aN; i++) if (int res = getKid(i)->compare(*b.getKid(i), equivs)) return res; equivs.insert(std::make_pair(ap, bp)); return 0; }
bool TheoryArith::isAtomicArithTerm(const Expr& e) { switch (e.getKind()) { case RATIONAL_EXPR: return true; case ITE: return false; case UMINUS: case PLUS: case MINUS: case MULT: case DIVIDE: case POW: case INTDIV: case MOD: { int i=0, iend=e.arity(); for(; i!=iend; ++i) { if (!isAtomicArithTerm(e[i])) return false; } break; } default: break; } return true; }
Expr ExprManager::mkExpr(Expr opExpr, const std::vector<Expr>& children) { const unsigned n = children.size(); Kind kind = NodeManager::operatorToKind(opExpr.getNode()); CheckArgument(opExpr.getKind() == kind::BUILTIN || kind::metaKindOf(kind) == kind::metakind::PARAMETERIZED, opExpr, "This Expr constructor is for parameterized kinds only"); CheckArgument(n >= minArity(kind) && n <= maxArity(kind), kind, "Exprs with kind %s must have at least %u children and " "at most %u children (the one under construction has %u)", kind::kindToString(kind).c_str(), minArity(kind), maxArity(kind), n); NodeManagerScope nms(d_nodeManager); vector<Node> nodes; vector<Expr>::const_iterator it = children.begin(); vector<Expr>::const_iterator it_end = children.end(); while(it != it_end) { nodes.push_back(it->getNode()); ++it; } try { INC_STAT(kind); return Expr(this,d_nodeManager->mkNodePtr(opExpr.getNode(), nodes)); } catch (const TypeCheckingExceptionPrivate& e) { throw TypeCheckingException(this, &e); } }
ExprVisitor::Action ExprEvaluator::visitExprPost(const Expr& e) { // When evaluating an assignment we should fold NotOptimizedExpr // nodes so we can fully evaluate. if (e.getKind() == Expr::NotOptimized) { return Action::changeTo(static_cast<const NotOptimizedExpr&>(e).src); } return Action::skipChildren(); }
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; }
bool TheoryArith::isAtomicArithFormula(const Expr& e) { switch (e.getKind()) { case LT: case GT: case LE: case GE: case EQ: return isAtomicArithTerm(e[0]) && isAtomicArithTerm(e[1]); } return false; }
Expr ExprManager::mkExpr(Expr opExpr, Expr child1) { const unsigned n = 1; Kind kind = NodeManager::operatorToKind(opExpr.getNode()); CheckArgument(opExpr.getKind() == kind::BUILTIN || kind::metaKindOf(kind) == kind::metakind::PARAMETERIZED, opExpr, "This Expr constructor is for parameterized kinds only"); CheckArgument(n >= minArity(kind) && n <= maxArity(kind), kind, "Exprs with kind %s must have at least %u children and " "at most %u children (the one under construction has %u)", kind::kindToString(kind).c_str(), minArity(kind), maxArity(kind), n); NodeManagerScope nms(d_nodeManager); try { INC_STAT(kind); return Expr(this, d_nodeManager->mkNodePtr(opExpr.getNode(), child1.getNode())); } catch (const TypeCheckingExceptionPrivate& e) { throw TypeCheckingException(this, &e); } }
// returns 0 if b is structurally equal to *this int Expr::compare(const Expr &b) const { if (this == &b) return 0; Kind ak = getKind(), bk = b.getKind(); if (ak!=bk) return (ak < bk) ? -1 : 1; if (hashValue != b.hashValue) return (hashValue < b.hashValue) ? -1 : 1; if (int res = compareContents(b)) return res; unsigned aN = getNumKids(); for (unsigned i=0; i<aN; i++) if (int res = getKid(i).compare(b.getKid(i))) return res; return 0; }
Expr collectSortsExpr(Expr e) { if(substitutions.find(e) != substitutions.end()) { return substitutions[e]; } ++depth; Expr old_e = e; for(unsigned i = 0; i < e.getNumChildren(); ++i) { collectSortsExpr(e[i]); } e = e.substitute(substitutions); // cout << "[debug] " << e << " " << e.getKind() << " " << theory::kindToTheoryId(e.getKind()) << endl; if(theory::kindToTheoryId(e.getKind()) == theory::THEORY_SETS) { SetType t = SetType(e.getType().isBoolean() ? e[1].getType() : e.getType()); substitutions[e] = add(t, e); e = e.substitute(substitutions); } substitutions[old_e] = e; // cout << ";"; for(int i = 0; i < depth; ++i) cout << " "; cout << old_e << " => " << e << endl; --depth; return e; }
void translate_to_redlog(const map<Expr, unsigned>& variables, const Expr& assertion) { bool first; unsigned n = assertion.getNumChildren(); if (n == 0) { if (assertion.isConst()) { if (assertion.getConst<bool>()) { cout << "(1 > 0)"; } else { cout << "(1 < 0)"; } } else { assert(false); } } else { std::string op; bool binary = false; bool theory = false; switch (assertion.getKind()) { case kind::NOT: cout << "(not "; translate_to_redlog(variables, assertion[0]); cout << ")"; break; case kind::OR: first = true; cout << "("; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " or "; } first = false; translate_to_redlog(variables, assertion[i]); } cout << ")"; break; case kind::AND: first = true; cout << "("; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " and "; } first = false; translate_to_redlog(variables, assertion[i]); } cout << ")"; break; case kind::IMPLIES: cout << "("; translate_to_redlog(variables, assertion[0]); cout << " impl "; translate_to_redlog(variables, assertion[1]); cout << ")"; break; case kind::IFF: cout << "("; translate_to_redlog(variables, assertion[0]); cout << " equiv "; translate_to_redlog(variables, assertion[1]); cout << ")"; break; case kind::EQUAL: op = "="; theory = true; break; case kind::LT: op = "<"; theory = true; break; case kind::LEQ: op = "<="; theory = true; break; case kind::GT: op = ">"; theory = true; break; case kind::GEQ: op = ">="; theory = true; break; default: assert(false); break; } if (binary) { cout << "("; translate_to_redlog(variables, assertion[0]); cout << " " << op << " "; translate_to_redlog(variables, assertion[1]); cout << ")"; } if (theory) { cout << "("; translate_to_redlog_term(variables, assertion[0]); cout << " " << op << " "; translate_to_redlog_term(variables, assertion[1]); cout << ")"; } } }
void translate_to_redlog_term(const map<Expr, unsigned>& variables, const Expr& term) { bool first; unsigned n = term.getNumChildren(); if (n == 0) { if (term.getKind() == kind::CONST_RATIONAL) { cout << term.getConst<Rational>(); } else { assert(variables.find(term) != variables.end()); cout << "x" << variables.find(term)->second; } } else { switch (term.getKind()) { case kind::PLUS: cout << "("; first = true; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " + "; } first = false; translate_to_redlog_term(variables, term[i]); } cout << ")"; break; case kind::MULT: cout << "("; first = true; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " * "; } first = false; translate_to_redlog_term(variables, term[i]); } cout << ")"; break; case kind::MINUS: cout << "("; translate_to_redlog_term(variables, term[0]); cout << " - "; translate_to_redlog_term(variables, term[1]); cout << ")"; break; case kind::DIVISION: cout << "("; translate_to_redlog_term(variables, term[0]); cout << " / "; translate_to_redlog_term(variables, term[1]); cout << ")"; break; case kind::UMINUS: cout << "(-("; translate_to_redlog_term(variables, term[0]); cout << "))"; break; default: assert(false); break; } } }
LFSCProof* LFSCProof::Make_CNF( const Expr& form, const Expr& reason, int pos ) { Expr ec = cascade_expr( form ); #ifdef PRINT_MAJOR_METHODS cout << ";[M] CNF " << reason << " " << pos << std::endl; #endif int m = queryM( ec ); if( m>0 ) { ostringstream os1; ostringstream os2; RefPtr< LFSCProof > p; if( reason==d_or_final_s ) { #if 0 //this is the version that cascades //make the proof for the or p = LFSCPfVar::Make( "@v", abs(m) ); //clausify the or statement p = LFSCClausify::Make( ec, p.get(), true ); //return return LFSCAssume::Make( m, p.get(), true ); #else //this is the version that does not expand the last ostringstream oss1, oss2; p = LFSCPfVar::Make( "@v", abs(m) ); for( int a=(form.arity()-2); a>=0; a-- ){ int m1 = queryM( form[a] ); oss1 << "(or_elim_1 _ _ "; oss1 << ( m1<0 ? "(not_not_intro _ " : "" ); oss1 << "@v" << abs( m1 ); oss1 << ( m1<0 ? ") " : " " ); oss2 << ")"; } p = LFSCProofGeneric::Make( oss1.str(), p.get(), oss2.str() ); //p = LFSCClausify::Make( form[form.arity()-1], p.get() ); p = LFSCClausify::Make( queryM( form[form.arity()-1] ), p.get() ); for( int a=0; a<(form.arity()-1); a++ ){ p = LFSCAssume::Make( queryM( form[a] ), p.get(), false ); } return LFSCAssume::Make( m, p.get() ); #endif } else if( reason==d_and_final_s ) { #if 1 //this is the version that does not expand the last p = LFSCPfVar::Make( "@v", abs(m) ); os1 << "(contra _ "; for( int a=0; a<form.arity(); a++ ){ if( a<(form.arity()-1)) os1 << "(and_intro _ _ "; os1 << "@v" << abs( queryM( form[a] ) ); if( a<(form.arity()-1)){ os1 << " "; os2 << ")"; } } os2 << " @v" << abs(m) << ")"; os1 << os2.str(); p = LFSCProofGeneric::MakeStr( os1.str().c_str() ); for( int a=0; a<form.arity(); a++ ){ p = LFSCAssume::Make( queryM( form[a] ), p.get() ); } return LFSCAssume::Make( m, p.get(), false ); #else //this is the version that cascades std::vector< Expr > assumes; Expr ce = cascade_expr( form ); Expr curr = ce; os1 << "(contra _ "; while( curr.getKind()==AND ){ os1 << "(and_intro _ _ "; os1 << "@v" << abs( queryM( curr[0] ) ) << " "; os2 << ")"; assumes.push_back( curr[0] ); curr = curr[1]; } os2 << " @v" << abs(m) << ")"; p = LFSCProofGeneric::Make( os1.str(), p.get(), os2.str() ); for( int a=0; a<(int)assumes.size(); a++ ){ p = LFSCAssume::Make( queryM( assumes[a] ), p.get() ); } return LFSCAssume::Make( m, p.get(), false ); #endif } else if( reason==d_imp_s ) { int m1 = queryM( ec[0] ); int m2 = queryM( ec[1] ); switch( pos ) { case 0: break; case 1: break; case 2: { //make a proof of the RHS ostringstream os; os << "(impl_elim _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); //clausify the RHS p = LFSCClausify::Make( form[1], p.get() ); //cascadeOr? p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; } } else if( reason==d_ite_s ) { int m1 = queryM( ec[0] ); int m2 = queryM( ec[1] ); switch( pos ) { case 1: { ostringstream os; os << "(ite_elim_2" << (m1<0 ? "n" : "" ); os << " _ _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( form[2], p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get(), false ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; case 2: { ostringstream os; os << "(not_ite_elim_2 _ _ _ @v" << (m1<0 ? "n" : "" ); os << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); Expr e = Expr( NOT, form[2] ); p = LFSCClausify::Make( e, p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get(), false ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 3: { ostringstream os; os << "(not_ite_elim_1 _ _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); Expr e = Expr( NOT, form[1] ); p = LFSCClausify::Make( e, p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 4: { ostringstream os; os << "(ite_elim_1";// << (m1<0 ? "n" : "" ); os << " _ _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( form[1], p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; case 5: { ostringstream os; os << "(not_ite_elim_3 _ _ _ @v" << abs( m2 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); Expr e = Expr( NOT, form[2] ); p = LFSCClausify::Make( e, p.get() ); p = LFSCAssume::Make( queryM( ec[1] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 6: { ostringstream os; os << "(ite_elim_3";// << (m1<0 ? "n" : "" ); os << " _ _ _ @v" << abs( m2 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( form[2], p.get() ); p = LFSCAssume::Make( queryM( ec[1] ), p.get(), false ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; } } else if( reason==d_iff_s ) { int m1 = queryM( ec[0] ); int m2 = queryM( ec[1] ); switch( pos ) { case 0: { ostringstream os; os << "(not_iff_elim_1 _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( form[1], p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get(), false ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 1: { ostringstream os; os << "(not_iff_elim_2 _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( Expr( NOT, form[1] ), p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 2: { ostringstream os; os << "(impl_elim _ _ @v" << abs( m1 ) << "(iff_elim_1 _ _ @v" << abs( m ) << "))"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); //clausify the RHS p = LFSCClausify::Make( form[1], p.get() ); //cascadeOr? p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; case 3: { ostringstream os; os << "(impl_elim _ _ @v" << abs( m2 ) << "(iff_elim_2 _ _ @v" << abs( m ) << "))"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); //clausify the RHS p = LFSCClausify::Make( form[0], p.get() ); //cascadeOr? p = LFSCAssume::Make( queryM( ec[1] ), p.get() ); return LFSCAssume::Make( m, p.get() ); } break; } } else if( reason==d_or_mid_s ) { ostringstream os1, os2; if( form[pos].isNot() ) os1 << "(not_not_elim _ "; os1 << "(or_elim" << ( (pos==form.arity()) ? "_end" : "" ); os1 << " _ _ " << pos << " "; os2 << ")"; if( form[pos].isNot() ) os2 << ")"; p = LFSCPfVar::Make( "@v", abs( m ) ); p = LFSCProofGeneric::Make( os1.str(), p.get(), os2.str() ); Expr ea = Expr( NOT, form[pos] ); p = LFSCClausify::Make( ea, p.get() ); return LFSCAssume::Make( m, p.get(), false ); } else if( reason==d_and_mid_s ) { //make a proof of the pos-th statement p = LFSCPfVar::Make( "@v", abs( m ) ); p = LFSCProof::Make_and_elim( form, p.get(), pos, form[pos] ); p = LFSCClausify::Make( form[pos], p.get() ); return LFSCAssume::Make( m, p.get() ); } } ostringstream ose; ose << "CNF, " << reason << " unknown position = " << pos << std::endl; print_error( ose.str().c_str(), cout ); return NULL; }
Expr add(SetType t, Expr e) { if(setTypes.find(t) == setTypes.end() ) { // mark as processed setTypes.insert(t); Type elementType = t.getElementType(); ostringstream oss_type; oss_type << language::SetLanguage(language::output::LANG_SMTLIB_V2) << elementType; string elementTypeAsString = oss_type.str(); elementTypeAsString.erase( remove_if(elementTypeAsString.begin(), elementTypeAsString.end(), nonsense), elementTypeAsString.end()); // define-sort ostringstream oss_name; oss_name << language::SetLanguage(language::output::LANG_SMTLIB_V2) << "(Set " << elementType << ")"; string name = oss_name.str(); Type newt = em->mkArrayType(t.getElementType(), em->booleanType()); mapTypes[t] = newt; // diffent types vector<Type> t_t; t_t.push_back(t); t_t.push_back(t); vector<Type> elet_t; elet_t.push_back(elementType); elet_t.push_back(t); if(!enableAxioms) sout << "(define-fun emptyset" << elementTypeAsString << " " << " ()" << " " << name << " ( (as const " << name << ") false ) )" << endl; setoperators[ make_pair(t, kind::EMPTYSET) ] = em->mkVar( std::string("emptyset") + elementTypeAsString, t); if(!enableAxioms) sout << "(define-fun singleton" << elementTypeAsString << " " << " ( (x " << elementType << ") )" << " " << name << "" << " (store emptyset" << elementTypeAsString << " x true) )" << endl; setoperators[ make_pair(t, kind::SINGLETON) ] = em->mkVar( std::string("singleton") + elementTypeAsString, em->mkFunctionType( elementType, t ) ); if(!enableAxioms) sout << "(define-fun union" << elementTypeAsString << " " << " ( (s1 " << name << ") (s2 " << name << ") )" << " " << name << "" << " ((_ map or) s1 s2))" << endl; setoperators[ make_pair(t, kind::UNION) ] = em->mkVar( std::string("union") + elementTypeAsString, em->mkFunctionType( t_t, t ) ); if(!enableAxioms) sout << "(define-fun intersection" << elementTypeAsString << "" << " ( (s1 " << name << ") (s2 " << name << ") )" << " " << name << "" << " ((_ map and) s1 s2))" << endl; setoperators[ make_pair(t, kind::INTERSECTION) ] = em->mkVar( std::string("intersection") + elementTypeAsString, em->mkFunctionType( t_t, t ) ); if(!enableAxioms) sout << "(define-fun setminus" << elementTypeAsString << " " << " ( (s1 " << name << ") (s2 " << name << ") )" << " " << name << "" << " (intersection" << elementTypeAsString << " s1 ((_ map not) s2)))" << endl; setoperators[ make_pair(t, kind::SETMINUS) ] = em->mkVar( std::string("setminus") + elementTypeAsString, em->mkFunctionType( t_t, t ) ); if(!enableAxioms) sout << "(define-fun member" << elementTypeAsString << " " << " ( (x " << elementType << ")" << " (s " << name << "))" << " Bool" << " (select s x) )" << endl; setoperators[ make_pair(t, kind::MEMBER) ] = em->mkVar( std::string("member") + elementTypeAsString, em->mkPredicateType( elet_t ) ); if(!enableAxioms) sout << "(define-fun subset" << elementTypeAsString << " " << " ( (s1 " << name << ") (s2 " << name << ") )" << " Bool" <<" (= emptyset" << elementTypeAsString << " (setminus" << elementTypeAsString << " s1 s2)) )" << endl; setoperators[ make_pair(t, kind::SUBSET) ] = em->mkVar( std::string("subset") + elementTypeAsString, em->mkPredicateType( t_t ) ); if(enableAxioms) { int N = sizeof(setaxioms) / sizeof(setaxioms[0]); for(int i = 0; i < N; ++i) { string s = setaxioms[i]; ostringstream oss; oss << language::SetLanguage(language::output::LANG_SMTLIB_V2) << elementType; boost::replace_all(s, "HOLDA", elementTypeAsString); boost::replace_all(s, "HOLDB", oss.str()); if( s == "" ) continue; sout << s << endl; } } } Expr ret; if(e.getKind() == kind::EMPTYSET) { ret = setoperators[ make_pair(t, e.getKind()) ]; } else { vector<Expr> children = e.getChildren(); children.insert(children.begin(), setoperators[ make_pair(t, e.getKind()) ]); ret = em->mkExpr(kind::APPLY, children); } // cout << "returning " << ret << endl; 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 translate_to_mathematica(const map<Expr, unsigned>& variables, const Expr& assertion) { bool first; unsigned n = assertion.getNumChildren(); if (n == 0) { assert(false); } else { std::string op; bool binary = false; bool theory = false; switch (assertion.getKind()) { case kind::NOT: cout << "!"; translate_to_mathematica(variables, assertion[0]); break; case kind::OR: first = true; cout << "("; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " || "; } first = false; translate_to_mathematica(variables, assertion[i]); } cout << ")"; break; case kind::AND: first = true; cout << "("; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " && "; } first = false; translate_to_mathematica(variables, assertion[i]); } cout << ")"; break; case kind::IMPLIES: cout << "Implies["; translate_to_mathematica(variables, assertion[0]); cout << ","; translate_to_mathematica(variables, assertion[1]); cout << "]"; break; case kind::IFF: cout << "Equivalent["; translate_to_mathematica(variables, assertion[0]); cout << ","; translate_to_mathematica(variables, assertion[1]); cout << "]"; break; case kind::EQUAL: op = "=="; theory = true; break; case kind::LT: op = "<"; theory = true; break; case kind::LEQ: op = "<="; theory = true; break; case kind::GT: op = ">"; theory = true; break; case kind::GEQ: op = ">="; theory = true; break; default: assert(false); break; } if (binary) { cout << "("; translate_to_mathematica(variables, assertion[0]); cout << " " << op << " "; translate_to_mathematica(variables, assertion[1]); cout << ")"; } if (theory) { cout << "("; translate_to_mathematica_term(variables, assertion[0]); cout << " " << op << " "; translate_to_mathematica_term(variables, assertion[1]); cout << ")"; } } }
Expr TheoryArith::rewriteToDiff(const Expr& e) { Expr tmp = e[0] - e[1]; tmp = canonRec(tmp).getRHS(); switch (tmp.getKind()) { case RATIONAL_EXPR: { Rational r = tmp.getRational(); switch (e.getKind()) { case LT: if (r < 0) return trueExpr(); else return falseExpr(); case LE: if (r <= 0) return trueExpr(); else return falseExpr(); case GT: if (r > 0) return trueExpr(); else return falseExpr(); case GE: if (r >= 0) return trueExpr(); else return falseExpr(); case EQ: if (r == 0) return trueExpr(); else return falseExpr(); } } case MULT: DebugAssert(tmp[0].isRational(), "Unexpected term structure from canon"); if (tmp[0].getRational() != -1) return e; return Expr(e.getOp(), theoryCore()->getTranslator()->zeroVar() - tmp[1], rat(0)); case PLUS: { DebugAssert(tmp[0].isRational(), "Unexpected term structure from canon"); Rational c = tmp[0].getRational(); Expr x, y; if (tmp.arity() == 2) { if (tmp[1].getKind() == MULT) { x = theoryCore()->getTranslator()->zeroVar(); y = tmp[1]; } else { x = tmp[1]; y = rat(-1) * theoryCore()->getTranslator()->zeroVar(); } } else if (tmp.arity() == 3) { if (tmp[1].getKind() == MULT) { x = tmp[2]; y = tmp[1]; } else if (tmp[2].getKind() == MULT) { x = tmp[1]; y = tmp[2]; } else return e; } else return e; if (x.getKind() == MULT) return e; DebugAssert(y[0].isRational(), "Unexpected term structure from canon"); if (y[0].getRational() != -1) return e; return Expr(e.getOp(), x - y[1], getEM()->newRatExpr(-c)); } default: return Expr(e.getOp(), tmp - theoryCore()->getTranslator()->zeroVar(), rat(0)); break; } return e; }
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; } }