mirror of
https://github.com/Z3Prover/z3
synced 2025-04-25 10:05:32 +00:00
update new assertions
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
5141477809
commit
ebcacaa26d
17 changed files with 331 additions and 199 deletions
|
@ -111,6 +111,71 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_ex
|
|||
return true;
|
||||
}
|
||||
|
||||
bool macro_finder::is_arith_macro(expr * n, proof * pr, vector<justified_expr>& new_fmls) {
|
||||
if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
|
||||
return false;
|
||||
expr * body = to_quantifier(n)->get_expr();
|
||||
unsigned num_decls = to_quantifier(n)->get_num_decls();
|
||||
|
||||
if (!m_autil.is_le(body) && !m_autil.is_ge(body) && !m_manager.is_eq(body))
|
||||
return false;
|
||||
if (!m_autil.is_add(to_app(body)->get_arg(0)))
|
||||
return false;
|
||||
app_ref head(m_manager);
|
||||
expr_ref def(m_manager);
|
||||
bool inv = false;
|
||||
if (!m_util.is_arith_macro(body, num_decls, head, def, inv))
|
||||
return false;
|
||||
app_ref new_body(m_manager);
|
||||
|
||||
if (!inv || m_manager.is_eq(body))
|
||||
new_body = m_manager.mk_app(to_app(body)->get_decl(), head, def);
|
||||
else if (m_autil.is_le(body))
|
||||
new_body = m_autil.mk_ge(head, def);
|
||||
else
|
||||
new_body = m_autil.mk_le(head, def);
|
||||
|
||||
quantifier_ref new_q(m_manager);
|
||||
new_q = m_manager.update_quantifier(to_quantifier(n), new_body);
|
||||
proof * new_pr = 0;
|
||||
if (m_manager.proofs_enabled()) {
|
||||
proof * rw = m_manager.mk_rewrite(n, new_q);
|
||||
new_pr = m_manager.mk_modus_ponens(pr, rw);
|
||||
}
|
||||
if (m_manager.is_eq(body)) {
|
||||
return m_macro_manager.insert(head->get_decl(), new_q, new_pr);
|
||||
}
|
||||
// is ge or le
|
||||
//
|
||||
TRACE("macro_finder", tout << "is_arith_macro: is_ge or is_le\n";);
|
||||
func_decl * f = head->get_decl();
|
||||
func_decl * k = m_manager.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
|
||||
app * k_app = m_manager.mk_app(k, head->get_num_args(), head->get_args());
|
||||
expr_ref_buffer new_rhs_args(m_manager);
|
||||
expr_ref new_rhs2(m_autil.mk_add(def, k_app), m_manager);
|
||||
expr * body1 = m_manager.mk_eq(head, new_rhs2);
|
||||
expr * body2 = m_manager.mk_app(new_body->get_decl(), k_app, m_autil.mk_int(0));
|
||||
quantifier * q1 = m_manager.update_quantifier(new_q, body1);
|
||||
expr * patterns[1] = { m_manager.mk_pattern(k_app) };
|
||||
quantifier * q2 = m_manager.update_quantifier(new_q, 1, patterns, body2);
|
||||
proof* pr1 = 0, *pr2 = 0;
|
||||
if (m_manager.proofs_enabled()) {
|
||||
// new_pr : new_q
|
||||
// rw : [rewrite] new_q ~ q1 & q2
|
||||
// mp : [modus_pones new_pr rw] q1 & q2
|
||||
// pr1 : [and-elim mp] q1
|
||||
// pr2 : [and-elim mp] q2
|
||||
app * q1q2 = m_manager.mk_and(q1,q2);
|
||||
proof * rw = m_manager.mk_oeq_rewrite(new_q, q1q2);
|
||||
proof * mp = m_manager.mk_modus_ponens(new_pr, rw);
|
||||
pr1 = m_manager.mk_and_elim(mp, 0);
|
||||
pr2 = m_manager.mk_and_elim(mp, 1);
|
||||
}
|
||||
new_fmls.push_back(justified_expr(m_manager, q1, pr1));
|
||||
new_fmls.push_back(justified_expr(m_manager, q2, pr2));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
n is of the form: (forall (X) (iff (= (f X) t) def[X]))
|
||||
|
||||
|
@ -152,6 +217,34 @@ static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, e
|
|||
}
|
||||
}
|
||||
|
||||
static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr,
|
||||
vector<justified_expr>& new_fmls) {
|
||||
func_decl * f = head->get_decl();
|
||||
func_decl * k = m.mk_fresh_func_decl(f->get_name(), symbol::null, f->get_arity(), f->get_domain(), f->get_range());
|
||||
app * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
|
||||
app * ite = m.mk_ite(def, t, k_app);
|
||||
app * body_1 = m.mk_eq(head, ite);
|
||||
app * body_2 = m.mk_not(m.mk_eq(k_app, t));
|
||||
quantifier * q1 = m.update_quantifier(q, body_1);
|
||||
proof * pr1 = 0, *pr2 = 0;
|
||||
expr * pats[1] = { m.mk_pattern(k_app) };
|
||||
quantifier * q2 = m.update_quantifier(q, 1, pats, body_2); // erase patterns
|
||||
if (m.proofs_enabled()) {
|
||||
// r : [rewrite] q ~ q1 & q2
|
||||
// pr : q
|
||||
// mp : [modus_pones pr pr1] q1 & q2
|
||||
// pr1 : [and-elim mp] q1
|
||||
// pr2 : [and-elim mp] q2
|
||||
app * q1q2 = m.mk_and(q1,q2);
|
||||
proof * r = m.mk_oeq_rewrite(q, q1q2);
|
||||
proof * mp = m.mk_modus_ponens(pr, r);
|
||||
pr1 = m.mk_and_elim(mp, 0);
|
||||
pr2 = m.mk_and_elim(mp, 1);
|
||||
}
|
||||
new_fmls.push_back(justified_expr(m, q1, pr1));
|
||||
new_fmls.push_back(justified_expr(m, q2, pr2));
|
||||
}
|
||||
|
||||
macro_finder::macro_finder(ast_manager & m, macro_manager & mm):
|
||||
m_manager(m),
|
||||
m_macro_manager(mm),
|
||||
|
@ -216,3 +309,51 @@ void macro_finder::operator()(unsigned num, expr * const * exprs, proof * const
|
|||
}
|
||||
|
||||
|
||||
|
||||
bool macro_finder::expand_macros(unsigned num, justified_expr const * fmls, vector<justified_expr>& new_fmls) {
|
||||
TRACE("macro_finder", tout << "starting expand_macros:\n";
|
||||
m_macro_manager.display(tout););
|
||||
bool found_new_macro = false;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
expr * n = fmls[i].get_fml();
|
||||
proof * pr = m_manager.proofs_enabled() ? fmls[i].get_proof() : 0;
|
||||
expr_ref new_n(m_manager), def(m_manager);
|
||||
proof_ref new_pr(m_manager);
|
||||
m_macro_manager.expand_macros(n, pr, new_n, new_pr);
|
||||
app_ref head(m_manager), t(m_manager);
|
||||
if (is_macro(new_n, head, def) && m_macro_manager.insert(head->get_decl(), to_quantifier(new_n.get()), new_pr)) {
|
||||
TRACE("macro_finder_found", tout << "found new macro: " << head->get_decl()->get_name() << "\n" << new_n << "\n";);
|
||||
found_new_macro = true;
|
||||
}
|
||||
else if (is_arith_macro(new_n, new_pr, new_fmls)) {
|
||||
TRACE("macro_finder_found", tout << "found new arith macro:\n" << new_n << "\n";);
|
||||
found_new_macro = true;
|
||||
}
|
||||
else if (m_util.is_pseudo_predicate_macro(new_n, head, t, def)) {
|
||||
TRACE("macro_finder_found", tout << "found new pseudo macro:\n" << head << "\n" << t << "\n" << def << "\n";);
|
||||
pseudo_predicate_macro2macro(m_manager, head, t, def, to_quantifier(new_n), new_pr, new_fmls);
|
||||
found_new_macro = true;
|
||||
}
|
||||
else {
|
||||
new_fmls.push_back(justified_expr(m_manager, new_n, new_pr));
|
||||
}
|
||||
}
|
||||
return found_new_macro;
|
||||
}
|
||||
|
||||
void macro_finder::operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls) {
|
||||
TRACE("macro_finder", tout << "processing macros...\n";);
|
||||
vector<justified_expr> _new_fmls;
|
||||
if (expand_macros(n, fmls, _new_fmls)) {
|
||||
while (true) {
|
||||
vector<justified_expr> old_fmls;
|
||||
_new_fmls.swap(old_fmls);
|
||||
SASSERT(_new_fmls.empty());
|
||||
if (!expand_macros(old_fmls.size(), old_fmls.c_ptr(), _new_fmls))
|
||||
break;
|
||||
}
|
||||
}
|
||||
new_fmls.append(_new_fmls);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,7 +38,9 @@ class macro_finder {
|
|||
macro_util & m_util;
|
||||
arith_util m_autil;
|
||||
bool expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
bool expand_macros(unsigned n, justified_expr const * fmls, vector<justified_expr>& new_fmls);
|
||||
bool is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
bool is_arith_macro(expr * n, proof * pr, vector<justified_expr>& new_fmls);
|
||||
|
||||
bool is_macro(expr * n, app_ref & head, expr_ref & def);
|
||||
bool is_pseudo_head(expr * n, unsigned num_decls, app * & head, app * & t);
|
||||
|
@ -48,6 +50,7 @@ public:
|
|||
macro_finder(ast_manager & m, macro_manager & mm);
|
||||
~macro_finder();
|
||||
void operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
void operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls);
|
||||
};
|
||||
|
||||
#endif /* MACRO_FINDER_H_ */
|
||||
|
|
|
@ -152,6 +152,14 @@ void macro_manager::mark_forbidden(unsigned n, expr * const * exprs) {
|
|||
for_each_expr(p, visited, exprs[i]);
|
||||
}
|
||||
|
||||
void macro_manager::mark_forbidden(unsigned n, justified_expr const * exprs) {
|
||||
expr_mark visited;
|
||||
macro_manager_ns::proc p(m_forbidden_set, m_forbidden);
|
||||
for (unsigned i = 0; i < n; i++)
|
||||
for_each_expr(p, visited, exprs[i].get_fml());
|
||||
}
|
||||
|
||||
|
||||
void macro_manager::get_head_def(quantifier * q, func_decl * d, app * & head, expr * & def) const {
|
||||
app * body = to_app(q->get_expr());
|
||||
SASSERT(m.is_eq(body) || m.is_iff(body));
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
void pop_scope(unsigned num_scopes);
|
||||
void reset();
|
||||
void mark_forbidden(unsigned n, expr * const * exprs);
|
||||
void mark_forbidden(unsigned n, justified_expr const * exprs);
|
||||
void mark_forbidden(expr * e) { mark_forbidden(1, &e); }
|
||||
bool is_forbidden(func_decl * d) const { return m_forbidden_set.contains(d); }
|
||||
obj_hashtable<func_decl> const & get_forbidden_set() const { return m_forbidden_set; }
|
||||
|
|
|
@ -293,6 +293,44 @@ bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
|
|||
return res;
|
||||
}
|
||||
|
||||
bool quasi_macros::find_macros(unsigned n, justified_expr const * exprs) {
|
||||
TRACE("quasi_macros", tout << "Finding quasi-macros in: " << std::endl;
|
||||
for (unsigned i = 0 ; i < n ; i++)
|
||||
tout << i << ": " << mk_pp(exprs[i].get_fml(), m_manager) << std::endl; );
|
||||
bool res = false;
|
||||
m_occurrences.reset();
|
||||
|
||||
|
||||
// Find out how many non-ground appearences for each uninterpreted function there are
|
||||
for ( unsigned i = 0 ; i < n ; i++ )
|
||||
find_occurrences(exprs[i].get_fml());
|
||||
|
||||
TRACE("quasi_macros", tout << "Occurrences: " << std::endl;
|
||||
for (occurrences_map::iterator it = m_occurrences.begin();
|
||||
it != m_occurrences.end();
|
||||
it++)
|
||||
tout << it->m_key->get_name() << ": " << it->m_value << std::endl; );
|
||||
|
||||
// Find all macros
|
||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
||||
app_ref a(m_manager);
|
||||
expr_ref t(m_manager);
|
||||
if (is_quasi_macro(exprs[i].get_fml(), a, t)) {
|
||||
quantifier_ref macro(m_manager);
|
||||
quasi_macro_to_macro(to_quantifier(exprs[i].get_fml()), a, t, macro);
|
||||
TRACE("quasi_macros", tout << "Found quasi macro: " << mk_pp(exprs[i].get_fml(), m_manager) << std::endl;
|
||||
tout << "Macro: " << mk_pp(macro, m_manager) << std::endl; );
|
||||
proof * pr = 0;
|
||||
if (m_manager.proofs_enabled())
|
||||
pr = m_manager.mk_def_axiom(macro);
|
||||
if (m_macro_manager.insert(a->get_decl(), macro, pr))
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void quasi_macros::apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) {
|
||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
||||
expr_ref r(m_manager), rs(m_manager);
|
||||
|
@ -319,3 +357,27 @@ bool quasi_macros::operator()(unsigned n, expr * const * exprs, proof * const *
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void quasi_macros::apply_macros(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls) {
|
||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
||||
expr_ref r(m_manager), rs(m_manager);
|
||||
proof_ref pr(m_manager), ps(m_manager);
|
||||
proof * p = m_manager.proofs_enabled() ? fmls[i].get_proof() : 0;
|
||||
m_macro_manager.expand_macros(fmls[i].get_fml(), p, r, pr);
|
||||
m_rewriter(r);
|
||||
new_fmls.push_back(justified_expr(m_manager, r, pr));
|
||||
}
|
||||
}
|
||||
|
||||
bool quasi_macros::operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls) {
|
||||
if (find_macros(n, fmls)) {
|
||||
apply_macros(n, fmls, new_fmls);
|
||||
return true;
|
||||
} else {
|
||||
// just copy them over
|
||||
for ( unsigned i = 0 ; i < n ; i++ ) {
|
||||
new_fmls.push_back(fmls[i]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,9 @@ class quasi_macros {
|
|||
|
||||
void find_occurrences(expr * e);
|
||||
bool find_macros(unsigned n, expr * const * exprs);
|
||||
bool find_macros(unsigned n, justified_expr const* expr);
|
||||
void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
void apply_macros(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls);
|
||||
|
||||
public:
|
||||
quasi_macros(ast_manager & m, macro_manager & mm);
|
||||
|
@ -63,6 +65,7 @@ public:
|
|||
\brief Find pure function macros and apply them.
|
||||
*/
|
||||
bool operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
bool operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue