3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 13:28:47 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-03-17 18:02:30 -07:00
parent 55ebb236db
commit 752b498254
2 changed files with 48 additions and 28 deletions

View file

@ -376,7 +376,6 @@ namespace opt {
if (optp.dump_models()) { if (optp.dump_models()) {
model_ref md = m->copy(); model_ref md = m->copy();
fix_model(md); fix_model(md);
std::cout << *md << "\n";
} }
} }

View file

@ -75,12 +75,20 @@ class eq2bv_tactic : public tactic {
class bvmc : public model_converter { class bvmc : public model_converter {
obj_map<func_decl, func_decl*> m_map; obj_map<func_decl, func_decl*> m_map;
func_decl_ref_vector m_vars;
unsigned_vector m_values;
public: public:
bvmc(ast_manager& m): m_vars(m) {}
void insert(func_decl* c_new, func_decl* c_old) { void insert(func_decl* c_new, func_decl* c_old) {
m_map.insert(c_new, c_old); m_map.insert(c_new, c_old);
} }
void insert(func_decl* var, unsigned val) {
m_vars.push_back(var);
m_values.push_back(val);
}
void operator()(model_ref& mdl) override { void operator()(model_ref& mdl) override {
ast_manager& m = mdl->get_manager(); ast_manager& m = mdl->get_manager();
bv_util bv(m); bv_util bv(m);
@ -101,21 +109,33 @@ class eq2bv_tactic : public tactic {
new_m->register_decl(f, val); new_m->register_decl(f, val);
} }
} }
for (unsigned i = 0; i < m_vars.size(); ++i) {
func_decl* f = m_vars.get(i);
new_m->register_decl(f, a.mk_numeral(rational(m_values[i]), f->get_range()));
}
mdl = new_m; mdl = new_m;
} }
model_converter* translate(ast_translation & translator) override { model_converter* translate(ast_translation & translator) override {
bvmc* v = alloc(bvmc); bvmc* v = alloc(bvmc, translator.to());
for (auto const& kv : m_map) { for (auto const& kv : m_map) {
v->m_map.insert(translator(kv.m_key), translator(kv.m_value)); v->m_map.insert(translator(kv.m_key), translator(kv.m_value));
} }
for (unsigned i = 0; i < m_vars.size(); ++i) {
v->insert(translator(m_vars.get(i)), m_values[i]);
}
return v; return v;
} }
void display(std::ostream & out) override { void display(std::ostream & out) override {
ast_manager& m = m_vars.get_manager();
for (auto const& kv : m_map) { for (auto const& kv : m_map) {
out << "(model-set " << kv.m_key->get_name() << " " << kv.m_value->get_name() << ")\n"; out << "(model-set " << kv.m_key->get_name() << " " << kv.m_value->get_name() << ")\n";
} }
for (unsigned i = 0; i < m_vars.size(); ++i) {
func_decl* v = m_vars.get(i);
out << "(model-add " << v->get_name() << " () " << mk_pp(v->get_range(), m) << " " << m_values[i] << ")\n";
}
} }
void get_units(obj_map<expr, bool>& units) override { units.reset(); } void get_units(obj_map<expr, bool>& units) override { units.reset(); }
@ -156,7 +176,7 @@ public:
m_max.reset(); m_max.reset();
m_nonfd.reset(); m_nonfd.reset();
m_bounds.reset(); m_bounds.reset();
ref<bvmc> mc1 = alloc(bvmc); ref<bvmc> mc1 = alloc(bvmc, m);
tactic_report report("eq2bv", *g); tactic_report report("eq2bv", *g);
@ -175,8 +195,11 @@ public:
for (unsigned i = 0; i < g->size(); i++) { for (unsigned i = 0; i < g->size(); i++) {
expr_ref new_curr(m); expr_ref new_curr(m);
proof_ref new_pr(m); proof_ref new_pr(m);
if (is_bound(g->form(i))) { func_decl_ref var(m);
unsigned val;
if (is_bound(g->form(i), var, val)) {
g->update(i, m.mk_true(), nullptr, nullptr); g->update(i, m.mk_true(), nullptr, nullptr);
mc1->insert(var, val);
continue; continue;
} }
m_rw(g->form(i), new_curr, new_pr); m_rw(g->form(i), new_curr, new_pr);
@ -186,9 +209,8 @@ public:
} }
g->update(i, new_curr, new_pr, g->dep(i)); g->update(i, new_curr, new_pr, g->dep(i));
} }
obj_map<expr, unsigned>::iterator it = m_max.begin(), end = m_max.end(); for (auto & kv : m_max) {
for (; it != end; ++it) { expr* c = kv.m_key;
expr* c = it->m_key;
bool strict; bool strict;
rational r; rational r;
expr_ref fml(m); expr_ref fml(m);
@ -224,36 +246,33 @@ public:
void cleanup_fd(ref<bvmc>& mc) { void cleanup_fd(ref<bvmc>& mc) {
SASSERT(m_fd.empty()); SASSERT(m_fd.empty());
ptr_vector<expr> rm; ptr_vector<expr> rm;
obj_map<expr, unsigned>::iterator it = m_max.begin(), end = m_max.end(); for (auto& kv : m_max) {
for (; it != end; ++it) { if (m_nonfd.is_marked(kv.m_key)) {
if (m_nonfd.is_marked(it->m_key)) { rm.push_back(kv.m_key);
rm.push_back(it->m_key);
} }
} }
for (unsigned i = 0; i < rm.size(); ++i) { for (unsigned i = 0; i < rm.size(); ++i) {
m_max.erase(rm[i]); m_max.erase(rm[i]);
} }
it = m_max.begin(); for (auto& kv : m_max) {
end = m_max.end();
for (; it != end; ++it) {
// ensure there are enough elements. // ensure there are enough elements.
bool strict; bool strict;
rational val; rational val;
if (m_bounds.has_upper(it->m_key, val, strict)) { if (m_bounds.has_upper(kv.m_key, val, strict)) {
SASSERT(!strict); SASSERT(!strict);
if (val.get_unsigned() > it->m_value) it->m_value = val.get_unsigned(); if (val.get_unsigned() > kv.m_value) kv.m_value = val.get_unsigned();
} }
else { else {
++it->m_value; ++kv.m_value;
} }
unsigned p = next_power_of_two(it->m_value); unsigned p = next_power_of_two(kv.m_value);
if (p <= 1) p = 2; if (p <= 1) p = 2;
if (it->m_value == p) p *= 2; if (kv.m_value == p) p *= 2;
unsigned n = log2(p); unsigned n = log2(p);
app* z = m.mk_fresh_const("z", bv.mk_sort(n)); app* z = m.mk_fresh_const("z", bv.mk_sort(n));
m_trail.push_back(z); m_trail.push_back(z);
m_fd.insert(it->m_key, z); m_fd.insert(kv.m_key, z);
mc->insert(z->get_decl(), to_app(it->m_key)->get_decl()); mc->insert(z->get_decl(), to_app(kv.m_key)->get_decl());
} }
} }
@ -268,32 +287,34 @@ public:
} }
} }
bool is_upper(expr* f) { bool is_upper(expr* f, func_decl_ref& var, unsigned& k) {
expr* e1, *e2; expr* e1, *e2;
unsigned k;
if ((a.is_le(f, e1, e2) || a.is_ge(f, e2, e1)) && is_var_const_pair(e1, e2, k)) { if ((a.is_le(f, e1, e2) || a.is_ge(f, e2, e1)) && is_var_const_pair(e1, e2, k)) {
SASSERT(m_bounds.has_upper(e1)); SASSERT(m_bounds.has_upper(e1));
var = to_app(e1)->get_decl();
return true; return true;
} }
return false; return false;
} }
bool is_lower(expr* f) { bool is_lower(expr* f, func_decl_ref& var, unsigned& k) {
expr* e1, *e2; expr* e1, *e2;
unsigned k;
if ((a.is_le(f, e1, e2) || a.is_ge(f, e2, e1)) && is_var_const_pair(e2, e1, k)) { if ((a.is_le(f, e1, e2) || a.is_ge(f, e2, e1)) && is_var_const_pair(e2, e1, k)) {
SASSERT(m_bounds.has_lower(e2)); SASSERT(m_bounds.has_lower(e2));
var = to_app(e2)->get_decl();
return true; return true;
} }
return false; return false;
} }
bool is_bound(expr* f) { bool is_bound(expr* f, func_decl_ref& var, unsigned& val) {
return is_lower(f) || is_upper(f); return is_lower(f, var, val) || is_upper(f, var, val);
} }
void collect_fd(expr* f) { void collect_fd(expr* f) {
if (is_bound(f)) return; func_decl_ref var(m);
unsigned val;
if (is_bound(f, var, val)) return;
m_todo.push_back(f); m_todo.push_back(f);
while (!m_todo.empty()) { while (!m_todo.empty()) {
f = m_todo.back(); f = m_todo.back();