3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-10-25 17:04:36 +00:00

have free variable utility use a class for more efficient re-use

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-09-15 16:14:22 -07:00
parent 73070585b8
commit c09903288f
39 changed files with 300 additions and 303 deletions

View file

@ -334,21 +334,13 @@ namespace datalog {
else {
m_names.reset();
m_abstractor(0, vars.size(), reinterpret_cast<expr*const*>(vars.c_ptr()), fml, result);
rm.collect_vars(result);
ptr_vector<sort>& sorts = rm.get_var_sorts();
if (sorts.empty()) {
m_free_vars(result);
if (m_free_vars.empty()) {
result = fml;
}
else {
for (unsigned i = 0; i < sorts.size(); ++i) {
if (!sorts[i]) {
if (i < vars.size()) {
sorts[i] = vars[i]->get_decl()->get_range();
}
else {
sorts[i] = m.mk_bool_sort();
}
}
m_free_vars.set_default_sort(m.mk_bool_sort());
for (unsigned i = 0; i < m_free_vars.size(); ++i) {
if (i < vars.size()) {
m_names.push_back(vars[i]->get_decl()->get_name());
}
@ -357,8 +349,8 @@ namespace datalog {
}
}
quantifier_ref q(m);
sorts.reverse();
q = m.mk_quantifier(is_forall, sorts.size(), sorts.c_ptr(), m_names.c_ptr(), result);
m_free_vars.reverse();
q = m.mk_quantifier(is_forall, m_free_vars.size(), m_free_vars.c_ptr(), m_names.c_ptr(), result);
m_elim_unused_vars(q, result);
}
}
@ -604,7 +596,7 @@ namespace datalog {
unsigned ut_size = r.get_uninterpreted_tail_size();
unsigned t_size = r.get_tail_size();
TRACE("dl", r.display_smt2(get_manager(), tout); tout << "\n";);
TRACE("dl", get_rule_manager().display_smt2(r, tout); tout << "\n";);
for (unsigned i = ut_size; i < t_size; ++i) {
app* t = r.get_tail(i);
TRACE("dl", tout << "checking: " << mk_ismt2_pp(t, get_manager()) << "\n";);
@ -1121,13 +1113,13 @@ namespace datalog {
void context::get_rules_as_formulas(expr_ref_vector& rules, expr_ref_vector& queries, svector<symbol>& names) {
expr_ref fml(m);
datalog::rule_manager& rm = get_rule_manager();
rule_manager& rm = get_rule_manager();
// ensure that rules are all using bound variables.
for (unsigned i = m_rule_fmls_head; i < m_rule_fmls.size(); ++i) {
ptr_vector<sort> sorts;
get_free_vars(m_rule_fmls[i].get(), sorts);
if (!sorts.empty()) {
m_free_vars(m_rule_fmls[i].get());
if (!m_free_vars.empty()) {
rm.mk_rule(m_rule_fmls[i].get(), 0, m_rule_set, m_rule_names[i]);
m_rule_fmls[i] = m_rule_fmls.back();
m_rule_names[i] = m_rule_names.back();
@ -1139,7 +1131,7 @@ namespace datalog {
rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end();
for (; it != end; ++it) {
rule* r = *it;
r->to_formula(fml);
rm.to_formula(*r, fml);
func_decl* h = r->get_decl();
if (m_rule_set.is_output_predicate(h)) {
expr* body = fml;

View file

@ -191,6 +191,7 @@ namespace datalog {
pred2syms m_argument_var_names;
rule_set m_rule_set;
rule_set m_transformed_rule_set;
expr_free_vars m_free_vars;
unsigned m_rule_fmls_head;
expr_ref_vector m_rule_fmls;
svector<symbol> m_rule_names;

View file

@ -111,16 +111,14 @@ namespace datalog {
}
void rule_manager::reset_collect_vars() {
m_vars.reset();
m_var_idx.reset();
m_todo.reset();
m_mark.reset();
m_free_vars.reset();
}
var_idx_set& rule_manager::finalize_collect_vars() {
unsigned sz = m_vars.size();
for (unsigned i=0; i<sz; ++i) {
if (m_vars[i]) m_var_idx.insert(i);
unsigned sz = m_free_vars.size();
for (unsigned i = 0; i < sz; ++i) {
if (m_free_vars[i]) m_var_idx.insert(i);
}
return m_var_idx;
}
@ -157,7 +155,7 @@ namespace datalog {
}
void rule_manager::accumulate_vars(expr* e) {
::get_free_vars(m_mark, m_todo, e, m_vars);
m_free_vars.accumulate(e);
}
@ -188,8 +186,6 @@ namespace datalog {
}
void rule_manager::mk_rule_core(expr* fml, proof* p, rule_set& rules, symbol const& name) {
DEBUG_CODE(ptr_vector<sort> sorts;
::get_free_vars(fml, sorts); );
expr_ref_vector fmls(m);
proof_ref_vector prs(m);
m_hnf.reset();
@ -200,8 +196,6 @@ namespace datalog {
m_ctx.register_predicate(m_hnf.get_fresh_predicates()[i], false);
}
for (unsigned i = 0; i < fmls.size(); ++i) {
DEBUG_CODE(ptr_vector<sort> sorts;
::get_free_vars(fmls[i].get(), sorts); );
mk_horn_rule(fmls[i].get(), prs[i].get(), rules, name);
}
}
@ -228,7 +222,7 @@ namespace datalog {
expr_ref fml1(m);
if (p) {
r->to_formula(fml1);
to_formula(*r, fml1);
if (fml1 == fml) {
// no-op.
}
@ -246,7 +240,7 @@ namespace datalog {
if (p) {
expr_ref fml2(m);
r->to_formula(fml2);
to_formula(*r, fml2);
if (fml1 != fml2) {
p = m.mk_modus_ponens(p, m.mk_rewrite(fml1, fml2));
}
@ -299,7 +293,8 @@ namespace datalog {
quantifier_hoister qh(m);
qh.pull_quantifier(false, q, 0, &names);
// retrieve free variables.
get_free_vars(q, vars);
m_free_vars(q);
vars.append(m_free_vars.size(), m_free_vars.c_ptr());
if (vars.contains(static_cast<sort*>(0))) {
var_subst sub(m, false);
expr_ref_vector args(m);
@ -316,7 +311,8 @@ namespace datalog {
}
sub(q, args.size(), args.c_ptr(), q);
vars.reset();
get_free_vars(q, vars);
m_free_vars(q);
vars.append(m_free_vars.size(), m_free_vars.c_ptr());
}
SASSERT(!vars.contains(static_cast<sort*>(0)) && "Unused variables have been eliminated");
@ -498,11 +494,6 @@ namespace datalog {
app * * uninterp_tail = r->m_tail; //grows upwards
app * * interp_tail = r->m_tail+n; //grows downwards
DEBUG_CODE(ptr_vector<sort> sorts;
::get_free_vars(head, sorts);
for (unsigned i = 0; i < n; ++i) {
::get_free_vars(tail[i], sorts);
});
bool has_neg = false;
@ -556,11 +547,6 @@ namespace datalog {
if (normalize) {
r->norm_vars(*this);
}
DEBUG_CODE(ptr_vector<sort> sorts;
::get_free_vars(head, sorts);
for (unsigned i = 0; i < n; ++i) {
::get_free_vars(tail[i], sorts);
});
return r;
}
@ -587,6 +573,55 @@ namespace datalog {
return r;
}
void rule_manager::to_formula(rule const& r, expr_ref& fml) {
ast_manager & m = fml.get_manager();
expr_ref_vector body(m);
for (unsigned i = 0; i < r.get_tail_size(); i++) {
body.push_back(r.get_tail(i));
if (r.is_neg_tail(i)) {
body[body.size()-1] = m.mk_not(body.back());
}
}
fml = r.get_head();
switch (body.size()) {
case 0: break;
case 1: fml = m.mk_implies(body[0].get(), fml); break;
default: fml = m.mk_implies(m.mk_and(body.size(), body.c_ptr()), fml); break;
}
m_free_vars(fml);
if (m_free_vars.empty()) {
return;
}
svector<symbol> names;
used_symbols<> us;
m_free_vars.set_default_sort(m.mk_bool_sort());
us(fml);
m_free_vars.reverse();
for (unsigned j = 0, i = 0; i < m_free_vars.size(); ++j) {
for (char c = 'A'; i < m_free_vars.size() && c <= 'Z'; ++c) {
func_decl_ref f(m);
std::stringstream _name;
_name << c;
if (j > 0) _name << j;
symbol name(_name.str().c_str());
if (!us.contains(name)) {
names.push_back(name);
++i;
}
}
}
fml = m.mk_forall(m_free_vars.size(), m_free_vars.c_ptr(), names.c_ptr(), fml);
}
std::ostream& rule_manager::display_smt2(rule const& r, std::ostream & out) {
expr_ref fml(m);
to_formula(r, fml);
return out << mk_ismt2_pp(fml, m);
}
void rule_manager::reduce_unbound_vars(rule_ref& r) {
unsigned ut_len = r->get_uninterpreted_tail_size();
unsigned t_len = r->get_tail_size();
@ -647,9 +682,7 @@ namespace datalog {
svector<bool> tail_neg;
app_ref head(r->get_head(), m);
collect_rule_vars(r);
vctr.count_vars(m, head);
ptr_vector<sort>& free_rule_vars = m_vars;
for (unsigned i = 0; i < ut_len; i++) {
app * t = r->get_tail(i);
@ -658,18 +691,16 @@ namespace datalog {
tail_neg.push_back(r->is_neg_tail(i));
}
ptr_vector<sort> interp_vars;
var_idx_set unbound_vars;
expr_ref_vector tails_with_unbound(m);
for (unsigned i = ut_len; i < t_len; i++) {
app * t = r->get_tail(i);
interp_vars.reset();
::get_free_vars(t, interp_vars);
m_free_vars(t);
bool has_unbound = false;
unsigned iv_size = interp_vars.size();
unsigned iv_size = m_free_vars.size();
for (unsigned i=0; i<iv_size; i++) {
if (!interp_vars[i]) { continue; }
if (!m_free_vars[i]) { continue; }
if (vctr.get(i)==0) {
has_unbound = true;
unbound_vars.insert(i);
@ -693,16 +724,15 @@ namespace datalog {
bool_rewriter(m).mk_and(tails_with_unbound.size(), tails_with_unbound.c_ptr(), unbound_tail);
unsigned q_var_cnt = unbound_vars.num_elems();
unsigned max_var = m_counter.get_max_rule_var(*r);
collect_rule_vars(r);
expr_ref_vector subst(m);
ptr_vector<sort> qsorts;
qsorts.resize(q_var_cnt);
unsigned q_idx = 0;
for (unsigned v = 0; v <= max_var; ++v) {
sort * v_sort = free_rule_vars[v];
for (unsigned v = 0; v < m_free_vars.size(); ++v) {
sort * v_sort = m_free_vars[v];
if (!v_sort) {
//this variable index is not used
continue;
@ -780,7 +810,7 @@ namespace datalog {
!new_rule.get_proof() &&
old_rule.get_proof()) {
expr_ref fml(m);
new_rule.to_formula(fml);
to_formula(new_rule, fml);
scoped_proof _sc(m);
proof* p = m.mk_rewrite(m.get_fact(old_rule.get_proof()), fml);
new_rule.set_proof(m, m.mk_modus_ponens(old_rule.get_proof(), p));
@ -791,7 +821,7 @@ namespace datalog {
if (m_ctx.generate_proof_trace()) {
scoped_proof _scp(m);
expr_ref fml(m);
r.to_formula(fml);
to_formula(r, fml);
r.set_proof(m, m.mk_asserted(fml));
}
}
@ -1066,57 +1096,6 @@ namespace datalog {
}
}
void rule::to_formula(expr_ref& fml) const {
ast_manager & m = fml.get_manager();
expr_ref_vector body(m);
for (unsigned i = 0; i < m_tail_size; i++) {
body.push_back(get_tail(i));
if (is_neg_tail(i)) {
body[body.size()-1] = m.mk_not(body.back());
}
}
switch(body.size()) {
case 0: fml = m_head; break;
case 1: fml = m.mk_implies(body[0].get(), m_head); break;
default: fml = m.mk_implies(m.mk_and(body.size(), body.c_ptr()), m_head); break;
}
ptr_vector<sort> sorts;
get_free_vars(fml, sorts);
if (sorts.empty()) {
return;
}
svector<symbol> names;
used_symbols<> us;
for (unsigned i = 0; i < sorts.size(); ++i) {
if (!sorts[i]) {
sorts[i] = m.mk_bool_sort();
}
}
us(fml);
sorts.reverse();
for (unsigned j = 0, i = 0; i < sorts.size(); ++j) {
for (char c = 'A'; i < sorts.size() && c <= 'Z'; ++c) {
func_decl_ref f(m);
std::stringstream _name;
_name << c;
if (j > 0) _name << j;
symbol name(_name.str().c_str());
if (!us.contains(name)) {
names.push_back(name);
++i;
}
}
}
fml = m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), fml);
}
std::ostream& rule::display_smt2(ast_manager& m, std::ostream & out) const {
expr_ref fml(m);
to_formula(fml);
return out << mk_ismt2_pp(fml, m);
}
bool rule_eq_proc::operator()(const rule * r1, const rule * r2) const {
if (r1->get_head()!=r2->get_head()) { return false; }

View file

@ -30,6 +30,7 @@ Revision History:
#include"rewriter.h"
#include"hnf.h"
#include"qe_lite.h"
#include"var_subst.h"
namespace datalog {
@ -64,10 +65,8 @@ namespace datalog {
context& m_ctx;
rule_counter m_counter;
used_vars m_used;
ptr_vector<sort> m_vars;
var_idx_set m_var_idx;
ptr_vector<expr> m_todo;
ast_mark m_mark;
expr_free_vars m_free_vars;
app_ref_vector m_body;
app_ref m_head;
expr_ref_vector m_args;
@ -143,7 +142,7 @@ namespace datalog {
void accumulate_vars(expr* pred);
ptr_vector<sort>& get_var_sorts() { return m_vars; }
// ptr_vector<sort>& get_var_sorts() { return m_vars; }
var_idx_set& get_var_idx() { return m_var_idx; }
@ -213,11 +212,14 @@ namespace datalog {
*/
bool is_fact(app * head) const;
static bool is_forall(ast_manager& m, expr* e, quantifier*& q);
rule_counter& get_counter() { return m_counter; }
void to_formula(rule const& r, expr_ref& result);
std::ostream& display_smt2(rule const& r, std::ostream & out);
};
class rule : public accounted_object {
@ -306,12 +308,8 @@ namespace datalog {
void get_vars(ast_manager& m, ptr_vector<sort>& sorts) const;
void to_formula(expr_ref& result) const;
void display(context & ctx, std::ostream & out) const;
std::ostream& display_smt2(ast_manager& m, std::ostream & out) const;
symbol const& name() const { return m_name; }
unsigned hash() const;

View file

@ -39,10 +39,10 @@ namespace datalog {
Each master object is also present as a key of the map, even if its master set
is empty.
*/
deps_type m_data;
context & m_context;
deps_type m_data;
context & m_context;
ptr_vector<expr> m_todo;
ast_mark m_visited;
expr_sparse_mark m_visited;
//we need to take care with removing to avoid memory leaks

View file

@ -56,9 +56,9 @@ namespace datalog {
bool contains_var(expr * trm, unsigned var_idx) {
ptr_vector<sort> vars;
::get_free_vars(trm, vars);
return var_idx < vars.size() && vars[var_idx] != 0;
expr_free_vars fv;
fv(trm);
return fv.contains(var_idx);
}
unsigned count_variable_arguments(app * pred)
@ -300,14 +300,15 @@ namespace datalog {
}
void resolve_rule(replace_proof_converter* pc, rule const& r1, rule const& r2, unsigned idx,
void resolve_rule(rule_manager& rm,
replace_proof_converter* pc, rule const& r1, rule const& r2, unsigned idx,
expr_ref_vector const& s1, expr_ref_vector const& s2, rule const& res) {
if (!pc) return;
ast_manager& m = s1.get_manager();
expr_ref fml1(m), fml2(m), fml3(m);
r1.to_formula(fml1);
r2.to_formula(fml2);
res.to_formula(fml3);
rm.to_formula(r1, fml1);
rm.to_formula(r2, fml2);
rm.to_formula(res, fml3);
vector<expr_ref_vector> substs;
svector<std::pair<unsigned, unsigned> > positions;
substs.push_back(s1);
@ -337,7 +338,7 @@ namespace datalog {
pc->insert(pr);
}
void resolve_rule(rule const& r1, rule const& r2, unsigned idx,
void resolve_rule(rule_manager& rm, rule const& r1, rule const& r2, unsigned idx,
expr_ref_vector const& s1, expr_ref_vector const& s2, rule& res) {
if (!r1.get_proof()) {
return;
@ -345,7 +346,7 @@ namespace datalog {
SASSERT(r2.get_proof());
ast_manager& m = s1.get_manager();
expr_ref fml(m);
res.to_formula(fml);
rm.to_formula(res, fml);
vector<expr_ref_vector> substs;
svector<std::pair<unsigned, unsigned> > positions;
substs.push_back(s1);

View file

@ -41,6 +41,7 @@ namespace datalog {
class pentagon_relation;
class relation_fact;
class relation_signature;
class rule_manager;
class verbose_action {
unsigned m_lvl;
@ -345,17 +346,19 @@ namespace datalog {
class rule_counter : public var_counter {
public:
rule_counter(bool stay_non_negative = true): var_counter(stay_non_negative) {}
rule_counter(){}
void count_rule_vars(ast_manager & m, const rule * r, int coef = 1);
unsigned get_max_rule_var(const rule& r);
};
void del_rule(horn_subsume_model_converter* mc, rule& r);
void resolve_rule(replace_proof_converter* pc, rule const& r1, rule const& r2, unsigned idx,
void resolve_rule(rule_manager& rm,
replace_proof_converter* pc, rule const& r1, rule const& r2, unsigned idx,
expr_ref_vector const& s1, expr_ref_vector const& s2, rule const& res);
void resolve_rule(rule const& r1, rule const& r2, unsigned idx,
void resolve_rule(rule_manager& rm,
rule const& r1, rule const& r2, unsigned idx,
expr_ref_vector const& s1, expr_ref_vector const& s2, rule& res);
model_converter* mk_skip_model_converter();

View file

@ -87,6 +87,7 @@ class hnf::imp {
expr_ref_vector m_body;
proof_ref_vector m_defs;
contains_predicate_proc m_proc;
expr_free_vars m_free_vars;
public:
@ -350,13 +351,13 @@ private:
}
app_ref mk_fresh_head(expr* e) {
ptr_vector<sort> sorts0, sorts1;
get_free_vars(e, sorts0);
ptr_vector<sort> sorts1;
m_free_vars(e);
expr_ref_vector args(m);
for (unsigned i = 0; i < sorts0.size(); ++i) {
if (sorts0[i]) {
args.push_back(m.mk_var(i, sorts0[i]));
sorts1.push_back(sorts0[i]);
for (unsigned i = 0; i < m_free_vars.size(); ++i) {
if (m_free_vars[i]) {
args.push_back(m.mk_var(i, m_free_vars[i]));
sorts1.push_back(m_free_vars[i]);
}
}
func_decl_ref f(m);