3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 06:03:23 +00:00

optimize rule preprocessing

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2013-04-26 14:40:20 -07:00
parent b644fb9875
commit 8038c719fb
10 changed files with 149 additions and 112 deletions

View file

@ -110,24 +110,27 @@ unsigned var_counter::get_max_var(bool& has_var) {
unsigned max_var = 0; unsigned max_var = 0;
while (!m_todo.empty()) { while (!m_todo.empty()) {
expr* e = m_todo.back(); expr* e = m_todo.back();
unsigned scope = m_scopes.back();
m_todo.pop_back(); m_todo.pop_back();
m_scopes.pop_back();
if (m_visited.is_marked(e)) { if (m_visited.is_marked(e)) {
continue; continue;
} }
m_visited.mark(e, true); m_visited.mark(e, true);
switch(e->get_kind()) { switch(e->get_kind()) {
case AST_QUANTIFIER: { case AST_QUANTIFIER: {
var_counter aux_counter;
quantifier* q = to_quantifier(e); quantifier* q = to_quantifier(e);
m_todo.push_back(q->get_expr()); bool has_var1 = false;
m_scopes.push_back(scope + q->get_num_decls()); unsigned max_v = aux_counter.get_max_var(has_var1);
if (max_v > max_var + q->get_num_decls()) {
max_var = max_v - q->get_num_decls();
has_var = true;
}
break; break;
} }
case AST_VAR: { case AST_VAR: {
if (to_var(e)->get_idx() >= scope + max_var) { if (to_var(e)->get_idx() >= max_var) {
has_var = true; has_var = true;
max_var = to_var(e)->get_idx() - scope; max_var = to_var(e)->get_idx();
} }
break; break;
} }
@ -135,7 +138,6 @@ unsigned var_counter::get_max_var(bool& has_var) {
app* a = to_app(e); app* a = to_app(e);
for (unsigned i = 0; i < a->get_num_args(); ++i) { for (unsigned i = 0; i < a->get_num_args(); ++i) {
m_todo.push_back(a->get_arg(i)); m_todo.push_back(a->get_arg(i));
m_scopes.push_back(scope);
} }
break; break;
} }
@ -152,14 +154,12 @@ unsigned var_counter::get_max_var(bool& has_var) {
unsigned var_counter::get_max_var(expr* e) { unsigned var_counter::get_max_var(expr* e) {
bool has_var = false; bool has_var = false;
m_todo.push_back(e); m_todo.push_back(e);
m_scopes.push_back(0);
return get_max_var(has_var); return get_max_var(has_var);
} }
unsigned var_counter::get_next_var(expr* e) { unsigned var_counter::get_next_var(expr* e) {
bool has_var = false; bool has_var = false;
m_todo.push_back(e); m_todo.push_back(e);
m_scopes.push_back(0);
unsigned mv = get_max_var(has_var); unsigned mv = get_max_var(has_var);
if (has_var) mv++; if (has_var) mv++;
return mv; return mv;

View file

@ -41,7 +41,6 @@ Revision History:
#include"for_each_expr.h" #include"for_each_expr.h"
#include"ast_smt_pp.h" #include"ast_smt_pp.h"
#include"ast_smt2_pp.h" #include"ast_smt2_pp.h"
#include"expr_functors.h"
#include"dl_mk_partial_equiv.h" #include"dl_mk_partial_equiv.h"
#include"dl_mk_bit_blast.h" #include"dl_mk_bit_blast.h"
#include"dl_mk_array_blast.h" #include"dl_mk_array_blast.h"
@ -227,6 +226,8 @@ namespace datalog {
m_rule_manager(*this), m_rule_manager(*this),
m_elim_unused_vars(m), m_elim_unused_vars(m),
m_abstractor(m), m_abstractor(m),
m_contains_p(*this),
m_check_pred(m_contains_p, m),
m_transf(*this), m_transf(*this),
m_trail(*this), m_trail(*this),
m_pinned(m), m_pinned(m),
@ -302,18 +303,19 @@ namespace datalog {
expr_ref context::bind_variables(expr* fml, bool is_forall) { expr_ref context::bind_variables(expr* fml, bool is_forall) {
expr_ref result(m); expr_ref result(m);
app_ref_vector const & vars = m_vars; app_ref_vector const & vars = m_vars;
rule_manager& rm = get_rule_manager();
if (vars.empty()) { if (vars.empty()) {
result = fml; result = fml;
} }
else { else {
ptr_vector<sort> sorts; m_names.reset();
m_abstractor(0, vars.size(), reinterpret_cast<expr*const*>(vars.c_ptr()), fml, result); m_abstractor(0, vars.size(), reinterpret_cast<expr*const*>(vars.c_ptr()), fml, result);
get_free_vars(result, sorts); rm.collect_vars(result);
ptr_vector<sort>& sorts = rm.get_var_sorts();
if (sorts.empty()) { if (sorts.empty()) {
result = fml; result = fml;
} }
else { else {
svector<symbol> names;
for (unsigned i = 0; i < sorts.size(); ++i) { for (unsigned i = 0; i < sorts.size(); ++i) {
if (!sorts[i]) { if (!sorts[i]) {
if (i < vars.size()) { if (i < vars.size()) {
@ -324,15 +326,15 @@ namespace datalog {
} }
} }
if (i < vars.size()) { if (i < vars.size()) {
names.push_back(vars[i]->get_decl()->get_name()); m_names.push_back(vars[i]->get_decl()->get_name());
} }
else { else {
names.push_back(symbol(i)); m_names.push_back(symbol(i));
} }
} }
quantifier_ref q(m); quantifier_ref q(m);
sorts.reverse(); sorts.reverse();
q = m.mk_quantifier(is_forall, sorts.size(), sorts.c_ptr(), names.c_ptr(), result); q = m.mk_quantifier(is_forall, sorts.size(), sorts.c_ptr(), m_names.c_ptr(), result);
m_elim_unused_vars(q, result); m_elim_unused_vars(q, result);
} }
} }
@ -608,28 +610,16 @@ namespace datalog {
} }
} }
class context::contains_pred : public i_expr_pred {
context const& ctx;
public:
contains_pred(context& ctx): ctx(ctx) {}
virtual ~contains_pred() {}
virtual bool operator()(expr* e) {
return ctx.is_predicate(e);
}
};
void context::check_existential_tail(rule_ref& r) { void context::check_existential_tail(rule_ref& r) {
unsigned ut_size = r->get_uninterpreted_tail_size(); unsigned ut_size = r->get_uninterpreted_tail_size();
unsigned t_size = r->get_tail_size(); unsigned t_size = r->get_tail_size();
contains_pred contains_p(*this);
check_pred check_pred(contains_p, get_manager());
TRACE("dl", r->display_smt2(get_manager(), tout); tout << "\n";); TRACE("dl", r->display_smt2(get_manager(), tout); tout << "\n";);
for (unsigned i = ut_size; i < t_size; ++i) { for (unsigned i = ut_size; i < t_size; ++i) {
app* t = r->get_tail(i); app* t = r->get_tail(i);
TRACE("dl", tout << "checking: " << mk_ismt2_pp(t, get_manager()) << "\n";); TRACE("dl", tout << "checking: " << mk_ismt2_pp(t, get_manager()) << "\n";);
if (check_pred(t)) { if (m_check_pred(t)) {
std::ostringstream out; std::ostringstream out;
out << "interpreted body " << mk_ismt2_pp(t, get_manager()) << " contains recursive predicate"; out << "interpreted body " << mk_ismt2_pp(t, get_manager()) << " contains recursive predicate";
throw default_exception(out.str()); throw default_exception(out.str());

View file

@ -46,6 +46,8 @@ Revision History:
#include"smt_params.h" #include"smt_params.h"
#include"dl_rule_transformer.h" #include"dl_rule_transformer.h"
#include"expr_abstract.h" #include"expr_abstract.h"
#include"expr_functors.h"
namespace datalog { namespace datalog {
@ -77,6 +79,18 @@ namespace datalog {
typedef obj_map<const func_decl, svector<symbol> > pred2syms; typedef obj_map<const func_decl, svector<symbol> > pred2syms;
typedef obj_map<const sort, sort_domain*> sort_domain_map; typedef obj_map<const sort, sort_domain*> sort_domain_map;
class contains_pred : public i_expr_pred {
context const& ctx;
public:
contains_pred(context& ctx): ctx(ctx) {}
virtual ~contains_pred() {}
virtual bool operator()(expr* e) {
return ctx.is_predicate(e);
}
};
ast_manager & m; ast_manager & m;
smt_params & m_fparams; smt_params & m_fparams;
params_ref m_params_ref; params_ref m_params_ref;
@ -87,10 +101,13 @@ namespace datalog {
rule_manager m_rule_manager; rule_manager m_rule_manager;
unused_vars_eliminator m_elim_unused_vars; unused_vars_eliminator m_elim_unused_vars;
expr_abstractor m_abstractor; expr_abstractor m_abstractor;
contains_pred m_contains_p;
check_pred m_check_pred;
rule_transformer m_transf; rule_transformer m_transf;
trail_stack<context> m_trail; trail_stack<context> m_trail;
ast_ref_vector m_pinned; ast_ref_vector m_pinned;
app_ref_vector m_vars; app_ref_vector m_vars;
svector<symbol> m_names;
sort_domain_map m_sorts; sort_domain_map m_sorts;
func_decl_set m_preds; func_decl_set m_preds;
sym2decl m_preds_by_name; sym2decl m_preds_by_name;

View file

@ -369,11 +369,14 @@ namespace datalog {
mk_interp_tail_simplifier::mk_interp_tail_simplifier(context & ctx, unsigned priority) mk_interp_tail_simplifier::mk_interp_tail_simplifier(context & ctx, unsigned priority)
: plugin(priority), : plugin(priority),
m(ctx.get_manager()), m(ctx.get_manager()),
m_context(ctx), m_context(ctx),
m_simp(ctx.get_rewriter()), m_simp(ctx.get_rewriter()),
a(m), a(m),
m_rule_subst(ctx) { m_rule_subst(ctx),
m_tail(m),
m_itail_members(m),
m_conj(m) {
m_cfg = alloc(normalizer_cfg, m); m_cfg = alloc(normalizer_cfg, m);
m_rw = alloc(normalizer_rw, m, *m_cfg); m_rw = alloc(normalizer_rw, m, *m_cfg);
} }
@ -404,15 +407,15 @@ namespace datalog {
return false; return false;
} }
ptr_vector<expr> todo; m_todo.reset();
m_leqs.reset();
for (unsigned i = u_len; i < len; i++) { for (unsigned i = u_len; i < len; i++) {
todo.push_back(r->get_tail(i)); m_todo.push_back(r->get_tail(i));
SASSERT(!r->is_neg_tail(i)); SASSERT(!r->is_neg_tail(i));
} }
m_rule_subst.reset(r); m_rule_subst.reset(r);
obj_hashtable<expr> leqs;
expr_ref_vector trail(m); expr_ref_vector trail(m);
expr_ref tmp1(m), tmp2(m); expr_ref tmp1(m), tmp2(m);
bool found_something = false; bool found_something = false;
@ -420,10 +423,10 @@ namespace datalog {
#define TRY_UNIFY(_x,_y) if (m_rule_subst.unify(_x,_y)) { found_something = true; } #define TRY_UNIFY(_x,_y) if (m_rule_subst.unify(_x,_y)) { found_something = true; }
#define IS_FLEX(_x) (is_var(_x) || m.is_value(_x)) #define IS_FLEX(_x) (is_var(_x) || m.is_value(_x))
while (!todo.empty()) { while (!m_todo.empty()) {
expr * arg1, *arg2; expr * arg1, *arg2;
expr * t0 = todo.back(); expr * t0 = m_todo.back();
todo.pop_back(); m_todo.pop_back();
expr* t = t0; expr* t = t0;
bool neg = m.is_not(t, t); bool neg = m.is_not(t, t);
if (is_var(t)) { if (is_var(t)) {
@ -431,7 +434,7 @@ namespace datalog {
} }
else if (!neg && m.is_and(t)) { else if (!neg && m.is_and(t)) {
app* a = to_app(t); app* a = to_app(t);
todo.append(a->get_num_args(), a->get_args()); m_todo.append(a->get_num_args(), a->get_args());
} }
else if (!neg && m.is_eq(t, arg1, arg2) && IS_FLEX(arg1) && IS_FLEX(arg2)) { else if (!neg && m.is_eq(t, arg1, arg2) && IS_FLEX(arg1) && IS_FLEX(arg2)) {
TRY_UNIFY(arg1, arg2); TRY_UNIFY(arg1, arg2);
@ -459,12 +462,12 @@ namespace datalog {
else if (!neg && (a.is_le(t, arg1, arg2) || a.is_ge(t, arg2, arg1))) { else if (!neg && (a.is_le(t, arg1, arg2) || a.is_ge(t, arg2, arg1))) {
tmp1 = a.mk_sub(arg1, arg2); tmp1 = a.mk_sub(arg1, arg2);
tmp2 = a.mk_sub(arg2, arg1); tmp2 = a.mk_sub(arg2, arg1);
if (false && leqs.contains(tmp2) && IS_FLEX(arg1) && IS_FLEX(arg2)) { if (false && m_leqs.contains(tmp2) && IS_FLEX(arg1) && IS_FLEX(arg2)) {
TRY_UNIFY(arg1, arg2); TRY_UNIFY(arg1, arg2);
} }
else { else {
trail.push_back(tmp1); trail.push_back(tmp1);
leqs.insert(tmp1); m_leqs.insert(tmp1);
} }
} }
} }
@ -504,12 +507,12 @@ namespace datalog {
} }
app_ref head(r->get_head(), m); app_ref head(r->get_head(), m);
app_ref_vector tail(m); m_tail.reset();
svector<bool> tail_neg; m_tail_neg.reset();
for (unsigned i=0; i<u_len; i++) { for (unsigned i=0; i<u_len; i++) {
tail.push_back(r->get_tail(i)); m_tail.push_back(r->get_tail(i));
tail_neg.push_back(r->is_neg_tail(i)); m_tail_neg.push_back(r->is_neg_tail(i));
} }
bool modified = false; bool modified = false;
@ -521,12 +524,12 @@ namespace datalog {
SASSERT(!r->is_neg_tail(u_len)); SASSERT(!r->is_neg_tail(u_len));
} }
else { else {
expr_ref_vector itail_members(m); m_itail_members.reset();
for (unsigned i=u_len; i<len; i++) { for (unsigned i=u_len; i<len; i++) {
itail_members.push_back(r->get_tail(i)); m_itail_members.push_back(r->get_tail(i));
SASSERT(!r->is_neg_tail(i)); SASSERT(!r->is_neg_tail(i));
} }
itail = m.mk_and(itail_members.size(), itail_members.c_ptr()); itail = m.mk_and(m_itail_members.size(), m_itail_members.c_ptr());
modified = true; modified = true;
} }
@ -542,21 +545,21 @@ namespace datalog {
SASSERT(m.is_bool(simp_res)); SASSERT(m.is_bool(simp_res));
if (modified) { if (modified) {
expr_ref_vector conjs(m); m_conj.reset();
flatten_and(simp_res, conjs); flatten_and(simp_res, m_conj);
for (unsigned i = 0; i < conjs.size(); ++i) { for (unsigned i = 0; i < m_conj.size(); ++i) {
expr* e = conjs[i].get(); expr* e = m_conj[i].get();
if (is_app(e)) { if (is_app(e)) {
tail.push_back(to_app(e)); m_tail.push_back(to_app(e));
} }
else { else {
tail.push_back(m.mk_eq(e, m.mk_true())); m_tail.push_back(m.mk_eq(e, m.mk_true()));
} }
tail_neg.push_back(false); m_tail_neg.push_back(false);
} }
SASSERT(tail.size() == tail_neg.size()); SASSERT(m_tail.size() == m_tail_neg.size());
res = m_context.get_rule_manager().mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr()); res = m_context.get_rule_manager().mk(head, m_tail.size(), m_tail.c_ptr(), m_tail_neg.c_ptr());
res->set_accounting_parent_object(m_context, r); res->set_accounting_parent_object(m_context, r);
} }
else { else {

View file

@ -71,6 +71,12 @@ namespace datalog {
th_rewriter & m_simp; th_rewriter & m_simp;
arith_util a; arith_util a;
rule_substitution m_rule_subst; rule_substitution m_rule_subst;
ptr_vector<expr> m_todo;
obj_hashtable<expr> m_leqs;
app_ref_vector m_tail;
expr_ref_vector m_itail_members;
expr_ref_vector m_conj;
svector<bool> m_tail_neg;
normalizer_cfg* m_cfg; normalizer_cfg* m_cfg;
normalizer_rw* m_rw; normalizer_rw* m_rw;

View file

@ -40,15 +40,18 @@ Revision History:
#include"quant_hoist.h" #include"quant_hoist.h"
#include"expr_replacer.h" #include"expr_replacer.h"
#include"bool_rewriter.h" #include"bool_rewriter.h"
#include"qe_lite.h"
#include"expr_safe_replace.h" #include"expr_safe_replace.h"
#include"hnf.h"
namespace datalog { namespace datalog {
rule_manager::rule_manager(context& ctx) rule_manager::rule_manager(context& ctx)
: m(ctx.get_manager()), : m(ctx.get_manager()),
m_ctx(ctx), m_ctx(ctx),
m_body(m),
m_head(m),
m_args(m),
m_hnf(m),
m_qe(m),
m_cfg(m), m_cfg(m),
m_rwr(m, false, m_cfg) {} m_rwr(m, false, m_cfg) {}
@ -179,13 +182,13 @@ namespace datalog {
} }
void rule_manager::mk_rule_core(expr* fml, proof* p, rule_set& rules, symbol const& name) { void rule_manager::mk_rule_core(expr* fml, proof* p, rule_set& rules, symbol const& name) {
hnf h(m);
expr_ref_vector fmls(m); expr_ref_vector fmls(m);
proof_ref_vector prs(m); proof_ref_vector prs(m);
h.set_name(name); m_hnf.reset();
h(fml, p, fmls, prs); m_hnf.set_name(name);
for (unsigned i = 0; i < h.get_fresh_predicates().size(); ++i) { m_hnf(fml, p, fmls, prs);
m_ctx.register_predicate(h.get_fresh_predicates()[i], false); for (unsigned i = 0; i < m_hnf.get_fresh_predicates().size(); ++i) {
m_ctx.register_predicate(m_hnf.get_fresh_predicates()[i], false);
} }
for (unsigned i = 0; i < fmls.size(); ++i) { for (unsigned i = 0; i < fmls.size(); ++i) {
mk_horn_rule(fmls[i].get(), prs[i].get(), rules, name); mk_horn_rule(fmls[i].get(), prs[i].get(), rules, name);
@ -194,24 +197,23 @@ namespace datalog {
void rule_manager::mk_horn_rule(expr* fml, proof* p, rule_set& rules, symbol const& name) { void rule_manager::mk_horn_rule(expr* fml, proof* p, rule_set& rules, symbol const& name) {
app_ref_vector body(m); m_body.reset();
app_ref head(m); m_neg.reset();
svector<bool> is_negated; unsigned index = extract_horn(fml, m_body, m_head);
unsigned index = extract_horn(fml, body, head); hoist_compound_predicates(index, m_head, m_body);
hoist_compound_predicates(index, head, body);
TRACE("dl_rule", TRACE("dl_rule",
tout << mk_pp(head, m) << " :- "; tout << mk_pp(head, m) << " :- ";
for (unsigned i = 0; i < body.size(); ++i) { for (unsigned i = 0; i < m_body.size(); ++i) {
tout << mk_pp(body[i].get(), m) << " "; tout << mk_pp(m_body[i].get(), m) << " ";
} }
tout << "\n";); tout << "\n";);
mk_negations(body, is_negated); mk_negations(m_body, m_neg);
check_valid_rule(head, body.size(), body.c_ptr()); check_valid_rule(m_head, m_body.size(), m_body.c_ptr());
rule_ref r(*this); rule_ref r(*this);
r = mk(head.get(), body.size(), body.c_ptr(), is_negated.c_ptr(), name); r = mk(m_head.get(), m_body.size(), m_body.c_ptr(), m_neg.c_ptr(), name);
expr_ref fml1(m); expr_ref fml1(m);
if (p) { if (p) {
@ -380,28 +382,28 @@ namespace datalog {
fml = m.mk_not(fml); fml = m.mk_not(fml);
return; return;
} }
expr_ref_vector args(m);
if (!m_ctx.is_predicate(fml)) { if (!m_ctx.is_predicate(fml)) {
return; return;
} }
m_args.reset();
for (unsigned i = 0; i < fml->get_num_args(); ++i) { for (unsigned i = 0; i < fml->get_num_args(); ++i) {
e = fml->get_arg(i); e = fml->get_arg(i);
if (!is_app(e)) { if (!is_app(e)) {
args.push_back(e); m_args.push_back(e);
continue; continue;
} }
app* b = to_app(e); app* b = to_app(e);
if (m.is_value(b)) { if (m.is_value(b)) {
args.push_back(e); m_args.push_back(e);
} }
else { else {
var* v = m.mk_var(num_bound++, m.get_sort(b)); var* v = m.mk_var(num_bound++, m.get_sort(b));
args.push_back(v); m_args.push_back(v);
body.push_back(m.mk_eq(v, b)); body.push_back(m.mk_eq(v, b));
} }
} }
fml = m.mk_app(fml->get_decl(), args.size(), args.c_ptr()); fml = m.mk_app(fml->get_decl(), m_args.size(), m_args.c_ptr());
TRACE("dl_rule", tout << mk_pp(fml.get(), m) << "\n";); TRACE("dl_rule", tout << mk_pp(fml.get(), m) << "\n";);
} }
@ -565,29 +567,22 @@ namespace datalog {
void rule_manager::reduce_unbound_vars(rule_ref& r) { void rule_manager::reduce_unbound_vars(rule_ref& r) {
unsigned ut_len = r->get_uninterpreted_tail_size(); unsigned ut_len = r->get_uninterpreted_tail_size();
unsigned t_len = r->get_tail_size(); unsigned t_len = r->get_tail_size();
ptr_vector<sort> vars;
uint_set index_set;
qe_lite qe(m);
expr_ref_vector conjs(m); expr_ref_vector conjs(m);
if (ut_len == t_len) { if (ut_len == t_len) {
return; return;
} }
get_free_vars(r->get_head(), vars); reset_collect_vars();
accumulate_vars(r->get_head());
for (unsigned i = 0; i < ut_len; ++i) { for (unsigned i = 0; i < ut_len; ++i) {
get_free_vars(r->get_tail(i), vars); accumulate_vars(r->get_tail(i));
} }
var_idx_set& index_set = finalize_collect_vars();
for (unsigned i = ut_len; i < t_len; ++i) { for (unsigned i = ut_len; i < t_len; ++i) {
conjs.push_back(r->get_tail(i)); conjs.push_back(r->get_tail(i));
} }
m_qe(index_set, false, conjs);
for (unsigned i = 0; i < vars.size(); ++i) {
if (vars[i]) {
index_set.insert(i);
}
}
qe(index_set, false, conjs);
bool change = conjs.size() != t_len - ut_len; bool change = conjs.size() != t_len - ut_len;
for (unsigned i = 0; !change && i < conjs.size(); ++i) { for (unsigned i = 0; !change && i < conjs.size(); ++i) {
change = r->get_tail(ut_len+i) != conjs[i].get(); change = r->get_tail(ut_len+i) != conjs[i].get();

View file

@ -28,6 +28,8 @@ Revision History:
#include"model_converter.h" #include"model_converter.h"
#include"ast_counter.h" #include"ast_counter.h"
#include"rewriter.h" #include"rewriter.h"
#include"hnf.h"
#include"qe_lite.h"
namespace datalog { namespace datalog {
@ -66,6 +68,12 @@ namespace datalog {
var_idx_set m_var_idx; var_idx_set m_var_idx;
ptr_vector<expr> m_todo; ptr_vector<expr> m_todo;
ast_mark m_mark; ast_mark m_mark;
app_ref_vector m_body;
app_ref m_head;
expr_ref_vector m_args;
svector<bool> m_neg;
hnf m_hnf;
qe_lite m_qe;
remove_label_cfg m_cfg; remove_label_cfg m_cfg;
rewriter_tpl<remove_label_cfg> m_rwr; rewriter_tpl<remove_label_cfg> m_rwr;

View file

@ -71,6 +71,9 @@ class hnf::imp {
obj_map<expr, app*> m_memoize_disj; obj_map<expr, app*> m_memoize_disj;
obj_map<expr, proof*> m_memoize_proof; obj_map<expr, proof*> m_memoize_proof;
func_decl_ref_vector m_fresh_predicates; func_decl_ref_vector m_fresh_predicates;
expr_ref_vector m_body;
proof_ref_vector m_defs;
public: public:
imp(ast_manager & m): imp(ast_manager & m):
@ -82,7 +85,9 @@ public:
m_refs(m), m_refs(m),
m_name("P"), m_name("P"),
m_qh(m), m_qh(m),
m_fresh_predicates(m) { m_fresh_predicates(m),
m_body(m),
m_defs(m) {
} }
void operator()(expr * n, void operator()(expr * n,
@ -182,13 +187,13 @@ private:
void mk_horn(expr_ref& fml, proof_ref& premise) { void mk_horn(expr_ref& fml, proof_ref& premise) {
expr* e1, *e2; expr* e1, *e2;
expr_ref_vector body(m);
proof_ref_vector defs(m);
expr_ref fml0(m), fml1(m), fml2(m), head(m); expr_ref fml0(m), fml1(m), fml2(m), head(m);
proof_ref p(m); proof_ref p(m);
fml0 = fml; fml0 = fml;
m_names.reset(); m_names.reset();
m_sorts.reset(); m_sorts.reset();
m_body.reset();
m_defs.reset();
m_qh.pull_quantifier(true, fml0, &m_sorts, &m_names); m_qh.pull_quantifier(true, fml0, &m_sorts, &m_names);
if (premise){ if (premise){
fml1 = bind_variables(fml0); fml1 = bind_variables(fml0);
@ -199,12 +204,12 @@ private:
} }
head = fml0; head = fml0;
while (m.is_implies(head, e1, e2)) { while (m.is_implies(head, e1, e2)) {
body.push_back(e1); m_body.push_back(e1);
head = e2; head = e2;
} }
datalog::flatten_and(body); datalog::flatten_and(m_body);
if (premise) { if (premise) {
p = m.mk_rewrite(fml0, mk_implies(body, head)); p = m.mk_rewrite(fml0, mk_implies(m_body, head));
} }
// //
@ -214,8 +219,8 @@ private:
// A -> C // A -> C
// B -> C // B -> C
// //
if (body.size() == 1 && m.is_or(body[0].get()) && contains_predicate(body[0].get())) { if (m_body.size() == 1 && m.is_or(m_body[0].get()) && contains_predicate(m_body[0].get())) {
app* _or = to_app(body[0].get()); app* _or = to_app(m_body[0].get());
unsigned sz = _or->get_num_args(); unsigned sz = _or->get_num_args();
expr* const* args = _or->get_args(); expr* const* args = _or->get_args();
for (unsigned i = 0; i < sz; ++i) { for (unsigned i = 0; i < sz; ++i) {
@ -224,7 +229,7 @@ private:
} }
if (premise) { if (premise) {
expr_ref f1 = bind_variables(mk_implies(body, head)); expr_ref f1 = bind_variables(mk_implies(m_body, head));
expr* f2 = m.mk_and(sz, m_todo.c_ptr()+m_todo.size()-sz); expr* f2 = m.mk_and(sz, m_todo.c_ptr()+m_todo.size()-sz);
proof_ref p2(m), p3(m); proof_ref p2(m), p3(m);
p2 = m.mk_def_axiom(m.mk_iff(f1, f2)); p2 = m.mk_def_axiom(m.mk_iff(f1, f2));
@ -240,13 +245,13 @@ private:
} }
eliminate_disjunctions(body, defs); eliminate_disjunctions(m_body, m_defs);
p = mk_congruence(p, body, head, defs); p = mk_congruence(p, m_body, head, m_defs);
eliminate_quantifier_body(body, defs); eliminate_quantifier_body(m_body, m_defs);
p = mk_congruence(p, body, head, defs); p = mk_congruence(p, m_body, head, m_defs);
fml2 = mk_implies(body, head); fml2 = mk_implies(m_body, head);
fml = bind_variables(fml2); fml = bind_variables(fml2);

View file

@ -28,10 +28,8 @@ Revision History:
#include "well_sorted.h" #include "well_sorted.h"
void horn_subsume_model_converter::insert(app* head, expr* body) { void horn_subsume_model_converter::insert(app* head, expr* body) {
func_decl_ref pred(m); m_delay_head.push_back(head);
expr_ref body_res(m); m_delay_body.push_back(body);
VERIFY(mk_horn(head, body, pred, body_res));
insert(pred.get(), body_res.get());
} }
void horn_subsume_model_converter::insert(app* head, unsigned sz, expr* const* body) { void horn_subsume_model_converter::insert(app* head, unsigned sz, expr* const* body) {
@ -148,6 +146,7 @@ bool horn_subsume_model_converter::mk_horn(
} }
void horn_subsume_model_converter::add_default_proc::operator()(app* n) { void horn_subsume_model_converter::add_default_proc::operator()(app* n) {
// //
// predicates that have not been assigned values // predicates that have not been assigned values
// in the Horn model are assumed false. // in the Horn model are assumed false.
@ -174,6 +173,16 @@ void horn_subsume_model_converter::add_default_false_interpretation(expr* e, mod
void horn_subsume_model_converter::operator()(model_ref& mr) { void horn_subsume_model_converter::operator()(model_ref& mr) {
func_decl_ref pred(m);
expr_ref body_res(m);
for (unsigned i = 0; i < m_delay_head.size(); ++i) {
VERIFY(mk_horn(m_delay_head[i].get(), m_delay_body[i].get(), pred, body_res));
insert(pred.get(), body_res.get());
}
m_delay_head.reset();
m_delay_body.reset();
TRACE("mc", tout << m_funcs.size() << "\n"; model_smt2_pp(tout, m, *mr, 0);); TRACE("mc", tout << m_funcs.size() << "\n"; model_smt2_pp(tout, m, *mr, 0););
for (unsigned i = m_funcs.size(); i > 0; ) { for (unsigned i = m_funcs.size(); i > 0; ) {
--i; --i;

View file

@ -43,6 +43,8 @@ class horn_subsume_model_converter : public model_converter {
func_decl_ref_vector m_funcs; func_decl_ref_vector m_funcs;
expr_ref_vector m_bodies; expr_ref_vector m_bodies;
th_rewriter m_rewrite; th_rewriter m_rewrite;
app_ref_vector m_delay_head;
expr_ref_vector m_delay_body;
void add_default_false_interpretation(expr* e, model_ref& md); void add_default_false_interpretation(expr* e, model_ref& md);
@ -56,7 +58,9 @@ class horn_subsume_model_converter : public model_converter {
public: public:
horn_subsume_model_converter(ast_manager& m): m(m), m_funcs(m), m_bodies(m), m_rewrite(m) {} horn_subsume_model_converter(ast_manager& m):
m(m), m_funcs(m), m_bodies(m), m_rewrite(m),
m_delay_head(m), m_delay_body(m) {}
bool mk_horn(expr* clause, func_decl_ref& pred, expr_ref& body); bool mk_horn(expr* clause, func_decl_ref& pred, expr_ref& body);