3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-05-06 15:25:46 +00:00

Merge branch 'unstable' of https://git01.codeplex.com/z3 into unstable

This commit is contained in:
Christoph M. Wintersteiger 2013-09-24 18:06:59 +01:00
commit 07a4fb4381
6 changed files with 221 additions and 111 deletions

View file

@ -31,7 +31,7 @@ Revision History:
#include"ast_smt2_pp.h" #include"ast_smt2_pp.h"
#include"th_rewriter.h" #include"th_rewriter.h"
#include"var_subst.h" #include"var_subst.h"
#include"expr_substitution.h" #include"expr_safe_replace.h"
#include"pp.h" #include"pp.h"
#include"scoped_ctrl_c.h" #include"scoped_ctrl_c.h"
#include"cancel_eh.h" #include"cancel_eh.h"
@ -786,17 +786,12 @@ extern "C" {
RETURN_Z3(of_expr(0)); RETURN_Z3(of_expr(0));
} }
} }
expr_safe_replace subst(m);
expr_substitution subst(m);
for (unsigned i = 0; i < num_exprs; i++) { for (unsigned i = 0; i < num_exprs; i++) {
subst.insert(from[i], to[i]); subst.insert(from[i], to[i]);
} }
th_rewriter m_rw(m);
m_rw.set_substitution(&subst);
expr_ref new_a(m); expr_ref new_a(m);
proof_ref pr(m); subst(a, new_a);
m_rw(a, new_a, pr);
mk_c(c)->save_ast_trail(new_a); mk_c(c)->save_ast_trail(new_a);
r = new_a.get(); r = new_a.get();
RETURN_Z3(of_expr(r)); RETURN_Z3(of_expr(r));

View file

@ -61,9 +61,6 @@ namespace datalog {
} }
cost get_cost() const { cost get_cost() const {
/*if(m_instantiated) {
return std::numeric_limits<cost>::min();
}*/
SASSERT(m_consumers > 0); SASSERT(m_consumers > 0);
cost amortized = m_total_cost/m_consumers; cost amortized = m_total_cost/m_consumers;
if (m_stratified) { if (m_stratified) {
@ -81,13 +78,14 @@ namespace datalog {
by the time of a call to this function by the time of a call to this function
*/ */
void add_rule(join_planner & pl, app * t1, app * t2, rule * r, void add_rule(join_planner & pl, app * t1, app * t2, rule * r,
const var_idx_set & non_local_vars_normalized) { const var_idx_set & non_local_vars_normalized,
const var_idx_set & non_local_vars) {
if (m_rules.empty()) { if (m_rules.empty()) {
m_total_cost = pl.compute_cost(t1, t2); m_total_cost = pl.compute_cost(t1, t2, non_local_vars);
m_src_stratum = std::max(pl.get_stratum(t1->get_decl()), pl.get_stratum(t2->get_decl())); m_src_stratum = std::max(pl.get_stratum(t1->get_decl()), pl.get_stratum(t2->get_decl()));
} }
m_rules.push_back(r); m_rules.push_back(r);
if(pl.m_rules_content.find_core(r)->get_data().m_value.size()>2) { if (pl.m_rules_content.find(r).size()>2) {
m_consumers++; m_consumers++;
} }
if (m_stratified) { if (m_stratified) {
@ -274,8 +272,6 @@ namespace datalog {
by the time of a call to this function by the time of a call to this function
*/ */
void register_pair(app * t1, app * t2, rule * r, const var_idx_set & non_local_vars) { void register_pair(app * t1, app * t2, rule * r, const var_idx_set & non_local_vars) {
TRACE("dl", tout << mk_pp(t1, m) << " " << mk_pp(t2, m) << "\n";
r->display(m_context, tout); tout << "\n";);
SASSERT(t1!=t2); SASSERT(t1!=t2);
cost_map::entry * e = m_costs.insert_if_not_there2(get_key(t1, t2), 0); cost_map::entry * e = m_costs.insert_if_not_there2(get_key(t1, t2), 0);
pair_info * & ptr_inf = e->get_data().m_value; pair_info * & ptr_inf = e->get_data().m_value;
@ -295,13 +291,18 @@ namespace datalog {
normalized_vars.insert(norm_var); normalized_vars.insert(norm_var);
} }
inf.add_rule(*this, t1, t2, r, normalized_vars); inf.add_rule(*this, t1, t2, r, normalized_vars, non_local_vars);
TRACE("dl", tout << mk_pp(t1, m) << " " << mk_pp(t2, m) << " ";
vit = non_local_vars.begin();
for (; vit != vend; ++vit) tout << *vit << " ";
tout << "\n";
r->display(m_context, tout);
if (inf.can_be_joined()) tout << "cost: " << inf.get_cost() << "\n";);
} }
pair_info & get_pair(app_pair key) const { pair_info & get_pair(app_pair key) const {
cost_map::entry * e = m_costs.find_core(key); return *m_costs.find(key);
SASSERT(e);
return *e->get_data().m_value;
} }
void remove_rule_from_pair(app_pair key, rule * r, unsigned original_len) { void remove_rule_from_pair(app_pair key, rule * r, unsigned original_len) {
@ -503,7 +504,7 @@ namespace datalog {
void apply_binary_rule(rule * r, app_pair pair_key, app * t_new) { void apply_binary_rule(rule * r, app_pair pair_key, app * t_new) {
app * t1 = pair_key.first; app * t1 = pair_key.first;
app * t2 = pair_key.second; app * t2 = pair_key.second;
ptr_vector<app> & rule_content = m_rules_content.find_core(r)->get_data().m_value; ptr_vector<app> & rule_content = m_rules_content.find(r);
unsigned len = rule_content.size(); unsigned len = rule_content.size();
if (len==1) { if (len==1) {
return; return;
@ -600,21 +601,39 @@ namespace datalog {
return res; return res;
} }
cost compute_cost(app * t1, app * t2) const { cost compute_cost(app * t1, app * t2, const var_idx_set & non_local_vars) const {
func_decl * t1_pred = t1->get_decl(); func_decl * t1_pred = t1->get_decl();
func_decl * t2_pred = t2->get_decl(); func_decl * t2_pred = t2->get_decl();
cost inters_size = 1; cost inters_size = 1;
variable_intersection vi(m_context.get_manager()); variable_intersection vi(m_context.get_manager());
vi.populate(t1, t2); vi.populate(t1, t2);
unsigned n = vi.size(); unsigned n = vi.size();
// remove contributions from joined columns.
for(unsigned i=0; i<n; i++) { for(unsigned i=0; i<n; i++) {
unsigned arg_index1, arg_index2; unsigned arg_index1, arg_index2;
vi.get(i, arg_index1, arg_index2); vi.get(i, arg_index1, arg_index2);
SASSERT(is_var(t1->get_arg(arg_index1)));
if (non_local_vars.contains(to_var(t1->get_arg(arg_index1))->get_idx())) {
inters_size *= get_domain_size(t1_pred, arg_index1); inters_size *= get_domain_size(t1_pred, arg_index1);
}
//joined arguments must have the same domain //joined arguments must have the same domain
SASSERT(get_domain_size(t1_pred, arg_index1)==get_domain_size(t2_pred, arg_index2)); SASSERT(get_domain_size(t1_pred, arg_index1)==get_domain_size(t2_pred, arg_index2));
} }
cost res = estimate_size(t1)*estimate_size(t2)/(inters_size*inters_size); // remove contributions from projected columns.
for (unsigned i = 0; i < t1->get_num_args(); ++i) {
if (is_var(t1->get_arg(i)) &&
!non_local_vars.contains(to_var(t1->get_arg(i))->get_idx())) {
inters_size *= get_domain_size(t1_pred, i);
}
}
for (unsigned i = 0; i < t2->get_num_args(); ++i) {
if (is_var(t2->get_arg(i)) &&
!non_local_vars.contains(to_var(t2->get_arg(i))->get_idx())) {
inters_size *= get_domain_size(t2_pred, i);
}
}
cost res = estimate_size(t1)*estimate_size(t2)/ inters_size; // (inters_size*inters_size);
//cost res = -inters_size; //cost res = -inters_size;
/*unsigned t1_strat = get_stratum(t1_pred); /*unsigned t1_strat = get_stratum(t1_pred);

View file

@ -31,7 +31,6 @@ namespace datalog {
rm(ctx.get_rule_manager()), rm(ctx.get_rule_manager()),
m_rewriter(m, m_params), m_rewriter(m, m_params),
m_simplifier(ctx), m_simplifier(ctx),
m_sub(m),
m_next_var(0) { m_next_var(0) {
m_params.set_bool("expand_select_store",true); m_params.set_bool("expand_select_store",true);
m_rewriter.updt_params(m_params); m_rewriter.updt_params(m_params);
@ -82,7 +81,6 @@ namespace datalog {
return false; return false;
} }
if (v) { if (v) {
m_sub.insert(e, v);
m_defs.insert(e, to_var(v)); m_defs.insert(e, to_var(v));
} }
else { else {
@ -92,71 +90,113 @@ namespace datalog {
m_next_var = vars.size() + 1; m_next_var = vars.size() + 1;
} }
v = m.mk_var(m_next_var, m.get_sort(e)); v = m.mk_var(m_next_var, m.get_sort(e));
m_sub.insert(e, v);
m_defs.insert(e, v); m_defs.insert(e, v);
++m_next_var; ++m_next_var;
} }
return true; return true;
} }
bool mk_array_blast::ackermanize(rule const& r, expr_ref& body, expr_ref& head) { bool mk_array_blast::is_select_eq_var(expr* e, app*& s, var*& v) const {
expr_ref_vector conjs(m);
qe::flatten_and(body, conjs);
m_defs.reset();
m_sub.reset();
m_next_var = 0;
ptr_vector<expr> todo;
todo.push_back(head);
for (unsigned i = 0; i < conjs.size(); ++i) {
expr* e = conjs[i].get();
expr* x, *y; expr* x, *y;
if (m.is_eq(e, x, y) || m.is_iff(e, x, y)) { if (m.is_eq(e, x, y) || m.is_iff(e, x, y)) {
if (a.is_select(y)) { if (a.is_select(y)) {
std::swap(x,y); std::swap(x,y);
} }
if (a.is_select(x) && is_var(y)) { if (a.is_select(x) && is_var(y)) {
if (!insert_def(r, to_app(x), to_var(y))) { s = to_app(x);
v = to_var(y);
return true;
}
}
return false; return false;
} }
bool mk_array_blast::ackermanize(rule const& r, expr_ref& body, expr_ref& head) {
expr_ref_vector conjs(m), trail(m);
qe::flatten_and(body, conjs);
m_defs.reset();
m_next_var = 0;
ptr_vector<expr> todo;
obj_map<expr, expr*> cache;
ptr_vector<expr> args;
app_ref e1(m);
app* s;
var* v;
for (unsigned i = 0; i < conjs.size(); ++i) {
expr* e = conjs[i].get();
if (is_select_eq_var(e, s, v)) {
todo.append(s->get_num_args(), s->get_args());
} }
} else {
if (a.is_select(e) && !insert_def(r, to_app(e), 0)) {
return false;
}
todo.push_back(e); todo.push_back(e);
} }
// now make sure to cover all occurrences. }
ast_mark mark;
while (!todo.empty()) { while (!todo.empty()) {
expr* e = todo.back(); expr* e = todo.back();
if (cache.contains(e)) {
todo.pop_back(); todo.pop_back();
if (mark.is_marked(e)) {
continue; continue;
} }
mark.mark(e, true);
if (is_var(e)) { if (is_var(e)) {
cache.insert(e, e);
todo.pop_back();
continue; continue;
} }
if (!is_app(e)) { if (!is_app(e)) {
return false; return false;
} }
app* ap = to_app(e); app* ap = to_app(e);
if (a.is_select(ap) && !m_defs.contains(ap)) { bool valid = true;
if (!insert_def(r, ap, 0)) { args.reset();
for (unsigned i = 0; i < ap->get_num_args(); ++i) {
expr* arg;
if (cache.find(ap->get_arg(i), arg)) {
args.push_back(arg);
}
else {
todo.push_back(ap->get_arg(i));
valid = false;
}
}
if (valid) {
todo.pop_back();
e1 = m.mk_app(ap->get_decl(), args.size(), args.c_ptr());
trail.push_back(e1);
if (a.is_select(ap)) {
if (m_defs.find(e1, v)) {
cache.insert(e, v);
}
else if (!insert_def(r, e1, 0)) {
return false; return false;
} }
} else {
if (a.is_select(e)) { cache.insert(e, m_defs.find(e1));
get_select_args(e, todo); }
continue; }
} else {
for (unsigned i = 0; i < ap->get_num_args(); ++i) { cache.insert(e, e1);
todo.push_back(ap->get_arg(i)); }
}
}
for (unsigned i = 0; i < conjs.size(); ++i) {
expr* e = conjs[i].get();
if (is_select_eq_var(e, s, v)) {
args.reset();
for (unsigned j = 0; j < s->get_num_args(); ++j) {
args.push_back(cache.find(s->get_arg(j)));
}
e1 = m.mk_app(s->get_decl(), args.size(), args.c_ptr());
if (!m_defs.contains(e1) && !insert_def(r, e1, v)) {
return false;
}
conjs[i] = m.mk_eq(v, m_defs.find(e1));
}
else {
conjs[i] = cache.find(e);
} }
} }
m_sub(body);
m_sub(head);
conjs.reset();
// perform the Ackermann reduction by creating implications // perform the Ackermann reduction by creating implications
// i1 = i2 => val1 = val2 for each equality pair: // i1 = i2 => val1 = val2 for each equality pair:
@ -171,6 +211,7 @@ namespace datalog {
for (; it2 != end; ++it2) { for (; it2 != end; ++it2) {
app* a2 = it2->m_key; app* a2 = it2->m_key;
var* v2 = it2->m_value; var* v2 = it2->m_value;
TRACE("dl", tout << mk_pp(a1, m) << " " << mk_pp(a2, m) << "\n";);
if (get_select(a1) != get_select(a2)) { if (get_select(a1) != get_select(a2)) {
continue; continue;
} }
@ -184,10 +225,7 @@ namespace datalog {
conjs.push_back(m.mk_implies(m.mk_and(eqs.size(), eqs.c_ptr()), m.mk_eq(v1, v2))); conjs.push_back(m.mk_implies(m.mk_and(eqs.size(), eqs.c_ptr()), m.mk_eq(v1, v2)));
} }
} }
if (!conjs.empty()) {
conjs.push_back(body);
body = m.mk_and(conjs.size(), conjs.c_ptr()); body = m.mk_and(conjs.size(), conjs.c_ptr());
}
m_rewriter(body); m_rewriter(body);
return true; return true;
} }

View file

@ -44,7 +44,6 @@ namespace datalog {
mk_interp_tail_simplifier m_simplifier; mk_interp_tail_simplifier m_simplifier;
defs_t m_defs; defs_t m_defs;
expr_safe_replace m_sub;
unsigned m_next_var; unsigned m_next_var;
bool blast(rule& r, rule_set& new_rules); bool blast(rule& r, rule_set& new_rules);
@ -59,6 +58,8 @@ namespace datalog {
bool insert_def(rule const& r, app* e, var* v); bool insert_def(rule const& r, app* e, var* v);
bool is_select_eq_var(expr* e, app*& s, var*& v) const;
public: public:
/** /**
\brief Create rule transformer that removes array stores and selects by ackermannization. \brief Create rule transformer that removes array stores and selects by ackermannization.

View file

@ -0,0 +1,56 @@
#include "expr_substitution.h"
#include "smt_params.h"
#include "substitution.h"
#include "unifier.h"
#include "bv_decl_plugin.h"
#include "ast_pp.h"
#include "arith_decl_plugin.h"
#include "reg_decl_plugins.h"
#include "th_rewriter.h"
expr* mk_bv_xor(bv_util& bv, expr* a, expr* b) {
expr* args[2];
args[0] = a;
args[1] = b;
return bv.mk_bv_xor(2, args);
}
expr* mk_bv_and(bv_util& bv, expr* a, expr* b) {
expr* args[2];
args[0] = a;
args[1] = b;
ast_manager& m = bv.get_manager();
return m.mk_app(bv.get_family_id(), OP_BAND, 2, args);
}
void tst_expr_substitution() {
memory::initialize(0);
ast_manager m;
reg_decl_plugins(m);
bv_util bv(m);
expr_ref a(m), b(m), c(m), d(m);
expr_ref x(m);
expr_ref new_a(m);
proof_ref pr(m);
x = m.mk_const(symbol("x"), bv.mk_sort(8));
a = mk_bv_and(bv, mk_bv_xor(bv, x,bv.mk_numeral(8,8)), mk_bv_xor(bv,x,x));
b = x;
c = bv.mk_bv_sub(x, bv.mk_numeral(4, 8));
expr_substitution subst(m);
th_rewriter rw(m);
// normalizing c does not help.
rw(c, d, pr);
subst.insert(b, d);
rw.set_substitution(&subst);
enable_trace("th_rewriter_step");
rw(a, new_a, pr);
std::cout << mk_pp(new_a, m) << "\n";
}

View file

@ -215,6 +215,7 @@ int main(int argc, char ** argv) {
TST(rcf); TST(rcf);
TST(polynorm); TST(polynorm);
TST(qe_arith); TST(qe_arith);
TST(expr_substitution);
} }
void initialize_mam() {} void initialize_mam() {}