3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 06:03:23 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-08-26 01:33:19 -07:00
commit c03be16039
15 changed files with 487 additions and 438 deletions

View file

@ -1964,7 +1964,7 @@ struct
let from_file (x:optimize) (s:string) = Z3native.optimize_from_file (gc x) x s let from_file (x:optimize) (s:string) = Z3native.optimize_from_file (gc x) x s
let from_string (x:optimize) (s:string) = Z3native.optimize_from_string (gc x) x s let from_string (x:optimize) (s:string) = Z3native.optimize_from_string (gc x) x s
let get_assertions (x:optimize) = AST.ASTVector.to_expr_list (Z3native.optimize_get_assertions (gc x) x) let get_assertions (x:optimize) = AST.ASTVector.to_expr_list (Z3native.optimize_get_assertions (gc x) x)
let get_objectives (x:optimize) = AST.ASTVector.to_expr_list (Z3native.optimize_get_statistics (gc x) x) let get_objectives (x:optimize) = AST.ASTVector.to_expr_list (Z3native.optimize_get_objectives (gc x) x)
end end

View file

@ -25,7 +25,7 @@ Revision History:
bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) { bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) {
if (!is_quantifier(n) || !to_quantifier(n)->is_forall()) if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
return false; return false;
TRACE("macro_finder", tout << "processing: " << mk_pp(n, m_manager) << "\n";); TRACE("macro_finder", tout << "processing: " << mk_pp(n, m) << "\n";);
expr * body = to_quantifier(n)->get_expr(); expr * body = to_quantifier(n)->get_expr();
unsigned num_decls = to_quantifier(n)->get_num_decls(); unsigned num_decls = to_quantifier(n)->get_num_decls();
return m_util.is_simple_macro(body, num_decls, head, def); return m_util.is_simple_macro(body, num_decls, head, def);
@ -45,69 +45,74 @@ bool macro_finder::is_macro(expr * n, app_ref & head, expr_ref & def) {
For case 2 & 3, the new quantifiers are stored in new_exprs and new_prs. For case 2 & 3, the new quantifiers are stored in new_exprs and new_prs.
*/ */
bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) { bool macro_finder::is_arith_macro(expr * n, proof * pr, expr_dependency * dep, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
if (!is_quantifier(n) || !to_quantifier(n)->is_forall()) if (!is_quantifier(n) || !to_quantifier(n)->is_forall())
return false; return false;
expr * body = to_quantifier(n)->get_expr(); expr * body = to_quantifier(n)->get_expr();
unsigned num_decls = to_quantifier(n)->get_num_decls(); 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)) if (!m_autil.is_le(body) && !m_autil.is_ge(body) && !m.is_eq(body))
return false; return false;
if (!m_autil.is_add(to_app(body)->get_arg(0))) if (!m_autil.is_add(to_app(body)->get_arg(0)))
return false; return false;
app_ref head(m_manager); app_ref head(m);
expr_ref def(m_manager); expr_ref def(m);
bool inv = false; bool inv = false;
if (!m_util.is_arith_macro(body, num_decls, head, def, inv)) if (!m_util.is_arith_macro(body, num_decls, head, def, inv))
return false; return false;
app_ref new_body(m_manager); app_ref new_body(m);
if (!inv || m_manager.is_eq(body)) if (!inv || m.is_eq(body))
new_body = m_manager.mk_app(to_app(body)->get_decl(), head, def); new_body = m.mk_app(to_app(body)->get_decl(), head, def);
else if (m_autil.is_le(body)) else if (m_autil.is_le(body))
new_body = m_autil.mk_ge(head, def); new_body = m_autil.mk_ge(head, def);
else else
new_body = m_autil.mk_le(head, def); new_body = m_autil.mk_le(head, def);
quantifier_ref new_q(m_manager); quantifier_ref new_q(m);
new_q = m_manager.update_quantifier(to_quantifier(n), new_body); new_q = m.update_quantifier(to_quantifier(n), new_body);
proof * new_pr = 0; proof * new_pr = 0;
if (m_manager.proofs_enabled()) { if (m.proofs_enabled()) {
proof * rw = m_manager.mk_rewrite(n, new_q); proof * rw = m.mk_rewrite(n, new_q);
new_pr = m_manager.mk_modus_ponens(pr, rw); new_pr = m.mk_modus_ponens(pr, rw);
} }
if (m_manager.is_eq(body)) { expr_dependency * new_dep = dep;
return m_macro_manager.insert(head->get_decl(), new_q, new_pr); if (m.is_eq(body)) {
return m_macro_manager.insert(head->get_decl(), new_q, new_pr, new_dep);
} }
// is ge or le // is ge or le
// //
TRACE("macro_finder", tout << "is_arith_macro: is_ge or is_le\n";); TRACE("macro_finder", tout << "is_arith_macro: is_ge or is_le\n";);
func_decl * f = head->get_decl(); 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()); 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_manager.mk_app(k, head->get_num_args(), head->get_args()); app * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
expr_ref_buffer new_rhs_args(m_manager); expr_ref_buffer new_rhs_args(m);
expr_ref new_rhs2(m_autil.mk_add(def, k_app), m_manager); expr_ref new_rhs2(m_autil.mk_add(def, k_app), m);
expr * body1 = m_manager.mk_eq(head, new_rhs2); expr * body1 = m.mk_eq(head, new_rhs2);
expr * body2 = m_manager.mk_app(new_body->get_decl(), k_app, m_autil.mk_int(0)); expr * body2 = m.mk_app(new_body->get_decl(), k_app, m_autil.mk_int(0));
quantifier * q1 = m_manager.update_quantifier(new_q, body1); quantifier * q1 = m.update_quantifier(new_q, body1);
expr * patterns[1] = { m_manager.mk_pattern(k_app) }; expr * patterns[1] = { m.mk_pattern(k_app) };
quantifier * q2 = m_manager.update_quantifier(new_q, 1, patterns, body2); quantifier * q2 = m.update_quantifier(new_q, 1, patterns, body2);
new_exprs.push_back(q1); new_exprs.push_back(q1);
new_exprs.push_back(q2); new_exprs.push_back(q2);
if (m_manager.proofs_enabled()) { if (m.proofs_enabled()) {
// new_pr : new_q // new_pr : new_q
// rw : [rewrite] new_q ~ q1 & q2 // rw : [rewrite] new_q ~ q1 & q2
// mp : [modus_pones new_pr rw] q1 & q2 // mp : [modus_pones new_pr rw] q1 & q2
// pr1 : [and-elim mp] q1 // pr1 : [and-elim mp] q1
// pr2 : [and-elim mp] q2 // pr2 : [and-elim mp] q2
app * q1q2 = m_manager.mk_and(q1,q2); app * q1q2 = m.mk_and(q1,q2);
proof * rw = m_manager.mk_oeq_rewrite(new_q, q1q2); proof * rw = m.mk_oeq_rewrite(new_q, q1q2);
proof * mp = m_manager.mk_modus_ponens(new_pr, rw); proof * mp = m.mk_modus_ponens(new_pr, rw);
proof * pr1 = m_manager.mk_and_elim(mp, 0); proof * pr1 = m.mk_and_elim(mp, 0);
proof * pr2 = m_manager.mk_and_elim(mp, 1); proof * pr2 = m.mk_and_elim(mp, 1);
new_prs.push_back(pr1); new_prs.push_back(pr1);
new_prs.push_back(pr2); new_prs.push_back(pr2);
} }
if (dep) {
new_deps.push_back(new_dep);
new_deps.push_back(new_dep);
}
return true; return true;
} }
@ -117,62 +122,62 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, vector<justified_expr>&
expr * body = to_quantifier(n)->get_expr(); expr * body = to_quantifier(n)->get_expr();
unsigned num_decls = to_quantifier(n)->get_num_decls(); 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)) if (!m_autil.is_le(body) && !m_autil.is_ge(body) && !m.is_eq(body))
return false; return false;
if (!m_autil.is_add(to_app(body)->get_arg(0))) if (!m_autil.is_add(to_app(body)->get_arg(0)))
return false; return false;
app_ref head(m_manager); app_ref head(m);
expr_ref def(m_manager); expr_ref def(m);
bool inv = false; bool inv = false;
if (!m_util.is_arith_macro(body, num_decls, head, def, inv)) if (!m_util.is_arith_macro(body, num_decls, head, def, inv))
return false; return false;
app_ref new_body(m_manager); app_ref new_body(m);
if (!inv || m_manager.is_eq(body)) if (!inv || m.is_eq(body))
new_body = m_manager.mk_app(to_app(body)->get_decl(), head, def); new_body = m.mk_app(to_app(body)->get_decl(), head, def);
else if (m_autil.is_le(body)) else if (m_autil.is_le(body))
new_body = m_autil.mk_ge(head, def); new_body = m_autil.mk_ge(head, def);
else else
new_body = m_autil.mk_le(head, def); new_body = m_autil.mk_le(head, def);
quantifier_ref new_q(m_manager); quantifier_ref new_q(m);
new_q = m_manager.update_quantifier(to_quantifier(n), new_body); new_q = m.update_quantifier(to_quantifier(n), new_body);
proof * new_pr = 0; proof * new_pr = 0;
if (m_manager.proofs_enabled()) { if (m.proofs_enabled()) {
proof * rw = m_manager.mk_rewrite(n, new_q); proof * rw = m.mk_rewrite(n, new_q);
new_pr = m_manager.mk_modus_ponens(pr, rw); new_pr = m.mk_modus_ponens(pr, rw);
} }
if (m_manager.is_eq(body)) { if (m.is_eq(body)) {
return m_macro_manager.insert(head->get_decl(), new_q, new_pr); return m_macro_manager.insert(head->get_decl(), new_q, new_pr);
} }
// is ge or le // is ge or le
// //
TRACE("macro_finder", tout << "is_arith_macro: is_ge or is_le\n";); TRACE("macro_finder", tout << "is_arith_macro: is_ge or is_le\n";);
func_decl * f = head->get_decl(); 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()); 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_manager.mk_app(k, head->get_num_args(), head->get_args()); app * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
expr_ref_buffer new_rhs_args(m_manager); expr_ref_buffer new_rhs_args(m);
expr_ref new_rhs2(m_autil.mk_add(def, k_app), m_manager); expr_ref new_rhs2(m_autil.mk_add(def, k_app), m);
expr * body1 = m_manager.mk_eq(head, new_rhs2); expr * body1 = m.mk_eq(head, new_rhs2);
expr * body2 = m_manager.mk_app(new_body->get_decl(), k_app, m_autil.mk_int(0)); expr * body2 = m.mk_app(new_body->get_decl(), k_app, m_autil.mk_int(0));
quantifier * q1 = m_manager.update_quantifier(new_q, body1); quantifier * q1 = m.update_quantifier(new_q, body1);
expr * patterns[1] = { m_manager.mk_pattern(k_app) }; expr * patterns[1] = { m.mk_pattern(k_app) };
quantifier * q2 = m_manager.update_quantifier(new_q, 1, patterns, body2); quantifier * q2 = m.update_quantifier(new_q, 1, patterns, body2);
proof* pr1 = 0, *pr2 = 0; proof* pr1 = 0, *pr2 = 0;
if (m_manager.proofs_enabled()) { if (m.proofs_enabled()) {
// new_pr : new_q // new_pr : new_q
// rw : [rewrite] new_q ~ q1 & q2 // rw : [rewrite] new_q ~ q1 & q2
// mp : [modus_pones new_pr rw] q1 & q2 // mp : [modus_pones new_pr rw] q1 & q2
// pr1 : [and-elim mp] q1 // pr1 : [and-elim mp] q1
// pr2 : [and-elim mp] q2 // pr2 : [and-elim mp] q2
app * q1q2 = m_manager.mk_and(q1,q2); app * q1q2 = m.mk_and(q1,q2);
proof * rw = m_manager.mk_oeq_rewrite(new_q, q1q2); proof * rw = m.mk_oeq_rewrite(new_q, q1q2);
proof * mp = m_manager.mk_modus_ponens(new_pr, rw); proof * mp = m.mk_modus_ponens(new_pr, rw);
pr1 = m_manager.mk_and_elim(mp, 0); pr1 = m.mk_and_elim(mp, 0);
pr2 = m_manager.mk_and_elim(mp, 1); pr2 = m.mk_and_elim(mp, 1);
} }
new_fmls.push_back(justified_expr(m_manager, q1, pr1)); new_fmls.push_back(justified_expr(m, q1, pr1));
new_fmls.push_back(justified_expr(m_manager, q2, pr2)); new_fmls.push_back(justified_expr(m, q2, pr2));
return true; return true;
} }
@ -188,8 +193,8 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, vector<justified_expr>&
The new quantifiers and proofs are stored in new_exprs and new_prs The new quantifiers and proofs are stored in new_exprs and new_prs
*/ */
static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr, static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr, expr_dependency * dep,
expr_ref_vector & new_exprs, proof_ref_vector & new_prs) { expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps ) {
func_decl * f = head->get_decl(); 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()); 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 * k_app = m.mk_app(k, head->get_num_args(), head->get_args());
@ -215,6 +220,8 @@ static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, e
new_prs.push_back(pr1); new_prs.push_back(pr1);
new_prs.push_back(pr2); new_prs.push_back(pr2);
} }
new_deps.push_back(dep);
new_deps.push_back(dep);
} }
static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr, static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, expr * def, quantifier * q, proof * pr,
@ -246,7 +253,7 @@ static void pseudo_predicate_macro2macro(ast_manager & m, app * head, app * t, e
} }
macro_finder::macro_finder(ast_manager & m, macro_manager & mm): macro_finder::macro_finder(ast_manager & m, macro_manager & mm):
m_manager(m), m(m),
m_macro_manager(mm), m_macro_manager(mm),
m_util(mm.get_util()), m_util(mm.get_util()),
m_autil(m) { m_autil(m) {
@ -255,57 +262,67 @@ macro_finder::macro_finder(ast_manager & m, macro_manager & mm):
macro_finder::~macro_finder() { macro_finder::~macro_finder() {
} }
bool macro_finder::expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) { bool macro_finder::expand_macros(unsigned num, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
TRACE("macro_finder", tout << "starting expand_macros:\n"; TRACE("macro_finder", tout << "starting expand_macros:\n";
m_macro_manager.display(tout);); m_macro_manager.display(tout););
bool found_new_macro = false; bool found_new_macro = false;
for (unsigned i = 0; i < num; i++) { for (unsigned i = 0; i < num; i++) {
expr * n = exprs[i]; expr * n = exprs[i];
proof * pr = m_manager.proofs_enabled() ? prs[i] : 0; proof * pr = m.proofs_enabled() ? prs[i] : 0;
expr_ref new_n(m_manager), def(m_manager); expr_dependency * depi = deps != 0 ? deps[i] : 0;
proof_ref new_pr(m_manager); expr_ref new_n(m), def(m);
m_macro_manager.expand_macros(n, pr, new_n, new_pr); proof_ref new_pr(m);
app_ref head(m_manager), t(m_manager); expr_dependency_ref new_dep(m);
if (is_macro(new_n, head, def) && m_macro_manager.insert(head->get_decl(), to_quantifier(new_n.get()), new_pr)) { m_macro_manager.expand_macros(n, pr, depi, new_n, new_pr, new_dep);
app_ref head(m), t(m);
if (is_macro(new_n, head, def) && m_macro_manager.insert(head->get_decl(), to_quantifier(new_n.get()), new_pr, new_dep)) {
TRACE("macro_finder_found", tout << "found new macro: " << head->get_decl()->get_name() << "\n" << new_n << "\n";); TRACE("macro_finder_found", tout << "found new macro: " << head->get_decl()->get_name() << "\n" << new_n << "\n";);
found_new_macro = true; found_new_macro = true;
} }
else if (is_arith_macro(new_n, new_pr, new_exprs, new_prs)) { else if (is_arith_macro(new_n, new_pr, new_dep, new_exprs, new_prs, new_deps)) {
TRACE("macro_finder_found", tout << "found new arith macro:\n" << new_n << "\n";); TRACE("macro_finder_found", tout << "found new arith macro:\n" << new_n << "\n";);
found_new_macro = true; found_new_macro = true;
} }
else if (m_util.is_pseudo_predicate_macro(new_n, head, t, def)) { 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";); 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_exprs, new_prs); pseudo_predicate_macro2macro(m, head, t, def, to_quantifier(new_n), new_pr, new_dep, new_exprs, new_prs, new_deps);
found_new_macro = true; found_new_macro = true;
} }
else { else {
new_exprs.push_back(new_n); new_exprs.push_back(new_n);
if (m_manager.proofs_enabled()) if (m.proofs_enabled())
new_prs.push_back(new_pr); new_prs.push_back(new_pr);
if (deps != 0)
new_deps.push_back(new_dep);
} }
} }
return found_new_macro; return found_new_macro;
} }
void macro_finder::operator()(unsigned num, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) { void macro_finder::operator()(unsigned num, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
TRACE("macro_finder", tout << "processing macros...\n";); TRACE("macro_finder", tout << "processing macros...\n";);
expr_ref_vector _new_exprs(m_manager); expr_ref_vector _new_exprs(m);
proof_ref_vector _new_prs(m_manager); proof_ref_vector _new_prs(m);
if (expand_macros(num, exprs, prs, _new_exprs, _new_prs)) { expr_dependency_ref_vector _new_deps(m);
if (expand_macros(num, exprs, prs, deps, _new_exprs, _new_prs, _new_deps)) {
while (true) { while (true) {
expr_ref_vector old_exprs(m_manager); expr_ref_vector old_exprs(m);
proof_ref_vector old_prs(m_manager); proof_ref_vector old_prs(m);
expr_dependency_ref_vector old_deps(m);
_new_exprs.swap(old_exprs); _new_exprs.swap(old_exprs);
_new_prs.swap(old_prs); _new_prs.swap(old_prs);
_new_deps.swap(old_deps);
SASSERT(_new_exprs.empty()); SASSERT(_new_exprs.empty());
SASSERT(_new_prs.empty()); SASSERT(_new_prs.empty());
if (!expand_macros(old_exprs.size(), old_exprs.c_ptr(), old_prs.c_ptr(), _new_exprs, _new_prs)) SASSERT(_new_deps.empty());
if (!expand_macros(old_exprs.size(), old_exprs.c_ptr(), old_prs.c_ptr(), old_deps.c_ptr(),
_new_exprs, _new_prs, _new_deps))
break; break;
} }
} }
new_exprs.append(_new_exprs); new_exprs.append(_new_exprs);
new_prs.append(_new_prs); new_prs.append(_new_prs);
new_deps.append(_new_deps);
} }
@ -316,11 +333,12 @@ bool macro_finder::expand_macros(unsigned num, justified_expr const * fmls, vect
bool found_new_macro = false; bool found_new_macro = false;
for (unsigned i = 0; i < num; i++) { for (unsigned i = 0; i < num; i++) {
expr * n = fmls[i].get_fml(); expr * n = fmls[i].get_fml();
proof * pr = m_manager.proofs_enabled() ? fmls[i].get_proof() : 0; proof * pr = m.proofs_enabled() ? fmls[i].get_proof() : 0;
expr_ref new_n(m_manager), def(m_manager); expr_ref new_n(m), def(m);
proof_ref new_pr(m_manager); proof_ref new_pr(m);
m_macro_manager.expand_macros(n, pr, new_n, new_pr); expr_dependency_ref new_dep(m);
app_ref head(m_manager), t(m_manager); m_macro_manager.expand_macros(n, pr, 0, new_n, new_pr, new_dep);
app_ref head(m), t(m);
if (is_macro(new_n, head, def) && m_macro_manager.insert(head->get_decl(), to_quantifier(new_n.get()), new_pr)) { 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";); TRACE("macro_finder_found", tout << "found new macro: " << head->get_decl()->get_name() << "\n" << new_n << "\n";);
found_new_macro = true; found_new_macro = true;
@ -331,11 +349,11 @@ bool macro_finder::expand_macros(unsigned num, justified_expr const * fmls, vect
} }
else if (m_util.is_pseudo_predicate_macro(new_n, head, t, def)) { 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";); 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); pseudo_predicate_macro2macro(m, head, t, def, to_quantifier(new_n), new_pr, new_fmls);
found_new_macro = true; found_new_macro = true;
} }
else { else {
new_fmls.push_back(justified_expr(m_manager, new_n, new_pr)); new_fmls.push_back(justified_expr(m, new_n, new_pr));
} }
} }
return found_new_macro; return found_new_macro;

View file

@ -22,34 +22,28 @@ Revision History:
#include "ast/macros/macro_manager.h" #include "ast/macros/macro_manager.h"
bool is_macro_head(expr * n, unsigned num_decls);
bool is_simple_macro(ast_manager & m, expr * n, unsigned num_decls, obj_hashtable<func_decl> const * forbidden_set, app * & head, expr * & def);
inline bool is_simple_macro(ast_manager & m, expr * n, unsigned num_decls, app * & head, expr * & def) {
return is_simple_macro(m, n, num_decls, 0, head, def);
}
/** /**
\brief Macro finder is responsible for finding universally quantified sub-formulas that can be used \brief Macro finder is responsible for finding universally quantified sub-formulas that can be used
as macros. as macros.
*/ */
class macro_finder { class macro_finder {
ast_manager & m_manager; ast_manager & m;
macro_manager & m_macro_manager; macro_manager & m_macro_manager;
macro_util & m_util; macro_util & m_util;
arith_util m_autil; 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 num, expr * const * exprs, proof * const * prs, expr_dependency * const* deps,
expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector& new_deps);
bool expand_macros(unsigned n, justified_expr const * fmls, vector<justified_expr>& new_fmls); 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, 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_arith_macro(expr * n, proof * pr, vector<justified_expr>& new_fmls);
bool is_arith_macro(expr * n, proof * pr, expr_dependency * dep, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
bool is_macro(expr * n, app_ref & head, expr_ref & def); bool is_macro(expr * n, app_ref & head, expr_ref & def);
bool is_pseudo_head(expr * n, unsigned num_decls, app * & head, app * & t);
bool is_pseudo_predicate_macro(expr * n, app * & head, app * & t, expr * & def);
public: public:
macro_finder(ast_manager & m, macro_manager & mm); macro_finder(ast_manager & m, macro_manager & mm);
~macro_finder(); ~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, expr * const * exprs, proof * const * prs, expr_dependency * const* deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
void operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls); void operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls);
}; };

View file

@ -34,6 +34,7 @@ macro_manager::macro_manager(ast_manager & m):
m_decls(m), m_decls(m),
m_macros(m), m_macros(m),
m_macro_prs(m), m_macro_prs(m),
m_macro_deps(m),
m_forbidden(m), m_forbidden(m),
m_deps(m) { m_deps(m) {
m_util.set_forbidden_set(&m_forbidden_set); m_util.set_forbidden_set(&m_forbidden_set);
@ -64,11 +65,13 @@ void macro_manager::restore_decls(unsigned old_sz) {
m_deps.erase(m_decls.get(i)); m_deps.erase(m_decls.get(i));
if (m.proofs_enabled()) if (m.proofs_enabled())
m_decl2macro_pr.erase(m_decls.get(i)); m_decl2macro_pr.erase(m_decls.get(i));
m_decl2macro_dep.erase(m_decls.get(i));
} }
m_decls.shrink(old_sz); m_decls.shrink(old_sz);
m_macros.shrink(old_sz); m_macros.shrink(old_sz);
if (m.proofs_enabled()) if (m.proofs_enabled())
m_macro_prs.shrink(old_sz); m_macro_prs.shrink(old_sz);
m_macro_deps.shrink(old_sz);
} }
void macro_manager::restore_forbidden(unsigned old_sz) { void macro_manager::restore_forbidden(unsigned old_sz) {
@ -81,16 +84,18 @@ void macro_manager::restore_forbidden(unsigned old_sz) {
void macro_manager::reset() { void macro_manager::reset() {
m_decl2macro.reset(); m_decl2macro.reset();
m_decl2macro_pr.reset(); m_decl2macro_pr.reset();
m_decl2macro_dep.reset();
m_decls.reset(); m_decls.reset();
m_macros.reset(); m_macros.reset();
m_macro_prs.reset(); m_macro_prs.reset();
m_macro_deps.reset();
m_scopes.reset(); m_scopes.reset();
m_forbidden_set.reset(); m_forbidden_set.reset();
m_forbidden.reset(); m_forbidden.reset();
m_deps.reset(); m_deps.reset();
} }
bool macro_manager::insert(func_decl * f, quantifier * q, proof * pr) { bool macro_manager::insert(func_decl * f, quantifier * q, proof * pr, expr_dependency* dep) {
TRACE("macro_insert", tout << "trying to create macro: " << f->get_name() << "\n" << mk_pp(q, m) << "\n";); TRACE("macro_insert", tout << "trying to create macro: " << f->get_name() << "\n" << mk_pp(q, m) << "\n";);
// if we already have a macro for f then return false; // if we already have a macro for f then return false;
@ -117,6 +122,8 @@ bool macro_manager::insert(func_decl * f, quantifier * q, proof * pr) {
m_macro_prs.push_back(pr); m_macro_prs.push_back(pr);
m_decl2macro_pr.insert(f, pr); m_decl2macro_pr.insert(f, pr);
} }
m_macro_deps.push_back(dep);
m_decl2macro_dep.insert(f, dep);
TRACE("macro_insert", tout << "A macro was successfully created for: " << f->get_name() << "\n";); TRACE("macro_insert", tout << "A macro was successfully created for: " << f->get_name() << "\n";);
@ -307,7 +314,7 @@ struct macro_manager::macro_expander_rw : public rewriter_tpl<macro_manager::mac
}; };
void macro_manager::expand_macros(expr * n, proof * pr, expr_ref & r, proof_ref & new_pr) { void macro_manager::expand_macros(expr * n, proof * pr, expr_dependency * dep, expr_ref & r, proof_ref & new_pr, expr_dependency_ref & new_dep) {
if (has_macros()) { if (has_macros()) {
// Expand macros with "real" proof production support (NO rewrite*) // Expand macros with "real" proof production support (NO rewrite*)
expr_ref old_n(m); expr_ref old_n(m);
@ -339,6 +346,7 @@ void macro_manager::expand_macros(expr * n, proof * pr, expr_ref & r, proof_ref
else { else {
r = n; r = n;
new_pr = pr; new_pr = pr;
new_dep = dep;
} }
} }

View file

@ -40,9 +40,11 @@ class macro_manager {
obj_map<func_decl, quantifier *> m_decl2macro; // func-decl -> quantifier obj_map<func_decl, quantifier *> m_decl2macro; // func-decl -> quantifier
obj_map<func_decl, proof *> m_decl2macro_pr; // func-decl -> quantifier_proof obj_map<func_decl, proof *> m_decl2macro_pr; // func-decl -> quantifier_proof
obj_map<func_decl, expr_dependency *> m_decl2macro_dep; // func-decl -> unsat core dependency
func_decl_ref_vector m_decls; func_decl_ref_vector m_decls;
quantifier_ref_vector m_macros; quantifier_ref_vector m_macros;
proof_ref_vector m_macro_prs; proof_ref_vector m_macro_prs;
expr_dependency_ref_vector m_macro_deps;
obj_hashtable<func_decl> m_forbidden_set; obj_hashtable<func_decl> m_forbidden_set;
func_decl_ref_vector m_forbidden; func_decl_ref_vector m_forbidden;
struct scope { struct scope {
@ -64,7 +66,7 @@ public:
~macro_manager(); ~macro_manager();
ast_manager & get_manager() const { return m; } ast_manager & get_manager() const { return m; }
macro_util & get_util() { return m_util; } macro_util & get_util() { return m_util; }
bool insert(func_decl * f, quantifier * m, proof * pr); bool insert(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep = 0);
bool has_macros() const { return !m_macros.empty(); } bool has_macros() const { return !m_macros.empty(); }
void push_scope(); void push_scope();
void pop_scope(unsigned num_scopes); void pop_scope(unsigned num_scopes);
@ -81,7 +83,7 @@ public:
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const; func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const;
quantifier * get_macro_quantifier(func_decl * f) const { quantifier * q = 0; m_decl2macro.find(f, q); return q; } quantifier * get_macro_quantifier(func_decl * f) const { quantifier * q = 0; m_decl2macro.find(f, q); return q; }
void get_head_def(quantifier * q, func_decl * d, app * & head, expr * & def) const; void get_head_def(quantifier * q, func_decl * d, app * & head, expr * & def) const;
void expand_macros(expr * n, proof * pr, expr_ref & r, proof_ref & new_pr); void expand_macros(expr * n, proof * pr, expr_dependency * dep, expr_ref & r, proof_ref & new_pr, expr_dependency_ref & new_dep);
}; };

View file

@ -264,17 +264,16 @@ bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
// Find out how many non-ground appearences for each uninterpreted function there are // Find out how many non-ground appearences for each uninterpreted function there are
for ( unsigned i = 0 ; i < n ; i++ ) for (unsigned i = 0 ; i < n ; i++)
find_occurrences(exprs[i]); find_occurrences(exprs[i]);
TRACE("quasi_macros", tout << "Occurrences: " << std::endl; TRACE("quasi_macros",
for (occurrences_map::iterator it = m_occurrences.begin(); tout << "Occurrences: " << std::endl;
it != m_occurrences.end(); for (auto & kd : m_occurrences)
it++) tout << kd.m_key->get_name() << ": " << kd.m_value << std::endl; );
tout << it->m_key->get_name() << ": " << it->m_value << std::endl; );
// Find all macros // Find all macros
for ( unsigned i = 0 ; i < n ; i++ ) { for (unsigned i = 0 ; i < n ; i++) {
app_ref a(m_manager); app_ref a(m_manager);
expr_ref t(m_manager); expr_ref t(m_manager);
if (is_quasi_macro(exprs[i], a, t)) { if (is_quasi_macro(exprs[i], a, t)) {
@ -285,7 +284,8 @@ bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
proof * pr = 0; proof * pr = 0;
if (m_manager.proofs_enabled()) if (m_manager.proofs_enabled())
pr = m_manager.mk_def_axiom(macro); pr = m_manager.mk_def_axiom(macro);
if (m_macro_manager.insert(a->get_decl(), macro, pr)) expr_dependency * dep = 0;
if (m_macro_manager.insert(a->get_decl(), macro, pr, dep))
res = true; res = true;
} }
} }
@ -331,23 +331,27 @@ bool quasi_macros::find_macros(unsigned n, justified_expr const * exprs) {
return res; 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) { void quasi_macros::apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const* deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector& new_deps) {
for ( unsigned i = 0 ; i < n ; i++ ) { for ( unsigned i = 0 ; i < n ; i++ ) {
expr_ref r(m_manager), rs(m_manager); expr_ref r(m_manager), rs(m_manager);
proof_ref pr(m_manager), ps(m_manager); proof_ref pr(m_manager), ps(m_manager);
expr_dependency_ref dep(m_manager);
proof * p = m_manager.proofs_enabled() ? prs[i] : 0; proof * p = m_manager.proofs_enabled() ? prs[i] : 0;
m_macro_manager.expand_macros(exprs[i], p, r, pr);
m_macro_manager.expand_macros(exprs[i], p, deps[i], r, pr, dep);
m_rewriter(r); m_rewriter(r);
new_exprs.push_back(r); new_exprs.push_back(r);
new_prs.push_back(ps); new_prs.push_back(ps);
new_deps.push_back(dep);
} }
} }
bool quasi_macros::operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs) { bool quasi_macros::operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps) {
if (find_macros(n, exprs)) { if (find_macros(n, exprs)) {
apply_macros(n, exprs, prs, new_exprs, new_prs); apply_macros(n, exprs, prs, deps, new_exprs, new_prs, new_deps);
return true; return true;
} else { }
else {
// just copy them over // just copy them over
for ( unsigned i = 0 ; i < n ; i++ ) { for ( unsigned i = 0 ; i < n ; i++ ) {
new_exprs.push_back(exprs[i]); new_exprs.push_back(exprs[i]);
@ -363,7 +367,8 @@ void quasi_macros::apply_macros(unsigned n, justified_expr const* fmls, vector<j
expr_ref r(m_manager), rs(m_manager); expr_ref r(m_manager), rs(m_manager);
proof_ref pr(m_manager), ps(m_manager); proof_ref pr(m_manager), ps(m_manager);
proof * p = m_manager.proofs_enabled() ? fmls[i].get_proof() : 0; proof * p = m_manager.proofs_enabled() ? fmls[i].get_proof() : 0;
m_macro_manager.expand_macros(fmls[i].get_fml(), p, r, pr); expr_dependency_ref dep(m_manager);
m_macro_manager.expand_macros(fmls[i].get_fml(), p, 0, r, pr, dep);
m_rewriter(r); m_rewriter(r);
new_fmls.push_back(justified_expr(m_manager, r, pr)); new_fmls.push_back(justified_expr(m_manager, r, pr));
} }

View file

@ -54,7 +54,8 @@ class quasi_macros {
void find_occurrences(expr * e); void find_occurrences(expr * e);
bool find_macros(unsigned n, expr * const * exprs); bool find_macros(unsigned n, expr * const * exprs);
bool find_macros(unsigned n, justified_expr const* expr); 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, expr * const * exprs, proof * const * prs, expr_dependency * const* deps,
expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector& new_deps);
void apply_macros(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls); void apply_macros(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls);
public: public:
@ -64,8 +65,10 @@ public:
/** /**
\brief Find pure function macros and apply them. \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, 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); bool operator()(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls);
bool operator()(unsigned n, expr * const * exprs, proof * const * prs, expr_dependency * const * deps, expr_ref_vector & new_exprs, proof_ref_vector & new_prs, expr_dependency_ref_vector & new_deps);
}; };
#endif #endif

View file

@ -389,8 +389,12 @@ void asserted_formulas::find_macros_core() {
expr_ref_vector new_exprs(m); expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m); proof_ref_vector new_prs(m);
unsigned sz = m_asserted_formulas.size(); unsigned sz = m_asserted_formulas.size();
m_macro_finder->operator()(sz - m_asserted_qhead, m_asserted_formulas.c_ptr() + m_asserted_qhead, expr_dependency_ref_vector new_deps(m);
m_asserted_formula_prs.c_ptr() + m_asserted_qhead, new_exprs, new_prs); m_macro_finder->operator()(sz - m_asserted_qhead,
m_asserted_formulas.c_ptr() + m_asserted_qhead,
m_asserted_formula_prs.c_ptr() + m_asserted_qhead,
0, // 0 == No dependency tracking
new_exprs, new_prs, new_deps);
swap_asserted_formulas(new_exprs, new_prs); swap_asserted_formulas(new_exprs, new_prs);
reduce_and_solve(); reduce_and_solve();
} }
@ -412,14 +416,17 @@ void asserted_formulas::apply_quasi_macros() {
TRACE("before_quasi_macros", display(tout);); TRACE("before_quasi_macros", display(tout););
expr_ref_vector new_exprs(m); expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m); proof_ref_vector new_prs(m);
expr_dependency_ref_vector new_deps(m);
quasi_macros proc(m, m_macro_manager); quasi_macros proc(m, m_macro_manager);
while (proc(m_asserted_formulas.size() - m_asserted_qhead, while (proc(m_asserted_formulas.size() - m_asserted_qhead,
m_asserted_formulas.c_ptr() + m_asserted_qhead, m_asserted_formulas.c_ptr() + m_asserted_qhead,
m_asserted_formula_prs.c_ptr() + m_asserted_qhead, m_asserted_formula_prs.c_ptr() + m_asserted_qhead,
new_exprs, new_prs)) { 0, // 0 == No dependency tracking
new_exprs, new_prs, new_deps)) {
swap_asserted_formulas(new_exprs, new_prs); swap_asserted_formulas(new_exprs, new_prs);
new_exprs.reset(); new_exprs.reset();
new_prs.reset(); new_prs.reset();
new_deps.reset();
} }
TRACE("after_quasi_macros", display(tout);); TRACE("after_quasi_macros", display(tout););
reduce_and_solve(); reduce_and_solve();

View file

@ -144,9 +144,7 @@ public:
func_decl * get_macro_func_decl(unsigned i) const { return m_macro_manager.get_macro_func_decl(i); } func_decl * get_macro_func_decl(unsigned i) const { return m_macro_manager.get_macro_func_decl(i); }
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_macro_manager.get_macro_interpretation(i, interp); } func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_macro_manager.get_macro_interpretation(i, interp); }
quantifier * get_macro_quantifier(func_decl * f) const { return m_macro_manager.get_macro_quantifier(f); } quantifier * get_macro_quantifier(func_decl * f) const { return m_macro_manager.get_macro_quantifier(f); }
// auxiliary function used to create a logic context based on a model. void insert_macro(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep) { m_macro_manager.insert(f, m, pr, dep); }
void insert_macro(func_decl * f, quantifier * m, proof * pr) { m_macro_manager.insert(f, m, pr); }
}; };
#endif /* ASSERTED_FORMULAS_H_ */ #endif /* ASSERTED_FORMULAS_H_ */

View file

@ -22,6 +22,8 @@ Revision History:
void preprocessor_params::updt_local_params(params_ref const & _p) { void preprocessor_params::updt_local_params(params_ref const & _p) {
smt_params_helper p(_p); smt_params_helper p(_p);
m_macro_finder = p.macro_finder(); m_macro_finder = p.macro_finder();
m_quasi_macros = p.quasi_macros();
m_restricted_quasi_macros = p.restricted_quasi_macros();
m_pull_nested_quantifiers = p.pull_nested_quantifiers(); m_pull_nested_quantifiers = p.pull_nested_quantifiers();
m_refine_inj_axiom = p.refine_inj_axioms(); m_refine_inj_axiom = p.refine_inj_axioms();
} }

View file

@ -7,6 +7,8 @@ def_module_params(module_name='smt',
('random_seed', UINT, 0, 'random seed for the smt solver'), ('random_seed', UINT, 0, 'random seed for the smt solver'),
('relevancy', UINT, 2, 'relevancy propagation heuristic: 0 - disabled, 1 - relevancy is tracked by only affects quantifier instantiation, 2 - relevancy is tracked, and an atom is only asserted if it is relevant'), ('relevancy', UINT, 2, 'relevancy propagation heuristic: 0 - disabled, 1 - relevancy is tracked by only affects quantifier instantiation, 2 - relevancy is tracked, and an atom is only asserted if it is relevant'),
('macro_finder', BOOL, False, 'try to find universally quantified formulas that can be viewed as macros'), ('macro_finder', BOOL, False, 'try to find universally quantified formulas that can be viewed as macros'),
('quasi_macros', BOOL, False, 'try to find universally quantified formulas that are quasi-macros'),
('restricted_quasi_macros', BOOL, False, 'try to find universally quantified formulas that are restricted quasi-macros'),
('ematching', BOOL, True, 'E-Matching based quantifier instantiation'), ('ematching', BOOL, True, 'E-Matching based quantifier instantiation'),
('phase_selection', UINT, 3, 'phase selection heuristic: 0 - always false, 1 - always true, 2 - phase caching, 3 - phase caching conservative, 4 - phase caching conservative 2, 5 - random, 6 - number of occurrences'), ('phase_selection', UINT, 3, 'phase selection heuristic: 0 - always false, 1 - always true, 2 - phase caching, 3 - phase caching conservative, 4 - phase caching conservative 2, 5 - random, 6 - number of occurrences'),
('restart_strategy', UINT, 1, '0 - geometric, 1 - inner-outer-geometric, 2 - luby, 3 - fixed, 4 - arithmetic'), ('restart_strategy', UINT, 1, '0 - geometric, 1 - inner-outer-geometric, 2 - luby, 3 - fixed, 4 - arithmetic'),

View file

@ -1566,7 +1566,7 @@ namespace smt {
func_decl * get_macro_func_decl(unsigned i) const { return m_asserted_formulas.get_macro_func_decl(i); } func_decl * get_macro_func_decl(unsigned i) const { return m_asserted_formulas.get_macro_func_decl(i); }
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_asserted_formulas.get_macro_interpretation(i, interp); } func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_asserted_formulas.get_macro_interpretation(i, interp); }
quantifier * get_macro_quantifier(func_decl * f) const { return m_asserted_formulas.get_macro_quantifier(f); } quantifier * get_macro_quantifier(func_decl * f) const { return m_asserted_formulas.get_macro_quantifier(f); }
void insert_macro(func_decl * f, quantifier * m, proof * pr) { m_asserted_formulas.insert_macro(f, m, pr); } void insert_macro(func_decl * f, quantifier * m, proof * pr, expr_dependency * dep) { m_asserted_formulas.insert_macro(f, m, pr, dep); }
}; };
}; };

View file

@ -45,25 +45,29 @@ class macro_finder_tactic : public tactic {
SASSERT(g->is_well_sorted()); SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0; mc = 0; pc = 0; core = 0;
tactic_report report("macro-finder", *g); tactic_report report("macro-finder", *g);
fail_if_unsat_core_generation("macro-finder", g);
bool produce_proofs = g->proofs_enabled(); bool produce_proofs = g->proofs_enabled();
bool unsat_core_enabled = g->unsat_core_enabled();
macro_manager mm(m_manager); macro_manager mm(m_manager);
macro_finder mf(m_manager, mm); macro_finder mf(m_manager, mm);
expr_ref_vector forms(m_manager), new_forms(m_manager); expr_ref_vector forms(m_manager), new_forms(m_manager);
proof_ref_vector proofs(m_manager), new_proofs(m_manager); proof_ref_vector proofs(m_manager), new_proofs(m_manager);
expr_dependency_ref_vector deps(m_manager), new_deps(m_manager);
unsigned size = g->size(); unsigned size = g->size();
for (unsigned idx = 0; idx < size; idx++) { for (unsigned idx = 0; idx < size; idx++) {
forms.push_back(g->form(idx)); forms.push_back(g->form(idx));
proofs.push_back(g->pr(idx)); proofs.push_back(g->pr(idx));
deps.push_back(g->dep(idx));
} }
mf(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs); mf(forms.size(), forms.c_ptr(), proofs.c_ptr(), deps.c_ptr(), new_forms, new_proofs, new_deps);
g->reset(); g->reset();
for (unsigned i = 0; i < new_forms.size(); i++) for (unsigned i = 0; i < new_forms.size(); i++)
g->assert_expr(new_forms.get(i), produce_proofs ? new_proofs.get(i) : 0, 0); g->assert_expr(new_forms.get(i),
produce_proofs ? new_proofs.get(i) : 0,
unsat_core_enabled ? new_deps.get(i) : 0);
extension_model_converter * evmc = alloc(extension_model_converter, mm.get_manager()); extension_model_converter * evmc = alloc(extension_model_converter, mm.get_manager());
unsigned num = mm.get_num_macros(); unsigned num = mm.get_num_macros();

View file

@ -43,9 +43,9 @@ class quasi_macros_tactic : public tactic {
SASSERT(g->is_well_sorted()); SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0; mc = 0; pc = 0; core = 0;
tactic_report report("quasi-macros", *g); tactic_report report("quasi-macros", *g);
fail_if_unsat_core_generation("quasi-macros", g);
bool produce_proofs = g->proofs_enabled(); bool produce_proofs = g->proofs_enabled();
bool produce_unsat_cores = g->unsat_core_enabled();
macro_manager mm(m_manager); macro_manager mm(m_manager);
quasi_macros qm(m_manager, mm); quasi_macros qm(m_manager, mm);
@ -53,11 +53,13 @@ class quasi_macros_tactic : public tactic {
expr_ref_vector forms(m_manager), new_forms(m_manager); expr_ref_vector forms(m_manager), new_forms(m_manager);
proof_ref_vector proofs(m_manager), new_proofs(m_manager); proof_ref_vector proofs(m_manager), new_proofs(m_manager);
expr_dependency_ref_vector deps(m_manager), new_deps(m_manager);
unsigned size = g->size(); unsigned size = g->size();
for (unsigned i = 0; i < size; i++) { for (unsigned i = 0; i < size; i++) {
forms.push_back(g->form(i)); forms.push_back(g->form(i));
proofs.push_back(g->pr(i)); proofs.push_back(g->pr(i));
deps.push_back(g->dep(i));
} }
while (more) { // CMW: use repeat(...) ? while (more) { // CMW: use repeat(...) ?
@ -66,14 +68,18 @@ class quasi_macros_tactic : public tactic {
new_forms.reset(); new_forms.reset();
new_proofs.reset(); new_proofs.reset();
more = qm(forms.size(), forms.c_ptr(), proofs.c_ptr(), new_forms, new_proofs); new_deps.reset();
more = qm(forms.size(), forms.c_ptr(), proofs.c_ptr(), deps.c_ptr(), new_forms, new_proofs, new_deps);
forms.swap(new_forms); forms.swap(new_forms);
proofs.swap(new_proofs); proofs.swap(new_proofs);
deps.swap(new_deps);
} }
g->reset(); g->reset();
for (unsigned i = 0; i < new_forms.size(); i++) for (unsigned i = 0; i < new_forms.size(); i++)
g->assert_expr(new_forms.get(i), produce_proofs ? new_proofs.get(i) : 0, 0); g->assert_expr(forms.get(i),
produce_proofs ? proofs.get(i) : 0,
produce_unsat_cores ? deps.get(i) : 0);
extension_model_converter * evmc = alloc(extension_model_converter, mm.get_manager()); extension_model_converter * evmc = alloc(extension_model_converter, mm.get_manager());
unsigned num = mm.get_num_macros(); unsigned num = mm.get_num_macros();