mirror of
https://github.com/Z3Prover/z3
synced 2025-04-15 13:28:47 +00:00
propagate bounds implementation
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
d7186eede8
commit
8fc58e1ace
|
@ -19,6 +19,7 @@ Author:
|
||||||
#include "bv_bounds_tactic.h"
|
#include "bv_bounds_tactic.h"
|
||||||
#include "ctx_simplify_tactic.h"
|
#include "ctx_simplify_tactic.h"
|
||||||
#include "bv_decl_plugin.h"
|
#include "bv_decl_plugin.h"
|
||||||
|
#include "ast_pp.h"
|
||||||
|
|
||||||
class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier {
|
class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier {
|
||||||
ast_manager& m;
|
ast_manager& m;
|
||||||
|
@ -42,6 +43,13 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_bound(bool lo, bool s, expr* t, rational const& n) {
|
||||||
|
push();
|
||||||
|
bound(lo, s).insert(t, n);
|
||||||
|
m_trail.push_back(t);
|
||||||
|
m_trail_kind.push_back(lo?(s?0:1):(s?2:3));
|
||||||
|
}
|
||||||
|
|
||||||
bool is_bound(expr* t, expr*& b, bool& lo, bool& sign, rational& n) {
|
bool is_bound(expr* t, expr*& b, bool& lo, bool& sign, rational& n) {
|
||||||
expr* t1, *t2;
|
expr* t1, *t2;
|
||||||
unsigned sz;
|
unsigned sz;
|
||||||
|
@ -76,7 +84,24 @@ class bv_bounds_simplifier : public ctx_simplify_tactic::simplifier {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_eq_const(expr* t, expr*& b, rational& n) {
|
||||||
|
expr* t1, *t2;
|
||||||
|
unsigned sz;
|
||||||
|
if (m.is_eq(t, t1, t2)) {
|
||||||
|
if (m_bv.is_numeral(t1, n, sz)) {
|
||||||
|
b = t2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m_bv.is_numeral(t2, n, sz)) {
|
||||||
|
b = t1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bv_bounds_simplifier(ast_manager& m): m(m), m_bv(m), m_trail(m) {}
|
bv_bounds_simplifier(ast_manager& m): m(m), m_bv(m), m_trail(m) {}
|
||||||
|
|
||||||
virtual ~bv_bounds_simplifier() {}
|
virtual ~bv_bounds_simplifier() {}
|
||||||
|
@ -98,11 +123,13 @@ public:
|
||||||
// check overflow conditions:
|
// check overflow conditions:
|
||||||
rational n1 = m_bv.norm(n, m_bv.get_bv_size(t1), s);
|
rational n1 = m_bv.norm(n, m_bv.get_bv_size(t1), s);
|
||||||
if (n1 == n) {
|
if (n1 == n) {
|
||||||
bound(!lo, s).insert(t1, n);
|
TRACE("bv", tout << "(not " << mk_pp(t, m) << "): " << mk_pp(t1, m) << (lo?" <= ":" >= ") << n << "\n";);
|
||||||
|
add_bound(!lo, s, t1, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bound(lo, s).insert(t1, n);
|
TRACE("bv", tout << mk_pp(t, m) << ": " << mk_pp(t1, m) << (lo?" >= ":" <= ") << n << "\n";);
|
||||||
|
add_bound(lo, s, t1, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,47 +138,66 @@ public:
|
||||||
bool lo, s;
|
bool lo, s;
|
||||||
expr* t1;
|
expr* t1;
|
||||||
rational b1, b2;
|
rational b1, b2;
|
||||||
|
result = 0;
|
||||||
if (is_bound(t, t1, lo, s, b1)) {
|
if (is_bound(t, t1, lo, s, b1)) {
|
||||||
if (bound(!lo, s).find(t1, b2)) {
|
if (bound(!lo, s).find(t1, b2)) {
|
||||||
// t1 <= b1 < b2 <= t1
|
|
||||||
if (lo && b2 > b1) {
|
|
||||||
result = m.mk_false();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// t1 >= b1 > b2 >= t1
|
// t1 >= b1 > b2 >= t1
|
||||||
if (!lo && b2 < b1) {
|
if (lo && b1 > b2) {
|
||||||
result = m.mk_false();
|
result = m.mk_false();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if (b1 == b2) {
|
// t1 <= b1 < b2 <= t1
|
||||||
|
else if (!lo && b1 < b2) {
|
||||||
|
result = m.mk_false();
|
||||||
|
}
|
||||||
|
else if (b1 == b2) {
|
||||||
result = m.mk_eq(t1, m_bv.mk_numeral(b1, m.get_sort(t1)));
|
result = m.mk_eq(t1, m_bv.mk_numeral(b1, m.get_sort(t1)));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bound(lo, s).find(t1, b2)) {
|
if (result == 0 && bound(lo, s).find(t1, b2)) {
|
||||||
// b1 <= b2 <= t1
|
// b1 <= b2 <= t1
|
||||||
if (lo && b1 <= b2) {
|
if (lo && b1 <= b2) {
|
||||||
result = m.mk_true();
|
result = m.mk_true();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
// b1 >= b2 >= t1
|
// b1 >= b2 >= t1
|
||||||
if (!lo && b1 >= b2) {
|
else if (!lo && b1 >= b2) {
|
||||||
result = m.mk_true();
|
result = m.mk_true();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
if (is_eq_const(t, t1, b1)) {
|
||||||
|
if (bound(true, false).find(t1, b2) && b2 > b1) {
|
||||||
|
result = m.mk_false();
|
||||||
|
}
|
||||||
|
else if (bound(false, false).find(t1, b2) && b2 < b1) {
|
||||||
|
result = m.mk_false();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (bound(true, true).find(t1, b2)) {
|
||||||
|
b1 = m_bv.norm(b1, m_bv.get_bv_size(t1), true);
|
||||||
|
if (b2 > b1) result = m.mk_false();
|
||||||
|
}
|
||||||
|
if (result == 0 && bound(false, true).find(t1, b2)) {
|
||||||
|
b1 = m_bv.norm(b1, m_bv.get_bv_size(t1), true);
|
||||||
|
if (b2 < b1) result = m.mk_false();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CTRACE("bv", result != 0, tout << mk_pp(t, m) << " " << (lo?"lo":"hi") << " " << b1 << " " << b2 << ": " << result << "\n";);
|
||||||
|
return result != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void push() {
|
virtual void push() {
|
||||||
|
TRACE("bv", tout << "push\n";);
|
||||||
m_scopes.push_back(m_trail.size());
|
m_scopes.push_back(m_trail.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pop(unsigned num_scopes) {
|
virtual void pop(unsigned num_scopes) {
|
||||||
|
TRACE("bv", tout << "pop: " << num_scopes << "\n";);
|
||||||
if (num_scopes == 0) return;
|
if (num_scopes == 0) return;
|
||||||
unsigned old_sz = m_scopes[m_scopes.size() - num_scopes];
|
unsigned old_sz = m_scopes[m_scopes.size() - num_scopes];
|
||||||
for (unsigned i = old_sz; i < m_trail.size(); ++i) {
|
for (unsigned i = old_sz; i < m_trail.size(); ++i) {
|
||||||
|
TRACE("bv", tout << "remove: " << mk_pp(m_trail[i].get(), m) << "\n";);
|
||||||
|
SASSERT(m_bound[m_trail_kind[i]].contains(m_trail[i].get()));
|
||||||
m_bound[m_trail_kind[i]].erase(m_trail[i].get());
|
m_bound[m_trail_kind[i]].erase(m_trail[i].get());
|
||||||
}
|
}
|
||||||
m_trail_kind.resize(old_sz);
|
m_trail_kind.resize(old_sz);
|
||||||
|
|
Loading…
Reference in a new issue