static void test2(char const *ex) { smt_params params; params.m_model = true; ast_manager m; reg_decl_plugins(m); arith_util a(m); expr_ref fml = parse_fml(m, ex); app_ref_vector vars(m); expr_ref_vector lits(m); vars.push_back(m.mk_const(symbol("x"), a.mk_real())); vars.push_back(m.mk_const(symbol("y"), a.mk_real())); vars.push_back(m.mk_const(symbol("z"), a.mk_real())); flatten_and(fml, lits); smt::context ctx(m, params); ctx.push(); ctx.assert_expr(fml); lbool result = ctx.check(); VERIFY(result == l_true); ref<model> md; ctx.get_model(md); ctx.pop(1); std::cout << mk_pp(fml, m) << "\n"; expr_ref pr1(m), pr2(m), fml2(m); expr_ref_vector bound(m); ptr_vector<sort> sorts; svector<symbol> names; for (unsigned i = 0; i < vars.size(); ++i) { bound.push_back(vars[i].get()); names.push_back(vars[i]->get_decl()->get_name()); sorts.push_back(m.get_sort(vars[i].get())); } expr_abstract(m, 0, bound.size(), bound.c_ptr(), fml, fml2); fml2 = m.mk_exists(bound.size(), sorts.c_ptr(), names.c_ptr(), fml2); qe::expr_quant_elim qe(m, params); for (unsigned i = 0; i < vars.size(); ++i) { VERIFY(qe::arith_project(*md, vars[i].get(), lits)); } pr1 = mk_and(lits); qe(m.mk_true(), fml2, pr2); std::cout << mk_pp(pr1, m) << "\n"; std::cout << mk_pp(pr2, m) << "\n"; expr_ref npr2(m); npr2 = m.mk_not(pr2); ctx.push(); ctx.assert_expr(pr1); ctx.assert_expr(npr2); VERIFY(l_false == ctx.check()); ctx.pop(1); }
expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app* const* bound, expr* n) { expr_ref result(m); expr_abstract(m, 0, num_bound, (expr* const*)bound, n, result); if (num_bound > 0) { ptr_vector<sort> sorts; svector<symbol> names; for (unsigned i = 0; i < num_bound; ++i) { sorts.push_back(m.get_sort(bound[i])); names.push_back(bound[i]->get_decl()->get_name()); } result = m.mk_quantifier(is_forall, num_bound, sorts.c_ptr(), names.c_ptr(), result); } return result; }
static void test(app* var, expr_ref& fml) { ast_manager& m = fml.get_manager(); smt_params params; params.m_model = true; symbol x_name(var->get_decl()->get_name()); sort* x_sort = m.get_sort(var); expr_ref pr(m); expr_ref_vector lits(m); flatten_and(fml, lits); model_ref md; { smt::context ctx(m, params); ctx.assert_expr(fml); lbool result = ctx.check(); if (result != l_true) return; ctx.get_model(md); } VERIFY(qe::arith_project(*md, var, lits)); pr = mk_and(lits); std::cout << "original: " << mk_pp(fml, m) << "\n"; std::cout << "projected: " << mk_pp(pr, m) << "\n"; // projection is consistent with model. VERIFY(md->is_true(pr)); // projection implies E x. fml { qe::expr_quant_elim qelim(m, params); expr_ref result(m), efml(m); expr* x = var; expr_abstract(m, 0, 1, &x, fml, efml); efml = m.mk_exists(1, &x_sort, &x_name, efml); qelim(m.mk_true(), efml, result); smt::context ctx(m, params); ctx.assert_expr(pr); ctx.assert_expr(m.mk_not(result)); std::cout << "exists: " << pr << " =>\n" << result << "\n"; VERIFY(l_false == ctx.check()); } std::cout << "\n"; }
void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) { expr * curr = 0, *b = 0; SASSERT(n->get_ref_count() > 0); m_stack.push_back(n); for (unsigned i = 0; i < num_bound; ++i) { b = bound[i]; expr* v = m.mk_var(base + num_bound - i - 1, m.get_sort(b)); m_pinned.push_back(v); m_map.insert(b, v); } while(!m_stack.empty()) { curr = m_stack.back(); if (m_map.contains(curr)) { m_stack.pop_back(); continue; } switch(curr->get_kind()) { case AST_VAR: { m_map.insert(curr, curr); m_stack.pop_back(); break; } case AST_APP: { app* a = to_app(curr); bool all_visited = true; m_args.reset(); for (unsigned i = 0; i < a->get_num_args(); ++i) { if (!m_map.find(a->get_arg(i), b)) { m_stack.push_back(a->get_arg(i)); all_visited = false; } else { m_args.push_back(b); } } if (all_visited) { b = m.mk_app(a->get_decl(), m_args.size(), m_args.c_ptr()); m_pinned.push_back(b); m_map.insert(curr, b); m_stack.pop_back(); } break; } case AST_QUANTIFIER: { quantifier* q = to_quantifier(curr); expr_ref_buffer patterns(m); expr_ref result1(m); unsigned new_base = base + q->get_num_decls(); for (unsigned i = 0; i < q->get_num_patterns(); ++i) { expr_abstract(m, new_base, num_bound, bound, q->get_pattern(i), result1); patterns.push_back(result1.get()); } expr_abstract(m, new_base, num_bound, bound, q->get_expr(), result1); b = m.update_quantifier(q, patterns.size(), patterns.c_ptr(), result1.get()); m_pinned.push_back(b); m_map.insert(curr, b); m_stack.pop_back(); break; } default: UNREACHABLE(); } } VERIFY (m_map.find(n, b)); result = b; m_pinned.reset(); m_map.reset(); m_stack.reset(); m_args.reset(); }
Z3_ast Z3_API Z3_mk_quantifier_const_ex(Z3_context c, Z3_bool is_forall, unsigned weight, Z3_symbol quantifier_id, Z3_symbol skolem_id, unsigned num_bound, Z3_app const bound[], unsigned num_patterns, Z3_pattern const patterns[], unsigned num_no_patterns, Z3_ast const no_patterns[], Z3_ast body) { Z3_TRY; LOG_Z3_mk_quantifier_const_ex(c, is_forall, weight, quantifier_id, skolem_id, num_bound, bound, num_patterns, patterns, num_no_patterns, no_patterns, body); RESET_ERROR_CODE(); svector<Z3_symbol> names; svector<Z3_sort> types; ptr_vector<expr> bound_asts; if (num_patterns > 0 && num_no_patterns > 0) { SET_ERROR_CODE(Z3_INVALID_USAGE); RETURN_Z3(0); } if (num_bound == 0) { SET_ERROR_CODE(Z3_INVALID_USAGE); RETURN_Z3(0); } for (unsigned i = 0; i < num_bound; ++i) { app* a = to_app(bound[i]); if (a->get_kind() != AST_APP) { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); } symbol s(to_app(a)->get_decl()->get_name()); names.push_back(of_symbol(s)); types.push_back(of_sort(mk_c(c)->m().get_sort(a))); bound_asts.push_back(a); if (a->get_family_id() != null_family_id || a->get_num_args() != 0) { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); } } // Abstract patterns svector<Z3_pattern> _patterns; expr_ref_vector pinned(mk_c(c)->m()); for (unsigned i = 0; i < num_patterns; ++i) { expr_ref result(mk_c(c)->m()); app* pat = to_pattern(patterns[i]); SASSERT(mk_c(c)->m().is_pattern(pat)); expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), pat, result); SASSERT(result.get()->get_kind() == AST_APP); pinned.push_back(result.get()); SASSERT(mk_c(c)->m().is_pattern(result.get())); _patterns.push_back(of_pattern(result.get())); } svector<Z3_ast> _no_patterns; for (unsigned i = 0; i < num_no_patterns; ++i) { expr_ref result(mk_c(c)->m()); if (!is_app(to_expr(no_patterns[i]))) { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); } app* pat = to_app(to_expr(no_patterns[i])); expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), pat, result); SASSERT(result.get()->get_kind() == AST_APP); pinned.push_back(result.get()); _no_patterns.push_back(of_ast(result.get())); } expr_ref abs_body(mk_c(c)->m()); expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), to_expr(body), abs_body); Z3_ast result = mk_quantifier_ex_core(c, is_forall, weight, quantifier_id, skolem_id, num_patterns, _patterns.c_ptr(), num_no_patterns, _no_patterns.c_ptr(), names.size(), types.c_ptr(), names.c_ptr(), of_ast(abs_body.get())); RETURN_Z3(result); Z3_CATCH_RETURN(0); }