mirror of
https://github.com/Z3Prover/z3
synced 2025-06-04 21:31:22 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
c03be16039
15 changed files with 487 additions and 438 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,89 +25,94 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Detect macros of the form
|
\brief Detect macros of the form
|
||||||
1- (forall (X) (= (+ (f X) (R X)) c))
|
1- (forall (X) (= (+ (f X) (R X)) c))
|
||||||
2- (forall (X) (<= (+ (f X) (R X)) c))
|
2- (forall (X) (<= (+ (f X) (R X)) c))
|
||||||
3- (forall (X) (>= (+ (f X) (R X)) c))
|
3- (forall (X) (>= (+ (f X) (R X)) c))
|
||||||
|
|
||||||
The second and third cases are first converted into
|
The second and third cases are first converted into
|
||||||
(forall (X) (= (f X) (+ c (* -1 (R x)) (k X))))
|
(forall (X) (= (f X) (+ c (* -1 (R x)) (k X))))
|
||||||
and
|
and
|
||||||
(forall (X) (<= (k X) 0)) when case 2
|
(forall (X) (<= (k X) 0)) when case 2
|
||||||
(forall (X) (>= (k X) 0)) when case 3
|
(forall (X) (>= (k X) 0)) when case 3
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +185,7 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, vector<justified_expr>&
|
||||||
n is of the form: (forall (X) (iff (= (f X) t) def[X]))
|
n is of the form: (forall (X) (iff (= (f X) t) def[X]))
|
||||||
|
|
||||||
Convert it into:
|
Convert it into:
|
||||||
|
|
||||||
(forall (X) (= (f X) (ite def[X] t (k X))))
|
(forall (X) (= (f X) (ite def[X] t (k X))))
|
||||||
(forall (X) (not (= (k X) t)))
|
(forall (X) (not (= (k X) t)))
|
||||||
|
|
||||||
|
@ -188,13 +193,13 @@ 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());
|
||||||
app * ite = m.mk_ite(def, t, k_app);
|
app * ite = m.mk_ite(def, t, k_app);
|
||||||
app * body_1 = m.mk_eq(head, ite);
|
app * body_1 = m.mk_eq(head, ite);
|
||||||
app * body_2 = m.mk_not(m.mk_eq(k_app, t));
|
app * body_2 = m.mk_not(m.mk_eq(k_app, t));
|
||||||
quantifier * q1 = m.update_quantifier(q, body_1);
|
quantifier * q1 = m.update_quantifier(q, body_1);
|
||||||
expr * pats[1] = { m.mk_pattern(k_app) };
|
expr * pats[1] = { m.mk_pattern(k_app) };
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
@ -50,7 +52,7 @@ class macro_manager {
|
||||||
unsigned m_forbidden_lim;
|
unsigned m_forbidden_lim;
|
||||||
};
|
};
|
||||||
svector<scope> m_scopes;
|
svector<scope> m_scopes;
|
||||||
|
|
||||||
func_decl_dependencies m_deps;
|
func_decl_dependencies m_deps;
|
||||||
|
|
||||||
void restore_decls(unsigned old_sz);
|
void restore_decls(unsigned old_sz);
|
||||||
|
@ -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,9 +83,9 @@ 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);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MACRO_MANAGER_H_ */
|
#endif /* MACRO_MANAGER_H_ */
|
||||||
|
|
|
@ -31,7 +31,7 @@ quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm) :
|
||||||
m_new_qsorts(m) {
|
m_new_qsorts(m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
quasi_macros::~quasi_macros() {
|
quasi_macros::~quasi_macros() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void quasi_macros::find_occurrences(expr * e) {
|
void quasi_macros::find_occurrences(expr * e) {
|
||||||
|
@ -41,7 +41,7 @@ void quasi_macros::find_occurrences(expr * e) {
|
||||||
|
|
||||||
// we remember whether we have seen an expr once, or more than once;
|
// we remember whether we have seen an expr once, or more than once;
|
||||||
// when we see it the second time, we don't have to visit it another time,
|
// when we see it the second time, we don't have to visit it another time,
|
||||||
// as we are only interested in finding unique function applications.
|
// as we are only interested in finding unique function applications.
|
||||||
m_visited_once.reset();
|
m_visited_once.reset();
|
||||||
m_visited_more.reset();
|
m_visited_more.reset();
|
||||||
|
|
||||||
|
@ -64,8 +64,8 @@ void quasi_macros::find_occurrences(expr * e) {
|
||||||
if (is_non_ground_uninterp(cur)) {
|
if (is_non_ground_uninterp(cur)) {
|
||||||
func_decl * f = to_app(cur)->get_decl();
|
func_decl * f = to_app(cur)->get_decl();
|
||||||
m_occurrences.insert_if_not_there(f, 0);
|
m_occurrences.insert_if_not_there(f, 0);
|
||||||
occurrences_map::iterator it = m_occurrences.find_iterator(f);
|
occurrences_map::iterator it = m_occurrences.find_iterator(f);
|
||||||
it->m_value++;
|
it->m_value++;
|
||||||
}
|
}
|
||||||
j = to_app(cur)->get_num_args();
|
j = to_app(cur)->get_num_args();
|
||||||
while (j)
|
while (j)
|
||||||
|
@ -84,16 +84,16 @@ bool quasi_macros::is_unique(func_decl * f) const {
|
||||||
return m_occurrences.find(f) == 1;
|
return m_occurrences.find(f) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct var_dep_proc {
|
struct var_dep_proc {
|
||||||
bit_vector m_bitset;
|
bit_vector m_bitset;
|
||||||
public:
|
public:
|
||||||
var_dep_proc(quantifier * q) { m_bitset.resize(q->get_num_decls(), false); }
|
var_dep_proc(quantifier * q) { m_bitset.resize(q->get_num_decls(), false); }
|
||||||
void operator()(var * n) { m_bitset.set(n->get_idx(), true); }
|
void operator()(var * n) { m_bitset.set(n->get_idx(), true); }
|
||||||
void operator()(quantifier * n) {}
|
void operator()(quantifier * n) {}
|
||||||
void operator()(app * n) {}
|
void operator()(app * n) {}
|
||||||
bool all_used(void) {
|
bool all_used(void) {
|
||||||
for (unsigned i = 0; i < m_bitset.size() ; i++)
|
for (unsigned i = 0; i < m_bitset.size() ; i++)
|
||||||
if (!m_bitset.get(i))
|
if (!m_bitset.get(i))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ public:
|
||||||
|
|
||||||
bool quasi_macros::fully_depends_on(app * a, quantifier * q) const {
|
bool quasi_macros::fully_depends_on(app * a, quantifier * q) const {
|
||||||
// CMW: This checks whether all variables in q are used _somewhere_ deep down in the children of a
|
// CMW: This checks whether all variables in q are used _somewhere_ deep down in the children of a
|
||||||
|
|
||||||
/* var_dep_proc proc(q);
|
/* var_dep_proc proc(q);
|
||||||
for_each_expr(proc, a);
|
for_each_expr(proc, a);
|
||||||
return proc.all_used(); */
|
return proc.all_used(); */
|
||||||
|
@ -116,14 +116,14 @@ bool quasi_macros::fully_depends_on(app * a, quantifier * q) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < bitset.size() ; i++) {
|
for (unsigned i = 0; i < bitset.size() ; i++) {
|
||||||
if (!bitset.get(i))
|
if (!bitset.get(i))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool quasi_macros::depends_on(expr * e, func_decl * f) const {
|
bool quasi_macros::depends_on(expr * e, func_decl * f) const {
|
||||||
ptr_vector<expr> todo;
|
ptr_vector<expr> todo;
|
||||||
expr_mark visited;
|
expr_mark visited;
|
||||||
todo.push_back(e);
|
todo.push_back(e);
|
||||||
|
@ -133,12 +133,12 @@ bool quasi_macros::depends_on(expr * e, func_decl * f) const {
|
||||||
|
|
||||||
if (visited.is_marked(cur))
|
if (visited.is_marked(cur))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (is_app(cur)) {
|
if (is_app(cur)) {
|
||||||
app * a = to_app(cur);
|
app * a = to_app(cur);
|
||||||
if (a->get_decl() == f)
|
if (a->get_decl() == f)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
unsigned j = a->get_num_args();
|
unsigned j = a->get_num_args();
|
||||||
while (j>0)
|
while (j>0)
|
||||||
todo.push_back(a->get_arg(--j));
|
todo.push_back(a->get_arg(--j));
|
||||||
|
@ -151,7 +151,7 @@ bool quasi_macros::depends_on(expr * e, func_decl * f) const {
|
||||||
|
|
||||||
bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
||||||
// Our definition of a quasi-macro:
|
// Our definition of a quasi-macro:
|
||||||
// Forall X. f[X] = T[X], where f[X] is a term starting with symbol f, f is uninterpreted,
|
// Forall X. f[X] = T[X], where f[X] is a term starting with symbol f, f is uninterpreted,
|
||||||
// f[X] contains all universally quantified variables, and f does not occur in T[X].
|
// f[X] contains all universally quantified variables, and f does not occur in T[X].
|
||||||
TRACE("quasi_macros", tout << "Checking for quasi macro: " << mk_pp(e, m_manager) << std::endl;);
|
TRACE("quasi_macros", tout << "Checking for quasi macro: " << mk_pp(e, m_manager) << std::endl;);
|
||||||
|
|
||||||
|
@ -165,14 +165,14 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
||||||
if (is_non_ground_uninterp(lhs) && is_unique(to_app(lhs)->get_decl()) &&
|
if (is_non_ground_uninterp(lhs) && is_unique(to_app(lhs)->get_decl()) &&
|
||||||
!depends_on(rhs, to_app(lhs)->get_decl()) && fully_depends_on(to_app(lhs), q)) {
|
!depends_on(rhs, to_app(lhs)->get_decl()) && fully_depends_on(to_app(lhs), q)) {
|
||||||
a = to_app(lhs);
|
a = to_app(lhs);
|
||||||
t = rhs;
|
t = rhs;
|
||||||
return true;
|
return true;
|
||||||
} else if (is_non_ground_uninterp(rhs) && is_unique(to_app(rhs)->get_decl()) &&
|
} else if (is_non_ground_uninterp(rhs) && is_unique(to_app(rhs)->get_decl()) &&
|
||||||
!depends_on(lhs, to_app(rhs)->get_decl()) && fully_depends_on(to_app(rhs), q)) {
|
!depends_on(lhs, to_app(rhs)->get_decl()) && fully_depends_on(to_app(rhs), q)) {
|
||||||
a = to_app(rhs);
|
a = to_app(rhs);
|
||||||
t = lhs;
|
t = lhs;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (m_manager.is_not(qe) && is_non_ground_uninterp(to_app(qe)->get_arg(0)) &&
|
} else if (m_manager.is_not(qe) && is_non_ground_uninterp(to_app(qe)->get_arg(0)) &&
|
||||||
is_unique(to_app(to_app(qe)->get_arg(0))->get_decl())) { // this is like f(...) = false
|
is_unique(to_app(to_app(qe)->get_arg(0))->get_decl())) { // this is like f(...) = false
|
||||||
a = to_app(to_app(qe)->get_arg(0));
|
a = to_app(to_app(qe)->get_arg(0));
|
||||||
|
@ -189,7 +189,7 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quantifier_ref & macro) {
|
void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quantifier_ref & macro) {
|
||||||
m_new_var_names.reset();
|
m_new_var_names.reset();
|
||||||
m_new_vars.reset();
|
m_new_vars.reset();
|
||||||
m_new_qsorts.reset();
|
m_new_qsorts.reset();
|
||||||
m_new_eqs.reset();
|
m_new_eqs.reset();
|
||||||
|
@ -197,19 +197,19 @@ void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quant
|
||||||
func_decl * f = a->get_decl();
|
func_decl * f = a->get_decl();
|
||||||
|
|
||||||
// CMW: we rely on the fact that all variables in q appear at least once as
|
// CMW: we rely on the fact that all variables in q appear at least once as
|
||||||
// a direct argument of `a'.
|
// a direct argument of `a'.
|
||||||
|
|
||||||
bit_vector v_seen;
|
bit_vector v_seen;
|
||||||
v_seen.resize(q->get_num_decls(), false);
|
v_seen.resize(q->get_num_decls(), false);
|
||||||
for (unsigned i = 0 ; i < a->get_num_args() ; i++) {
|
for (unsigned i = 0 ; i < a->get_num_args() ; i++) {
|
||||||
if (!is_var(a->get_arg(i)) ||
|
if (!is_var(a->get_arg(i)) ||
|
||||||
v_seen.get(to_var(a->get_arg(i))->get_idx())) {
|
v_seen.get(to_var(a->get_arg(i))->get_idx())) {
|
||||||
unsigned inx = m_new_var_names.size();
|
unsigned inx = m_new_var_names.size();
|
||||||
m_new_name.str("");
|
m_new_name.str("");
|
||||||
m_new_name << "X" << inx;
|
m_new_name << "X" << inx;
|
||||||
m_new_var_names.push_back(symbol(m_new_name.str().c_str()));
|
m_new_var_names.push_back(symbol(m_new_name.str().c_str()));
|
||||||
m_new_qsorts.push_back(f->get_domain()[i]);
|
m_new_qsorts.push_back(f->get_domain()[i]);
|
||||||
|
|
||||||
m_new_vars.push_back(m_manager.mk_var(inx + q->get_num_decls(), f->get_domain()[i]));
|
m_new_vars.push_back(m_manager.mk_var(inx + q->get_num_decls(), f->get_domain()[i]));
|
||||||
m_new_eqs.push_back(m_manager.mk_eq(m_new_vars.back(), a->get_arg(i)));
|
m_new_eqs.push_back(m_manager.mk_eq(m_new_vars.back(), a->get_arg(i)));
|
||||||
} else {
|
} else {
|
||||||
|
@ -228,13 +228,13 @@ void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quant
|
||||||
new_var_names_rev.push_back(m_new_var_names.get(i));
|
new_var_names_rev.push_back(m_new_var_names.get(i));
|
||||||
new_qsorts_rev.push_back(m_new_qsorts.get(i));
|
new_qsorts_rev.push_back(m_new_qsorts.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to keep all the old variables [already reversed]
|
// We want to keep all the old variables [already reversed]
|
||||||
for (unsigned i = 0 ; i < q->get_num_decls() ; i++) {
|
for (unsigned i = 0 ; i < q->get_num_decls() ; i++) {
|
||||||
new_var_names_rev.push_back(q->get_decl_name(i));
|
new_var_names_rev.push_back(q->get_decl_name(i));
|
||||||
new_qsorts_rev.push_back(q->get_decl_sort(i));
|
new_qsorts_rev.push_back(q->get_decl_sort(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Macro := Forall m_new_vars . appl = ITE( m_new_eqs, t, f_else)
|
// Macro := Forall m_new_vars . appl = ITE( m_new_eqs, t, f_else)
|
||||||
|
|
||||||
app_ref appl(m_manager);
|
app_ref appl(m_manager);
|
||||||
|
@ -251,30 +251,29 @@ void quasi_macros::quasi_macro_to_macro(quantifier * q, app * a, expr * t, quant
|
||||||
|
|
||||||
eq = m_manager.mk_eq(appl, ite);
|
eq = m_manager.mk_eq(appl, ite);
|
||||||
|
|
||||||
macro = m_manager.mk_quantifier(true, new_var_names_rev.size(),
|
macro = m_manager.mk_quantifier(true, new_var_names_rev.size(),
|
||||||
new_qsorts_rev.c_ptr(), new_var_names_rev.c_ptr(), eq);
|
new_qsorts_rev.c_ptr(), new_var_names_rev.c_ptr(), eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
|
bool quasi_macros::find_macros(unsigned n, expr * const * exprs) {
|
||||||
TRACE("quasi_macros", tout << "Finding quasi-macros in: " << std::endl;
|
TRACE("quasi_macros", tout << "Finding quasi-macros in: " << std::endl;
|
||||||
for (unsigned i = 0 ; i < n ; i++)
|
for (unsigned i = 0 ; i < n ; i++)
|
||||||
tout << i << ": " << mk_pp(exprs[i], m_manager) << std::endl; );
|
tout << i << ": " << mk_pp(exprs[i], m_manager) << std::endl; );
|
||||||
bool res = false;
|
bool res = false;
|
||||||
m_occurrences.reset();
|
m_occurrences.reset();
|
||||||
|
|
||||||
|
|
||||||
// Find out how many non-ground appearences for each uninterpreted function there are
|
|
||||||
for ( unsigned i = 0 ; i < n ; i++ )
|
// Find out how many non-ground appearences for each uninterpreted function there are
|
||||||
|
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,31 +331,35 @@ 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]);
|
||||||
if (m_manager.proofs_enabled())
|
if (m_manager.proofs_enabled())
|
||||||
new_prs.push_back(prs[i]);
|
new_prs.push_back(prs[i]);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void quasi_macros::apply_macros(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls) {
|
void quasi_macros::apply_macros(unsigned n, justified_expr const* fmls, vector<justified_expr>& new_fmls) {
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,39 +33,42 @@ class quasi_macros {
|
||||||
macro_manager & m_macro_manager;
|
macro_manager & m_macro_manager;
|
||||||
th_rewriter m_rewriter;
|
th_rewriter m_rewriter;
|
||||||
occurrences_map m_occurrences;
|
occurrences_map m_occurrences;
|
||||||
ptr_vector<expr> m_todo;
|
ptr_vector<expr> m_todo;
|
||||||
|
|
||||||
vector<symbol> m_new_var_names;
|
vector<symbol> m_new_var_names;
|
||||||
expr_ref_vector m_new_vars;
|
expr_ref_vector m_new_vars;
|
||||||
expr_ref_vector m_new_eqs;
|
expr_ref_vector m_new_eqs;
|
||||||
sort_ref_vector m_new_qsorts;
|
sort_ref_vector m_new_qsorts;
|
||||||
std::stringstream m_new_name;
|
std::stringstream m_new_name;
|
||||||
expr_mark m_visited_once;
|
expr_mark m_visited_once;
|
||||||
expr_mark m_visited_more;
|
expr_mark m_visited_more;
|
||||||
|
|
||||||
bool is_unique(func_decl * f) const;
|
bool is_unique(func_decl * f) const;
|
||||||
bool is_non_ground_uninterp(expr const * e) const;
|
bool is_non_ground_uninterp(expr const * e) const;
|
||||||
bool fully_depends_on(app * a, quantifier * q) const;
|
bool fully_depends_on(app * a, quantifier * q) const;
|
||||||
bool depends_on(expr * e, func_decl * f) const;
|
bool depends_on(expr * e, func_decl * f) const;
|
||||||
|
|
||||||
bool is_quasi_macro(expr * e, app_ref & a, expr_ref &v) const;
|
bool is_quasi_macro(expr * e, app_ref & a, expr_ref &v) const;
|
||||||
void quasi_macro_to_macro(quantifier * q, app * a, expr * t, quantifier_ref & macro);
|
void quasi_macro_to_macro(quantifier * q, app * a, expr * t, quantifier_ref & macro);
|
||||||
|
|
||||||
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:
|
||||||
quasi_macros(ast_manager & m, macro_manager & mm);
|
quasi_macros(ast_manager & m, macro_manager & mm);
|
||||||
~quasi_macros();
|
~quasi_macros();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\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
|
||||||
|
|
|
@ -76,7 +76,7 @@ asserted_formulas::asserted_formulas(ast_manager & m, smt_params & p):
|
||||||
void asserted_formulas::setup() {
|
void asserted_formulas::setup() {
|
||||||
switch (m_params.m_lift_ite) {
|
switch (m_params.m_lift_ite) {
|
||||||
case LI_FULL:
|
case LI_FULL:
|
||||||
m_params.m_ng_lift_ite = LI_NONE;
|
m_params.m_ng_lift_ite = LI_NONE;
|
||||||
break;
|
break;
|
||||||
case LI_CONSERVATIVE:
|
case LI_CONSERVATIVE:
|
||||||
if (m_params.m_ng_lift_ite == LI_CONSERVATIVE)
|
if (m_params.m_ng_lift_ite == LI_CONSERVATIVE)
|
||||||
|
@ -85,7 +85,7 @@ void asserted_formulas::setup() {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_params.m_relevancy_lvl == 0)
|
if (m_params.m_relevancy_lvl == 0)
|
||||||
m_params.m_relevancy_lemma = false;
|
m_params.m_relevancy_lemma = false;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ void asserted_formulas::setup_simplifier_plugins(simplifier & s, basic_simplifie
|
||||||
s.register_plugin(alloc(array_simplifier_plugin, m, *bsimp, s, m_params));
|
s.register_plugin(alloc(array_simplifier_plugin, m, *bsimp, s, m_params));
|
||||||
bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, m_params);
|
bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, m_params);
|
||||||
s.register_plugin(bvsimp);
|
s.register_plugin(bvsimp);
|
||||||
s.register_plugin(alloc(datatype_simplifier_plugin, m, *bsimp));
|
s.register_plugin(alloc(datatype_simplifier_plugin, m, *bsimp));
|
||||||
s.register_plugin(alloc(fpa_simplifier_plugin, m, *bsimp));
|
s.register_plugin(alloc(fpa_simplifier_plugin, m, *bsimp));
|
||||||
s.register_plugin(alloc(seq_simplifier_plugin, m, *bsimp));
|
s.register_plugin(alloc(seq_simplifier_plugin, m, *bsimp));
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ void asserted_formulas::set_eliminate_and(bool flag) {
|
||||||
|
|
||||||
|
|
||||||
void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
|
void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
|
||||||
if (inconsistent())
|
if (inconsistent())
|
||||||
return;
|
return;
|
||||||
m_has_quantifiers |= ::has_quantifiers(e);
|
m_has_quantifiers |= ::has_quantifiers(e);
|
||||||
if (!m_params.m_preprocess) {
|
if (!m_params.m_preprocess) {
|
||||||
|
@ -177,7 +177,7 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void asserted_formulas::assert_expr(expr * e) {
|
void asserted_formulas::assert_expr(expr * e) {
|
||||||
if (inconsistent())
|
if (inconsistent())
|
||||||
return;
|
return;
|
||||||
assert_expr(e, m.mk_asserted(e));
|
assert_expr(e, m.mk_asserted(e));
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ void asserted_formulas::push_scope() {
|
||||||
m_bv_sharing.push_scope();
|
m_bv_sharing.push_scope();
|
||||||
commit();
|
commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void asserted_formulas::pop_scope(unsigned num_scopes) {
|
void asserted_formulas::pop_scope(unsigned num_scopes) {
|
||||||
TRACE("asserted_formulas_scopes", tout << "before pop " << num_scopes << "\n"; display(tout););
|
TRACE("asserted_formulas_scopes", tout << "before pop " << num_scopes << "\n"; display(tout););
|
||||||
m_bv_sharing.pop_scope(num_scopes);
|
m_bv_sharing.pop_scope(num_scopes);
|
||||||
|
@ -230,15 +230,15 @@ void asserted_formulas::reset() {
|
||||||
|
|
||||||
#ifdef Z3DEBUG
|
#ifdef Z3DEBUG
|
||||||
bool asserted_formulas::check_well_sorted() const {
|
bool asserted_formulas::check_well_sorted() const {
|
||||||
for (unsigned i = 0; i < m_asserted_formulas.size(); i++) {
|
for (unsigned i = 0; i < m_asserted_formulas.size(); i++) {
|
||||||
if (!is_well_sorted(m, m_asserted_formulas.get(i))) return false;
|
if (!is_well_sorted(m, m_asserted_formulas.get(i))) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void asserted_formulas::reduce() {
|
void asserted_formulas::reduce() {
|
||||||
if (inconsistent())
|
if (inconsistent())
|
||||||
return;
|
return;
|
||||||
if (canceled()) {
|
if (canceled()) {
|
||||||
return;
|
return;
|
||||||
|
@ -255,7 +255,7 @@ void asserted_formulas::reduce() {
|
||||||
|
|
||||||
|
|
||||||
#define INVOKE(COND, FUNC) if (COND) { FUNC; IF_VERBOSE(10000, verbose_stream() << "total size: " << get_total_size() << "\n";); } TRACE("reduce_step_ll", ast_mark visited; display_ll(tout, visited);); TRACE("reduce_step", display(tout << #FUNC << " ");); CASSERT("well_sorted",check_well_sorted()); if (inconsistent() || canceled()) { TRACE("after_reduce", display(tout);); TRACE("after_reduce_ll", ast_mark visited; display_ll(tout, visited);); return; }
|
#define INVOKE(COND, FUNC) if (COND) { FUNC; IF_VERBOSE(10000, verbose_stream() << "total size: " << get_total_size() << "\n";); } TRACE("reduce_step_ll", ast_mark visited; display_ll(tout, visited);); TRACE("reduce_step", display(tout << #FUNC << " ");); CASSERT("well_sorted",check_well_sorted()); if (inconsistent() || canceled()) { TRACE("after_reduce", display(tout);); TRACE("after_reduce_ll", ast_mark visited; display_ll(tout, visited);); return; }
|
||||||
|
|
||||||
set_eliminate_and(false); // do not eliminate and before nnf.
|
set_eliminate_and(false); // do not eliminate and before nnf.
|
||||||
INVOKE(m_params.m_propagate_booleans, propagate_booleans());
|
INVOKE(m_params.m_propagate_booleans, propagate_booleans());
|
||||||
INVOKE(m_params.m_propagate_values, propagate_values());
|
INVOKE(m_params.m_propagate_values, propagate_values());
|
||||||
|
@ -268,18 +268,18 @@ void asserted_formulas::reduce() {
|
||||||
INVOKE(m_params.m_lift_ite != LI_NONE, lift_ite());
|
INVOKE(m_params.m_lift_ite != LI_NONE, lift_ite());
|
||||||
INVOKE(m_params.m_eliminate_term_ite && m_params.m_lift_ite != LI_FULL, eliminate_term_ite());
|
INVOKE(m_params.m_eliminate_term_ite && m_params.m_lift_ite != LI_FULL, eliminate_term_ite());
|
||||||
INVOKE(m_params.m_refine_inj_axiom && has_quantifiers(), refine_inj_axiom());
|
INVOKE(m_params.m_refine_inj_axiom && has_quantifiers(), refine_inj_axiom());
|
||||||
INVOKE(m_params.m_distribute_forall && has_quantifiers(), apply_distribute_forall());
|
INVOKE(m_params.m_distribute_forall && has_quantifiers(), apply_distribute_forall());
|
||||||
TRACE("qbv_bug", tout << "after distribute_forall:\n"; display(tout););
|
TRACE("qbv_bug", tout << "after distribute_forall:\n"; display(tout););
|
||||||
INVOKE(m_params.m_macro_finder && has_quantifiers(), find_macros());
|
INVOKE(m_params.m_macro_finder && has_quantifiers(), find_macros());
|
||||||
INVOKE(m_params.m_quasi_macros && has_quantifiers(), apply_quasi_macros());
|
INVOKE(m_params.m_quasi_macros && has_quantifiers(), apply_quasi_macros());
|
||||||
INVOKE(m_params.m_simplify_bit2int, apply_bit2int());
|
INVOKE(m_params.m_simplify_bit2int, apply_bit2int());
|
||||||
INVOKE(m_params.m_eliminate_bounds && has_quantifiers(), cheap_quant_fourier_motzkin());
|
INVOKE(m_params.m_eliminate_bounds && has_quantifiers(), cheap_quant_fourier_motzkin());
|
||||||
INVOKE(m_params.m_ematching && has_quantifiers(), infer_patterns());
|
INVOKE(m_params.m_ematching && has_quantifiers(), infer_patterns());
|
||||||
INVOKE(m_params.m_max_bv_sharing && has_bv(), max_bv_sharing());
|
INVOKE(m_params.m_max_bv_sharing && has_bv(), max_bv_sharing());
|
||||||
INVOKE(m_params.m_bb_quantifiers, elim_bvs_from_quantifiers());
|
INVOKE(m_params.m_bb_quantifiers, elim_bvs_from_quantifiers());
|
||||||
// temporary HACK: make sure that arith & bv are list-assoc
|
// temporary HACK: make sure that arith & bv are list-assoc
|
||||||
// this may destroy some simplification steps such as max_bv_sharing
|
// this may destroy some simplification steps such as max_bv_sharing
|
||||||
reduce_asserted_formulas();
|
reduce_asserted_formulas();
|
||||||
|
|
||||||
CASSERT("well_sorted",check_well_sorted());
|
CASSERT("well_sorted",check_well_sorted());
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ void asserted_formulas::reduce() {
|
||||||
void asserted_formulas::eliminate_and() {
|
void asserted_formulas::eliminate_and() {
|
||||||
IF_IVERBOSE(10, verbose_stream() << "(smt.eliminating-and)\n";);
|
IF_IVERBOSE(10, verbose_stream() << "(smt.eliminating-and)\n";);
|
||||||
set_eliminate_and(true);
|
set_eliminate_and(true);
|
||||||
reduce_asserted_formulas();
|
reduce_asserted_formulas();
|
||||||
TRACE("after_elim_and", display(tout););
|
TRACE("after_elim_and", display(tout););
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,10 +333,10 @@ void asserted_formulas::display(std::ostream & out) const {
|
||||||
void asserted_formulas::display_ll(std::ostream & out, ast_mark & pp_visited) const {
|
void asserted_formulas::display_ll(std::ostream & out, ast_mark & pp_visited) const {
|
||||||
if (!m_asserted_formulas.empty()) {
|
if (!m_asserted_formulas.empty()) {
|
||||||
unsigned sz = m_asserted_formulas.size();
|
unsigned sz = m_asserted_formulas.size();
|
||||||
for (unsigned i = 0; i < sz; i++)
|
for (unsigned i = 0; i < sz; i++)
|
||||||
ast_def_ll_pp(out, m, m_asserted_formulas.get(i), pp_visited, true, false);
|
ast_def_ll_pp(out, m, m_asserted_formulas.get(i), pp_visited, true, false);
|
||||||
out << "asserted formulas:\n";
|
out << "asserted formulas:\n";
|
||||||
for (unsigned i = 0; i < sz; i++)
|
for (unsigned i = 0; i < sz; i++)
|
||||||
out << "#" << m_asserted_formulas[i]->get_id() << " ";
|
out << "#" << m_asserted_formulas[i]->get_id() << " ";
|
||||||
out << "\n";
|
out << "\n";
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -432,7 +439,7 @@ void asserted_formulas::nnf_cnf() {
|
||||||
proof_ref_vector new_prs(m);
|
proof_ref_vector new_prs(m);
|
||||||
expr_ref_vector push_todo(m);
|
expr_ref_vector push_todo(m);
|
||||||
proof_ref_vector push_todo_prs(m);
|
proof_ref_vector push_todo_prs(m);
|
||||||
|
|
||||||
unsigned i = m_asserted_qhead;
|
unsigned i = m_asserted_qhead;
|
||||||
unsigned sz = m_asserted_formulas.size();
|
unsigned sz = m_asserted_formulas.size();
|
||||||
TRACE("nnf_bug", tout << "i: " << i << " sz: " << sz << "\n";);
|
TRACE("nnf_bug", tout << "i: " << i << " sz: " << sz << "\n";);
|
||||||
|
@ -462,8 +469,8 @@ void asserted_formulas::nnf_cnf() {
|
||||||
CASSERT("well_sorted",is_well_sorted(m, r1));
|
CASSERT("well_sorted",is_well_sorted(m, r1));
|
||||||
if (canceled()) {
|
if (canceled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.proofs_enabled())
|
if (m.proofs_enabled())
|
||||||
pr = m.mk_modus_ponens(push_todo_prs.get(k), pr1);
|
pr = m.mk_modus_ponens(push_todo_prs.get(k), pr1);
|
||||||
else
|
else
|
||||||
|
@ -600,7 +607,7 @@ void asserted_formulas::propagate_values() {
|
||||||
// C is a set which contains formulas of the form
|
// C is a set which contains formulas of the form
|
||||||
// { x = n }, where x is a variable and n a numeral.
|
// { x = n }, where x is a variable and n a numeral.
|
||||||
// R contains the rest.
|
// R contains the rest.
|
||||||
//
|
//
|
||||||
// - new_exprs1 is the set C
|
// - new_exprs1 is the set C
|
||||||
// - new_exprs2 is the set R
|
// - new_exprs2 is the set R
|
||||||
//
|
//
|
||||||
|
@ -665,7 +672,7 @@ void asserted_formulas::propagate_values() {
|
||||||
// x->n will be removed from m_cache. If we don't do that, the next transformation
|
// x->n will be removed from m_cache. If we don't do that, the next transformation
|
||||||
// may simplify constraints in C using these entries, and the variables x in C
|
// may simplify constraints in C using these entries, and the variables x in C
|
||||||
// will be (silently) eliminated, and models produced by Z3 will not contain them.
|
// will be (silently) eliminated, and models produced by Z3 will not contain them.
|
||||||
flush_cache();
|
flush_cache();
|
||||||
}
|
}
|
||||||
TRACE("propagate_values", tout << "after:\n"; display(tout););
|
TRACE("propagate_values", tout << "after:\n"; display(tout););
|
||||||
}
|
}
|
||||||
|
@ -788,7 +795,7 @@ void asserted_formulas::refine_inj_axiom() {
|
||||||
TRACE("inj_axiom", tout << "simplifying...\n" << mk_pp(n, m) << "\n" << mk_pp(new_n, m) << "\n";);
|
TRACE("inj_axiom", tout << "simplifying...\n" << mk_pp(n, m) << "\n" << mk_pp(new_n, m) << "\n";);
|
||||||
m_asserted_formulas.set(i, new_n);
|
m_asserted_formulas.set(i, new_n);
|
||||||
if (m.proofs_enabled()) {
|
if (m.proofs_enabled()) {
|
||||||
proof_ref new_pr(m);
|
proof_ref new_pr(m);
|
||||||
new_pr = m.mk_rewrite(n, new_n);
|
new_pr = m.mk_rewrite(n, new_n);
|
||||||
new_pr = m.mk_modus_ponens(pr, new_pr);
|
new_pr = m.mk_modus_ponens(pr, new_pr);
|
||||||
m_asserted_formula_prs.set(i, new_pr);
|
m_asserted_formula_prs.set(i, new_pr);
|
||||||
|
@ -862,7 +869,7 @@ void asserted_formulas::max_bv_sharing() {
|
||||||
}
|
}
|
||||||
reduce_asserted_formulas();
|
reduce_asserted_formulas();
|
||||||
TRACE("bv_sharing", display(tout););
|
TRACE("bv_sharing", display(tout););
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Z3DEBUG
|
#ifdef Z3DEBUG
|
||||||
|
|
|
@ -51,7 +51,7 @@ class asserted_formulas {
|
||||||
|
|
||||||
macro_manager m_macro_manager;
|
macro_manager m_macro_manager;
|
||||||
scoped_ptr<macro_finder> m_macro_finder;
|
scoped_ptr<macro_finder> m_macro_finder;
|
||||||
|
|
||||||
bit2int m_bit2int;
|
bit2int m_bit2int;
|
||||||
|
|
||||||
maximise_bv_sharing m_bv_sharing;
|
maximise_bv_sharing m_bv_sharing;
|
||||||
|
@ -90,7 +90,7 @@ class asserted_formulas {
|
||||||
bool apply_bit2int();
|
bool apply_bit2int();
|
||||||
void lift_ite();
|
void lift_ite();
|
||||||
bool elim_bvs_from_quantifiers();
|
bool elim_bvs_from_quantifiers();
|
||||||
void ng_lift_ite();
|
void ng_lift_ite();
|
||||||
#ifdef Z3DEBUG
|
#ifdef Z3DEBUG
|
||||||
bool check_well_sorted() const;
|
bool check_well_sorted() const;
|
||||||
#endif
|
#endif
|
||||||
|
@ -115,8 +115,8 @@ public:
|
||||||
unsigned get_num_formulas() const { return m_asserted_formulas.size(); }
|
unsigned get_num_formulas() const { return m_asserted_formulas.size(); }
|
||||||
unsigned get_formulas_last_level() const;
|
unsigned get_formulas_last_level() const;
|
||||||
unsigned get_qhead() const { return m_asserted_qhead; }
|
unsigned get_qhead() const { return m_asserted_qhead; }
|
||||||
void commit();
|
void commit();
|
||||||
void commit(unsigned new_qhead);
|
void commit(unsigned new_qhead);
|
||||||
expr * get_formula(unsigned idx) const { return m_asserted_formulas.get(idx); }
|
expr * get_formula(unsigned idx) const { return m_asserted_formulas.get(idx); }
|
||||||
proof * get_formula_proof(unsigned idx) const { return m.proofs_enabled() ? m_asserted_formula_prs.get(idx) : 0; }
|
proof * get_formula_proof(unsigned idx) const { return m.proofs_enabled() ? m_asserted_formula_prs.get(idx) : 0; }
|
||||||
expr * const * get_formulas() const { return m_asserted_formulas.c_ptr(); }
|
expr * const * get_formulas() const { return m_asserted_formulas.c_ptr(); }
|
||||||
|
@ -133,7 +133,7 @@ public:
|
||||||
void collect_statistics(statistics & st) const;
|
void collect_statistics(statistics & st) const;
|
||||||
// TODO: improve precision of the following method.
|
// TODO: improve precision of the following method.
|
||||||
bool has_quantifiers() const { return m_has_quantifiers; }
|
bool has_quantifiers() const { return m_has_quantifiers; }
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
//
|
//
|
||||||
// Macros
|
// Macros
|
||||||
|
@ -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_ */
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'),
|
||||||
|
|
|
@ -209,7 +209,7 @@ namespace smt {
|
||||||
~scoped_mk_model() {
|
~scoped_mk_model() {
|
||||||
if (m_ctx.m_proto_model.get() != 0) {
|
if (m_ctx.m_proto_model.get() != 0) {
|
||||||
m_ctx.m_model = m_ctx.m_proto_model->mk_model();
|
m_ctx.m_model = m_ctx.m_proto_model->mk_model();
|
||||||
m_ctx.add_rec_funs_to_model();
|
m_ctx.add_rec_funs_to_model();
|
||||||
m_ctx.m_proto_model = 0; // proto_model is not needed anymore.
|
m_ctx.m_proto_model = 0; // proto_model is not needed anymore.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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); }
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,48 +22,52 @@ Notes:
|
||||||
#include "tactic/extension_model_converter.h"
|
#include "tactic/extension_model_converter.h"
|
||||||
#include "tactic/ufbv/macro_finder_tactic.h"
|
#include "tactic/ufbv/macro_finder_tactic.h"
|
||||||
|
|
||||||
class macro_finder_tactic : public tactic {
|
class macro_finder_tactic : public tactic {
|
||||||
|
|
||||||
struct imp {
|
struct imp {
|
||||||
ast_manager & m_manager;
|
ast_manager & m_manager;
|
||||||
bool m_elim_and;
|
bool m_elim_and;
|
||||||
|
|
||||||
imp(ast_manager & m, params_ref const & p) :
|
imp(ast_manager & m, params_ref const & p) :
|
||||||
m_manager(m),
|
m_manager(m),
|
||||||
m_elim_and(false) {
|
m_elim_and(false) {
|
||||||
updt_params(p);
|
updt_params(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_manager & m() const { return m_manager; }
|
ast_manager & m() const { return m_manager; }
|
||||||
|
|
||||||
|
|
||||||
void operator()(goal_ref const & g,
|
void operator()(goal_ref const & g,
|
||||||
goal_ref_buffer & result,
|
goal_ref_buffer & result,
|
||||||
model_converter_ref & mc,
|
model_converter_ref & mc,
|
||||||
proof_converter_ref & pc,
|
proof_converter_ref & pc,
|
||||||
expr_dependency_ref & core) {
|
expr_dependency_ref & core) {
|
||||||
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);
|
||||||
unsigned size = g->size();
|
expr_dependency_ref_vector deps(m_manager), new_deps(m_manager);
|
||||||
|
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();
|
||||||
|
@ -73,7 +77,7 @@ class macro_finder_tactic : public tactic {
|
||||||
evmc->insert(f, f_interp);
|
evmc->insert(f, f_interp);
|
||||||
}
|
}
|
||||||
mc = evmc;
|
mc = evmc;
|
||||||
|
|
||||||
g->inc_depth();
|
g->inc_depth();
|
||||||
result.push_back(g.get());
|
result.push_back(g.get());
|
||||||
TRACE("macro-finder", g->display(tout););
|
TRACE("macro-finder", g->display(tout););
|
||||||
|
@ -86,7 +90,7 @@ class macro_finder_tactic : public tactic {
|
||||||
};
|
};
|
||||||
|
|
||||||
imp * m_imp;
|
imp * m_imp;
|
||||||
params_ref m_params;
|
params_ref m_params;
|
||||||
public:
|
public:
|
||||||
macro_finder_tactic(ast_manager & m, params_ref const & p):
|
macro_finder_tactic(ast_manager & m, params_ref const & p):
|
||||||
m_params(p) {
|
m_params(p) {
|
||||||
|
@ -96,7 +100,7 @@ public:
|
||||||
virtual tactic * translate(ast_manager & m) {
|
virtual tactic * translate(ast_manager & m) {
|
||||||
return alloc(macro_finder_tactic, m, m_params);
|
return alloc(macro_finder_tactic, m, m_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~macro_finder_tactic() {
|
virtual ~macro_finder_tactic() {
|
||||||
dealloc(m_imp);
|
dealloc(m_imp);
|
||||||
}
|
}
|
||||||
|
@ -112,19 +116,19 @@ public:
|
||||||
insert_produce_proofs(r);
|
insert_produce_proofs(r);
|
||||||
r.insert("elim_and", CPK_BOOL, "(default: false) eliminate conjunctions during (internal) calls to the simplifier.");
|
r.insert("elim_and", CPK_BOOL, "(default: false) eliminate conjunctions during (internal) calls to the simplifier.");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void operator()(goal_ref const & in,
|
virtual void operator()(goal_ref const & in,
|
||||||
goal_ref_buffer & result,
|
goal_ref_buffer & result,
|
||||||
model_converter_ref & mc,
|
model_converter_ref & mc,
|
||||||
proof_converter_ref & pc,
|
proof_converter_ref & pc,
|
||||||
expr_dependency_ref & core) {
|
expr_dependency_ref & core) {
|
||||||
(*m_imp)(in, result, mc, pc, core);
|
(*m_imp)(in, result, mc, pc, core);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void cleanup() {
|
virtual void cleanup() {
|
||||||
ast_manager & m = m_imp->m();
|
ast_manager & m = m_imp->m();
|
||||||
imp * d = alloc(imp, m, m_params);
|
imp * d = alloc(imp, m, m_params);
|
||||||
std::swap(d, m_imp);
|
std::swap(d, m_imp);
|
||||||
dealloc(d);
|
dealloc(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,49 +31,55 @@ class quasi_macros_tactic : public tactic {
|
||||||
imp(ast_manager & m, params_ref const & p) : m_manager(m) {
|
imp(ast_manager & m, params_ref const & p) : m_manager(m) {
|
||||||
updt_params(p);
|
updt_params(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_manager & m() const { return m_manager; }
|
ast_manager & m() const { return m_manager; }
|
||||||
|
|
||||||
|
|
||||||
void operator()(goal_ref const & g,
|
void operator()(goal_ref const & g,
|
||||||
goal_ref_buffer & result,
|
goal_ref_buffer & result,
|
||||||
model_converter_ref & mc,
|
model_converter_ref & mc,
|
||||||
proof_converter_ref & pc,
|
proof_converter_ref & pc,
|
||||||
expr_dependency_ref & core) {
|
expr_dependency_ref & core) {
|
||||||
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);
|
||||||
bool more = true;
|
bool more = true;
|
||||||
|
|
||||||
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(...) ?
|
||||||
if (m().canceled())
|
if (m().canceled())
|
||||||
throw tactic_exception(m().limit().get_cancel_msg());
|
throw tactic_exception(m().limit().get_cancel_msg());
|
||||||
|
|
||||||
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();
|
||||||
|
@ -93,7 +99,7 @@ class quasi_macros_tactic : public tactic {
|
||||||
void updt_params(params_ref const & p) {
|
void updt_params(params_ref const & p) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
imp * m_imp;
|
imp * m_imp;
|
||||||
params_ref m_params;
|
params_ref m_params;
|
||||||
|
|
||||||
|
@ -106,7 +112,7 @@ public:
|
||||||
virtual tactic * translate(ast_manager & m) {
|
virtual tactic * translate(ast_manager & m) {
|
||||||
return alloc(quasi_macros_tactic, m, m_params);
|
return alloc(quasi_macros_tactic, m, m_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~quasi_macros_tactic() {
|
virtual ~quasi_macros_tactic() {
|
||||||
dealloc(m_imp);
|
dealloc(m_imp);
|
||||||
}
|
}
|
||||||
|
@ -121,19 +127,19 @@ public:
|
||||||
insert_produce_models(r);
|
insert_produce_models(r);
|
||||||
insert_produce_proofs(r);
|
insert_produce_proofs(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void operator()(goal_ref const & in,
|
virtual void operator()(goal_ref const & in,
|
||||||
goal_ref_buffer & result,
|
goal_ref_buffer & result,
|
||||||
model_converter_ref & mc,
|
model_converter_ref & mc,
|
||||||
proof_converter_ref & pc,
|
proof_converter_ref & pc,
|
||||||
expr_dependency_ref & core) {
|
expr_dependency_ref & core) {
|
||||||
(*m_imp)(in, result, mc, pc, core);
|
(*m_imp)(in, result, mc, pc, core);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void cleanup() {
|
virtual void cleanup() {
|
||||||
ast_manager & m = m_imp->m();
|
ast_manager & m = m_imp->m();
|
||||||
imp * d = alloc(imp, m, m_params);
|
imp * d = alloc(imp, m, m_params);
|
||||||
std::swap(d, m_imp);
|
std::swap(d, m_imp);
|
||||||
dealloc(d);
|
dealloc(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue