bool visit_children(expr * n, unsigned delta) { bool visited = true; unsigned dw; unsigned j; switch (n->get_kind()) { case AST_VAR: dw = m_window <= UINT_MAX - delta ? m_window + delta : UINT_MAX; if (to_var(n)->get_idx() >= delta && to_var(n)->get_idx() <= dw) m_contains = true; break; case AST_APP: j = to_app(n)->get_num_args(); while (j > 0) { --j; visit(to_app(n)->get_arg(j), delta, visited); } break; case AST_QUANTIFIER: if (delta <= UINT_MAX - to_quantifier(n)->get_num_decls()) { visit(to_quantifier(n)->get_expr(), delta + to_quantifier(n)->get_num_decls(), visited); } break; default: break; } return visited; }
// // Hoist quantifier from rule (universal) or query (existential) // unsigned rule_manager::hoist_quantifier(bool is_forall, expr_ref& fml, svector<symbol>* names) { unsigned index = var_counter().get_next_var(fml); while (is_quantifier(fml) && (is_forall == to_quantifier(fml)->is_forall())) { quantifier* q = to_quantifier(fml); index += q->get_num_decls(); if (names) { names->append(q->get_num_decls(), q->get_decl_names()); } fml = q->get_expr(); } if (!has_quantifiers(fml)) { return index; } app_ref_vector vars(m); quantifier_hoister qh(m); qh.pull_quantifier(is_forall, fml, vars); if (vars.empty()) { return index; } // replace vars by de-bruijn indices expr_substitution sub(m); for (unsigned i = 0; i < vars.size(); ++i) { app* v = vars[i].get(); if (names) { names->push_back(v->get_decl()->get_name()); } sub.insert(v, m.mk_var(index++,m.get_sort(v))); } scoped_ptr<expr_replacer> rep = mk_default_expr_replacer(m); rep->set_substitution(&sub); (*rep)(fml); return index; }
void collect(expr * t, expr_fast_mark1 & visited) { rational k; visit(t, visited); while (!m_todo.empty()) { checkpoint(); expr * t = m_todo.back(); m_todo.pop_back(); if (is_var(t)) continue; if (is_quantifier(t)) { unsigned num_children = to_quantifier(t)->get_num_children(); for (unsigned i = 0; i < num_children; i ++) visit(to_quantifier(t)->get_child(i), visited); } else { SASSERT(is_app(t)); if (m_autil.is_power(t) && m_autil.is_numeral(to_app(t)->get_arg(1), k) && k.is_int() && k.is_pos()) { expr * arg = to_app(t)->get_arg(0); save_degree(arg, k); visit_args(arg, visited); } else { visit_args(t, visited); } } } }
/** \brief extract the instantiation by searching for the first occurrence of a hyper-resolution rule that produces an instance. */ void boogie_proof::get_subst(proof* p, subst& s) { ptr_vector<proof> todo; todo.push_back(p); ast_mark visited; std::cout << "get_subst\n" << mk_pp(p, m) << "\n"; while (!todo.empty()) { proof* p = todo.back(); todo.pop_back(); if (visited.is_marked(p)) { continue; } visited.mark(p, true); proof_ref_vector premises(m); expr_ref conclusion(m); svector<std::pair<unsigned, unsigned> > positions; vector<expr_ref_vector> substs; if (m.is_hyper_resolve(p, premises, conclusion, positions, substs)) { expr_ref_vector const& sub = substs[0]; if (!sub.empty()) { quantifier* q = to_quantifier(m.get_fact(premises[0].get())); unsigned sz = sub.size(); SASSERT(sz == q->get_num_decls()); for (unsigned i = 0; i < sz; ++i) { s.push_back(std::make_pair(q->get_decl_name(sz-1-i), sub[i])); } return; } } unsigned sz = m.get_num_parents(p); for (unsigned i = 0; i < sz; ++i) { todo.push_back(m.get_parent(p, i)); } } }
bool is_horn(expr* n) { expr* n1, *n2; while (is_forall(n)) n = to_quantifier(n)->get_expr(); if (m.is_implies(n, n1, n2) && is_predicate(n2)) { if (is_var(n1)) { return true; } if (is_quantifier(n1)) { return false; } app* a1 = to_app(n1); if (m.is_and(a1)) { for (unsigned i = 0; i < a1->get_num_args(); ++i) { if (!is_predicate(a1->get_arg(i)) && contains_predicate(a1->get_arg(i))) { return false; } } } else if (!is_predicate(a1) && contains_predicate(a1)) { return false; } return true; } return false; }
bool expr_delta::delta_dfs(unsigned& n, expr* e, expr_ref& result) { ast_manager& m = m_manager; if (m.is_true(e) || m.is_false(e)) { return false; } if (n == 0 && m.is_bool(e)) { result = m.mk_true(); return true; } else if (n == 1 && m.is_bool(e)) { result = m.mk_false(); return true; } else if (is_app(e)) { if (m.is_bool(e)) { SASSERT(n >= 2); n -= 2; } return delta_dfs(n, to_app(e), result); } else if (is_quantifier(e)) { SASSERT(n >= 2); n -= 2; quantifier* q = to_quantifier(e); if (delta_dfs(n, q->get_expr(), result)) { result = m.update_quantifier(q, result.get()); return true; } else { return false; } } return false; }
bool fpa_util::contains_floats(ast * a) { switch (a->get_kind()) { case AST_APP: { app * aa = to_app(a); if (contains_floats(aa->get_decl())) return true; else for (unsigned i = 0; i < aa->get_num_args(); i++) if (contains_floats(aa->get_arg(i))) return true; break; } case AST_VAR: return contains_floats(to_var(a)->get_sort()); break; case AST_QUANTIFIER: { quantifier * q = to_quantifier(a); for (unsigned i = 0; i < q->get_num_children(); i++) if (contains_floats(q->get_child(i))) return true; for (unsigned i = 0; i < q->get_num_decls(); i++) if (contains_floats(q->get_decl_sort(i))) return true; if (contains_floats(q->get_expr())) return true; break; } case AST_SORT: { sort * s = to_sort(a); if (is_float(s) || is_rm(s)) return true; else { for (unsigned i = 0; i < s->get_num_parameters(); i++) { parameter const & pi = s->get_parameter(i); if (pi.is_ast() && contains_floats(pi.get_ast())) return true; } } break; } case AST_FUNC_DECL: { func_decl * f = to_func_decl(a); for (unsigned i = 0; i < f->get_arity(); i++) if (contains_floats(f->get_domain(i))) return true; if (contains_floats(f->get_range())) return true; for (unsigned i = 0; i < f->get_num_parameters(); i++) { parameter const & pi = f->get_parameter(i); if (pi.is_ast() && contains_floats(pi.get_ast())) return true; } break; } default: UNREACHABLE(); } return false; }
unsigned get_symbol_count(expr * n) { unsigned r = 0; ptr_buffer<expr> todo; todo.push_back(n); while (!todo.empty()) { n = todo.back(); unsigned j; todo.pop_back(); r++; switch (n->get_kind()) { case AST_APP: j = to_app(n)->get_num_args(); while (j > 0) { --j; todo.push_back(to_app(n)->get_arg(j)); } break; case AST_QUANTIFIER: todo.push_back(to_quantifier(n)->get_expr()); break; default: break; } } return r; }
void expr_context_simplifier::reduce_rec(expr * m, expr_ref & result) { // // reduce expr in context evaluation. // bool polarity; if (m_context.find(m, polarity)) { result = polarity ? m_manager.mk_true() : m_manager.mk_false(); } else if (m_mark.is_marked(m) && !m_manager.is_not(m)) { result = m; } else if (is_quantifier(m)) { reduce_rec(to_quantifier(m), result); m_mark.mark(m, true); } else if (is_app(m)) { reduce_rec(to_app(m), result); m_mark.mark(m, true); } else if (is_var(m)) { result = m; m_mark.mark(m, true); } else { UNREACHABLE(); result = m; } }
void check_predicate(ast_mark& mark, expr* a) { ptr_vector<expr> todo; todo.push_back(a); while (!todo.empty()) { a = todo.back(); todo.pop_back(); if (mark.is_marked(a)) { continue; } mark.mark(a, true); if (is_quantifier(a)) { a = to_quantifier(a)->get_expr(); todo.push_back(a); } else if (m.is_not(a) || m.is_and(a) || m.is_or(a) || m.is_implies(a)) { todo.append(to_app(a)->get_num_args(), to_app(a)->get_args()); } else if (m.is_ite(a)) { todo.push_back(to_app(a)->get_arg(1)); todo.push_back(to_app(a)->get_arg(2)); } else if (is_predicate(a)) { register_predicate(a); } } }
bool is_implication(expr* f) { expr* e1; while (is_forall(f)) { f = to_quantifier(f)->get_expr(); } while (m.is_implies(f, e1, f)) ; return is_predicate(f); }
void check_pred::visit(expr* e) { ptr_vector<expr> todo; todo.push_back(e); while (!todo.empty()) { e = todo.back(); if (m_pred(e)) { m_pred_holds.mark(e, true); } if (m_visited.is_marked(e)) { todo.pop_back(); continue; } switch(e->get_kind()) { case AST_APP: { app* a = to_app(e); bool all_visited = true; unsigned num_args = a->get_num_args(); for (unsigned i = 0; i < num_args; ++i) { expr* arg = a->get_arg(i); if (!m_visited.is_marked(arg)) { todo.push_back(arg); all_visited = false; } else if (m_pred_holds.is_marked(arg)) { m_pred_holds.mark(e, true); } } if (all_visited) { m_visited.mark(e, true); todo.pop_back(); } break; } case AST_QUANTIFIER: { quantifier* q = to_quantifier(e); expr* arg = q->get_expr(); if (m_visited.is_marked(arg)) { todo.pop_back(); if (m_pred_holds.is_marked(arg)) { m_pred_holds.mark(e, true); } m_visited.mark(e, true); } else { todo.push_back(arg); } break; } case AST_VAR: todo.pop_back(); m_visited.mark(e, true); break; default: UNREACHABLE(); break; } } }
void mk_quantifier_instantiation::instantiate_quantifier(quantifier* q, expr_ref_vector & conjs) { expr_ref qe(m); qe = q; m_var2cnst(qe); q = to_quantifier(qe); if (q->get_num_patterns() == 0) { proof_ref new_pr(m); pattern_inference_params params; pattern_inference infer(m, params); infer(q, qe, new_pr); q = to_quantifier(qe); } unsigned num_patterns = q->get_num_patterns(); for (unsigned i = 0; i < num_patterns; ++i) { expr * pat = q->get_pattern(i); SASSERT(m.is_pattern(pat)); instantiate_quantifier(q, to_app(pat), conjs); } }
unsigned var_counter::get_max_var(bool& has_var) { has_var = false; unsigned max_var = 0; ptr_vector<quantifier> qs; while (!m_todo.empty()) { expr* e = m_todo.back(); m_todo.pop_back(); if (m_visited.is_marked(e)) { continue; } m_visited.mark(e, true); switch(e->get_kind()) { case AST_QUANTIFIER: { qs.push_back(to_quantifier(e)); break; } case AST_VAR: { if (to_var(e)->get_idx() >= max_var) { has_var = true; max_var = to_var(e)->get_idx(); } break; } case AST_APP: { app* a = to_app(e); for (unsigned i = 0; i < a->get_num_args(); ++i) { m_todo.push_back(a->get_arg(i)); } break; } default: UNREACHABLE(); break; } } m_visited.reset(); while (!qs.empty()) { var_counter aux_counter; quantifier* q = qs.back(); qs.pop_back(); aux_counter.m_todo.push_back(q->get_expr()); bool has_var1 = false; unsigned max_v = aux_counter.get_max_var(has_var1); if (max_v >= max_var + q->get_num_decls()) { max_var = max_v - q->get_num_decls(); has_var = has_var || has_var1; } } return max_var; }
void shared_occs::operator()(expr * t, shared_occs_mark & visited) { SASSERT(m_stack.empty()); if (process(t, visited)) { return; } SASSERT(!m_stack.empty()); while (!m_stack.empty()) { start: frame & fr = m_stack.back(); expr * curr = fr.first; switch (curr->get_kind()) { case AST_APP: { unsigned num_args = to_app(curr)->get_num_args(); while (fr.second < num_args) { expr * arg = to_app(curr)->get_arg(fr.second); fr.second++; if (!process(arg, visited)) goto start; } break; } case AST_QUANTIFIER: { SASSERT(m_visit_quantifiers); unsigned num_children = m_visit_patterns ? to_quantifier(curr)->get_num_children() : 1; while (fr.second < num_children) { expr * child = to_quantifier(curr)->get_child(fr.second); fr.second++; if (!process(child, visited)) goto start; } break; } default: UNREACHABLE(); break; } m_stack.pop_back(); } }
static void parse_fml(char const* str, app_ref_vector& vars, expr_ref& fml) { ast_manager& m = fml.get_manager(); fml = parse_fml(m, str); if (is_exists(fml)) { quantifier* q = to_quantifier(fml); for (unsigned i = 0; i < q->get_num_decls(); ++i) { vars.push_back(m.mk_const(q->get_decl_name(i), q->get_decl_sort(i))); } fml = q->get_expr(); var_subst vs(m, true); vs(fml, vars.size(), (expr*const*)vars.c_ptr(), fml); } }
Z3_bool Z3_API Z3_is_quantifier_forall(Z3_context c, Z3_ast a) { Z3_TRY; LOG_Z3_is_quantifier_forall(c, a); RESET_ERROR_CODE(); ast * _a = to_ast(a); if (_a->get_kind() == AST_QUANTIFIER) { return to_quantifier(_a)->is_forall(); } else { SET_ERROR_CODE(Z3_SORT_ERROR); return Z3_FALSE; } Z3_CATCH_RETURN(Z3_FALSE); }
void tst_instantiate(ast_manager & m, expr * f) { if (is_quantifier(f)) { tst_instantiate(m, to_quantifier(f)->get_expr()); return; } quantifier * q = find_quantifier(f); if (q) { expr_ref_vector cnsts(m); for (unsigned i = 0; i < q->get_num_decls(); i++) cnsts.push_back(m.mk_fresh_const("a", q->get_decl_sort(i))); expr_ref r(m); instantiate(m, q, cnsts.c_ptr(), r); TRACE("var_subst", tout << "quantifier:\n" << mk_pp(q, m) << "\nresult:\n" << mk_pp(r, m) << "\n";); }
void normalize(expr_ref& f) { bool is_positive = true; expr* e = 0; while (true) { if (is_forall(f) && is_positive) { f = to_quantifier(f)->get_expr(); } else if (is_exists(f) && !is_positive) { f = to_quantifier(f)->get_expr(); } else if (m.is_not(f, e)) { is_positive = !is_positive; f = e; } else { break; } } if (!is_positive) { f = m.mk_not(f); } }
void print_answer(cmd_context& ctx) { if (m_params.get_bool(":print-answer", false)) { datalog::context& dlctx = m_dl_ctx->get_dl_context(); ast_manager& m = ctx.m(); expr_ref query_result(dlctx.get_answer_as_formula(), m); sbuffer<symbol> var_names; unsigned num_decls = 0; if (is_quantifier(m_target)) { num_decls = to_quantifier(m_target)->get_num_decls(); } ctx.display(ctx.regular_stream(), query_result, 0, num_decls, "X", var_names); ctx.regular_stream() << std::endl; } }
Z3_symbol Z3_API Z3_get_quantifier_bound_name(Z3_context c, Z3_ast a, unsigned i) { Z3_TRY; LOG_Z3_get_quantifier_bound_name(c, a, i); RESET_ERROR_CODE(); ast * _a = to_ast(a); if (_a->get_kind() == AST_QUANTIFIER) { return of_symbol(to_quantifier(_a)->get_decl_names()[i]); } else { SET_ERROR_CODE(Z3_SORT_ERROR); return 0; } Z3_CATCH_RETURN(0); }
void distribute_forall::reduce1(expr * n) { switch (n->get_kind()) { case AST_VAR: cache_result(n, n); break; case AST_APP: reduce1_app(to_app(n)); break; case AST_QUANTIFIER: reduce1_quantifier(to_quantifier(n)); break; default: UNREACHABLE(); } }
unsigned Z3_API Z3_get_quantifier_num_no_patterns(Z3_context c, Z3_ast a) { Z3_TRY; LOG_Z3_get_quantifier_num_no_patterns(c, a); RESET_ERROR_CODE(); ast * _a = to_ast(a); if (_a->get_kind() == AST_QUANTIFIER) { return to_quantifier(_a)->get_num_no_patterns(); } else { SET_ERROR_CODE(Z3_SORT_ERROR); return 0; } Z3_CATCH_RETURN(0); }
void decl_collector::visit(ast* n) { datatype_util util(m()); m_todo.push_back(n); while (!m_todo.empty()) { n = m_todo.back(); m_todo.pop_back(); if (!m_visited.is_marked(n)) { switch(n->get_kind()) { case AST_APP: { app * a = to_app(n); for (expr* arg : *a) { m_todo.push_back(arg); } m_todo.push_back(a->get_decl()); break; } case AST_QUANTIFIER: { quantifier * q = to_quantifier(n); unsigned num_decls = q->get_num_decls(); for (unsigned i = 0; i < num_decls; ++i) { m_todo.push_back(q->get_decl_sort(i)); } m_todo.push_back(q->get_expr()); for (unsigned i = 0; i < q->get_num_patterns(); ++i) { m_todo.push_back(q->get_pattern(i)); } break; } case AST_SORT: visit_sort(to_sort(n)); break; case AST_FUNC_DECL: { func_decl * d = to_func_decl(n); for (sort* srt : *d) { m_todo.push_back(srt); } m_todo.push_back(d->get_range()); visit_func(d); break; } case AST_VAR: break; default: UNREACHABLE(); } m_visited.mark(n, true); } } }
void fixedpoint_context::simplify_rules( unsigned num_rules, expr* const* rules, unsigned num_outputs, func_decl* const* outputs, expr_ref_vector& result) { ast_manager& m = m_context.get_manager(); datalog::context ctx(m, m_context.get_fparams()); datalog::rule_manager& rm = ctx.get_rule_manager(); for (unsigned i = 0; i < num_rules; ++i) { expr* rule = rules[i], *body, *head; while (true) { if (is_quantifier(rule)) { rule = to_quantifier(rule)->get_expr(); } else if (m.is_implies(rule, body, head)) { rule = head; } else { break; } } if (is_app(rule)) { func_decl* r = to_app(rule)->get_decl(); if (!ctx.is_predicate(r)) { ctx.register_predicate(r); if (num_outputs == 0) { ctx.set_output_predicate(r); } } } } for (unsigned i = 0; i < num_outputs; ++i) { ctx.set_output_predicate(outputs[i]); } for (unsigned i = 0; i < num_rules; ++i) { expr* rule = rules[i]; ctx.add_rule(rule, symbol::null); } model_converter_ref mc; // not exposed. proof_converter_ref pc; // not exposed. ctx.apply_default_transformation(mc, pc); datalog::rule_set const& new_rules = ctx.get_rules(); datalog::rule_set::iterator it = new_rules.begin(), end = new_rules.end(); for (; it != end; ++it) { datalog::rule* r = *it; expr_ref fml(m); r->to_formula(fml); result.push_back(fml); } }
void decl_collector::visit(ast* n) { ptr_vector<ast> todo; todo.push_back(n); while (!todo.empty()) { n = todo.back(); todo.pop_back(); if (!m_visited.is_marked(n)) { m_visited.mark(n, true); switch(n->get_kind()) { case AST_APP: { app * a = to_app(n); for (unsigned i = 0; i < a->get_num_args(); ++i) { todo.push_back(a->get_arg(i)); } todo.push_back(a->get_decl()); break; } case AST_QUANTIFIER: { quantifier * q = to_quantifier(n); unsigned num_decls = q->get_num_decls(); for (unsigned i = 0; i < num_decls; ++i) { todo.push_back(q->get_decl_sort(i)); } todo.push_back(q->get_expr()); for (unsigned i = 0; i < q->get_num_patterns(); ++i) { todo.push_back(q->get_pattern(i)); } break; } case AST_SORT: visit_sort(to_sort(n)); break; case AST_FUNC_DECL: { func_decl * d = to_func_decl(n); for (unsigned i = 0; i < d->get_arity(); ++i) { todo.push_back(d->get_domain(i)); } todo.push_back(d->get_range()); visit_func(d); break; } case AST_VAR: break; default: UNREACHABLE(); } } } }
bool ufbv_rewriter::is_demodulator(expr * e, expr_ref & large, expr_ref & small) const { if (e->get_kind() == AST_QUANTIFIER) { quantifier * q = to_quantifier(e); if (q->is_forall()) { expr * qe = q->get_expr(); if ((m_manager.is_eq(qe) || m_manager.is_iff(qe))) { app * eq = to_app(q->get_expr()); expr * lhs = eq->get_arg(0); expr * rhs = eq->get_arg(1); int subset = is_subset(lhs, rhs); int smaller = is_smaller(lhs, rhs); TRACE("demodulator", tout << "testing is_demodulator:\n" << mk_pp(lhs, m_manager) << "\n" << mk_pp(rhs, m_manager) << "\n" << "subset: " << subset << ", smaller: " << smaller << "\n";);
Z3_ast Z3_API Z3_get_quantifier_body(Z3_context c, Z3_ast a) { Z3_TRY; LOG_Z3_get_quantifier_body(c, a); RESET_ERROR_CODE(); ast * _a = to_ast(a); if (_a->get_kind() == AST_QUANTIFIER) { Z3_ast r = of_ast(to_quantifier(_a)->get_expr()); RETURN_Z3(r); } else { SET_ERROR_CODE(Z3_SORT_ERROR); RETURN_Z3(0); } Z3_CATCH_RETURN(0); }
Z3_sort Z3_API Z3_get_quantifier_bound_sort(Z3_context c, Z3_ast a, unsigned i) { Z3_TRY; LOG_Z3_get_quantifier_bound_sort(c, a, i); RESET_ERROR_CODE(); ast * _a = to_ast(a); if (_a->get_kind() == AST_QUANTIFIER) { Z3_sort r = of_sort(to_quantifier(_a)->get_decl_sort(i)); RETURN_Z3(r); } else { SET_ERROR_CODE(Z3_SORT_ERROR); RETURN_Z3(0); } Z3_CATCH_RETURN(0); }
Z3_pattern Z3_API Z3_get_quantifier_pattern_ast(Z3_context c, Z3_ast a, unsigned i) { Z3_TRY; LOG_Z3_get_quantifier_pattern_ast(c, a, i); RESET_ERROR_CODE(); ast * _a = to_ast(a); if (_a->get_kind() == AST_QUANTIFIER) { Z3_pattern r = of_pattern(to_quantifier(_a)->get_patterns()[i]); RETURN_Z3(r); } else { SET_ERROR_CODE(Z3_SORT_ERROR); RETURN_Z3(0); } Z3_CATCH_RETURN(0); }