mirror of
https://github.com/Z3Prover/z3
synced 2025-04-15 21:38:44 +00:00
more rewrite rules
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
b2eb248bad
commit
27584d68db
|
@ -909,6 +909,18 @@ bool seq_rewriter::is_suffix(expr* s, expr* offset, expr* len) {
|
||||||
lens.contains(s));
|
lens.contains(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool seq_rewriter::is_prefix(expr* s, expr* offset, expr* len) {
|
||||||
|
expr_ref_vector lens(m());
|
||||||
|
rational a, b;
|
||||||
|
return
|
||||||
|
get_lengths(len, lens, a) &&
|
||||||
|
a < 0 &&
|
||||||
|
m_autil.is_numeral(offset, b) &&
|
||||||
|
b == 0 &&
|
||||||
|
lens.size() == 1 &&
|
||||||
|
lens.contains(s);
|
||||||
|
}
|
||||||
|
|
||||||
bool seq_rewriter::sign_is_determined(expr* e, sign& s) {
|
bool seq_rewriter::sign_is_determined(expr* e, sign& s) {
|
||||||
s = sign_zero;
|
s = sign_zero;
|
||||||
if (m_autil.is_add(e)) {
|
if (m_autil.is_add(e)) {
|
||||||
|
@ -965,6 +977,27 @@ expr_ref seq_rewriter::mk_len(rational const& p, expr_ref_vector const& xs) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool seq_rewriter::extract_pop_suffix(expr_ref_vector const& as, expr* b, expr* c, expr_ref& result) {
|
||||||
|
unsigned len_a1 = 0, len_a2 = 0;
|
||||||
|
min_length(as, len_a1);
|
||||||
|
rational pos, len;
|
||||||
|
if (!as.empty() && m_autil.is_numeral(b, pos) &&
|
||||||
|
m_autil.is_numeral(c, len) && len_a1 >= pos + len && pos >= 0 && len >= 0) {
|
||||||
|
unsigned i = 0;
|
||||||
|
len_a1 = 0;
|
||||||
|
for ( ; i < as.size() && len_a1 < pos + len; ++i) {
|
||||||
|
min_length(as.get(i), len_a2);
|
||||||
|
len_a1 += len_a2;
|
||||||
|
}
|
||||||
|
if (i < as.size()) {
|
||||||
|
expr* a = str().mk_concat(i, as.c_ptr(), as[0]->get_sort());
|
||||||
|
result = str().mk_substr(a, b, c);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool seq_rewriter::extract_push_offset(expr_ref_vector const& as, expr* b, expr* c, expr_ref& result) {
|
bool seq_rewriter::extract_push_offset(expr_ref_vector const& as, expr* b, expr* c, expr_ref& result) {
|
||||||
expr_ref_vector lens(m());
|
expr_ref_vector lens(m());
|
||||||
|
@ -1049,7 +1082,7 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// case 1: pos<0 or len<=0
|
// case 1: pos < 0 or len <= 0
|
||||||
// rewrite to ""
|
// rewrite to ""
|
||||||
if ( (constantPos && pos.is_neg()) || (constantLen && !len.is_pos()) ) {
|
if ( (constantPos && pos.is_neg()) || (constantLen && !len.is_pos()) ) {
|
||||||
result = str().mk_empty(a_sort);
|
result = str().mk_empty(a_sort);
|
||||||
|
@ -1057,42 +1090,41 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
|
||||||
}
|
}
|
||||||
// case 1.1: pos >= length(base)
|
// case 1.1: pos >= length(base)
|
||||||
// rewrite to ""
|
// rewrite to ""
|
||||||
if (constantPos && constantBase && pos >= rational(s.length())) {
|
if (constantPos && constantBase && pos >= s.length()) {
|
||||||
result = str().mk_empty(a_sort);
|
result = str().mk_empty(a_sort);
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
rational len_a;
|
rational len_a;
|
||||||
if (constantPos && max_length(a, len_a) && rational(len_a) <= pos) {
|
if (constantPos && max_length(a, len_a) && len_a <= pos) {
|
||||||
result = str().mk_empty(a_sort);
|
result = str().mk_empty(a_sort);
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
constantPos &= pos.is_unsigned();
|
constantPos &= pos.is_unsigned();
|
||||||
constantLen &= len.is_unsigned();
|
constantLen &= len.is_unsigned();
|
||||||
|
|
||||||
if (constantPos && constantLen && constantBase) {
|
if (constantPos && constantLen && constantBase) {
|
||||||
unsigned _pos = pos.get_unsigned();
|
unsigned _pos = pos.get_unsigned();
|
||||||
unsigned _len = len.get_unsigned();
|
unsigned _len = len.get_unsigned();
|
||||||
if (_pos + _len >= s.length()) {
|
if (pos + len >= s.length())
|
||||||
// case 2: pos+len goes past the end of the string
|
result = str().mk_string(s.extract(_pos, s.length()));
|
||||||
unsigned _len = s.length() - _pos + 1;
|
else
|
||||||
result = str().mk_string(s.extract(_pos, _len));
|
result = str().mk_string(s.extract(_pos, _len));
|
||||||
} else {
|
|
||||||
// case 3: pos+len still within string
|
|
||||||
result = str().mk_string(s.extract(_pos, _len));
|
|
||||||
}
|
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
expr_ref_vector as(m()), bs(m());
|
expr_ref_vector as(m());
|
||||||
str().get_concat_units(a, as);
|
str().get_concat_units(a, as);
|
||||||
if (as.empty()) {
|
if (as.empty()) {
|
||||||
result = str().mk_empty(a->get_sort());
|
result = str().mk_empty(a->get_sort());
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (extract_pop_suffix(as, b, c, result))
|
||||||
|
return BR_REWRITE1;
|
||||||
|
|
||||||
// extract(a + b + c, len(a + b), s) -> extract(c, 0, s)
|
// extract(a + b + c, len(a + b), s) -> extract(c, 0, s)
|
||||||
// extract(a + b + c, len(a) + len(b), s) -> extract(c, 0, s)
|
// extract(a + b + c, len(a) + len(b), s) -> extract(c, 0, s)
|
||||||
if (extract_push_offset(as, b, c, result))
|
if (extract_push_offset(as, b, c, result))
|
||||||
|
@ -1109,6 +1141,12 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
|
||||||
return BR_REWRITE3;
|
return BR_REWRITE3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (str().is_extract(a, a1, b1, c1) &&
|
||||||
|
is_prefix(a1, b1, c1) && is_prefix(a, b, c)) {
|
||||||
|
result = str().mk_substr(a1, b, m_autil.mk_sub(c1, m_autil.mk_sub(str().mk_length(a), c)));
|
||||||
|
return BR_REWRITE3;
|
||||||
|
}
|
||||||
|
|
||||||
if (!constantPos)
|
if (!constantPos)
|
||||||
return BR_FAILED;
|
return BR_FAILED;
|
||||||
|
|
||||||
|
@ -4522,23 +4560,42 @@ bool seq_rewriter::set_empty(unsigned sz, expr* const* es, bool all, expr_ref_pa
|
||||||
maximal length (the sequence is bounded).
|
maximal length (the sequence is bounded).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool seq_rewriter::min_length(expr_ref_vector const& es, unsigned& len) {
|
bool seq_rewriter::min_length(expr* e, unsigned& len) {
|
||||||
zstring s;
|
zstring s;
|
||||||
|
len = 0;
|
||||||
|
if (str().is_unit(e)) {
|
||||||
|
len = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (str().is_empty(e)) {
|
||||||
|
len = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (str().is_string(e, s)) {
|
||||||
|
len = s.length();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (str().is_concat(e)) {
|
||||||
|
unsigned min_l = 0;
|
||||||
|
bool bounded = true;
|
||||||
|
for (expr* arg : *to_app(e)) {
|
||||||
|
if (!min_length(arg, min_l))
|
||||||
|
bounded = false;
|
||||||
|
len += min_l;
|
||||||
|
}
|
||||||
|
return bounded;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool seq_rewriter::min_length(expr_ref_vector const& es, unsigned& len) {
|
||||||
|
unsigned min_l = 0;
|
||||||
bool bounded = true;
|
bool bounded = true;
|
||||||
len = 0;
|
len = 0;
|
||||||
for (expr* e : es) {
|
for (expr* arg : es) {
|
||||||
if (str().is_unit(e)) {
|
if (!min_length(arg, min_l))
|
||||||
++len;
|
|
||||||
}
|
|
||||||
else if (str().is_empty(e)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (str().is_string(e, s)) {
|
|
||||||
len += s.length();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bounded = false;
|
bounded = false;
|
||||||
}
|
len += min_l;
|
||||||
}
|
}
|
||||||
return bounded;
|
return bounded;
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,6 +210,7 @@ class seq_rewriter {
|
||||||
br_status mk_seq_concat(expr* a, expr* b, expr_ref& result);
|
br_status mk_seq_concat(expr* a, expr* b, expr_ref& result);
|
||||||
br_status mk_seq_length(expr* a, expr_ref& result);
|
br_status mk_seq_length(expr* a, expr_ref& result);
|
||||||
expr_ref mk_len(rational const& offset, expr_ref_vector const& xs);
|
expr_ref mk_len(rational const& offset, expr_ref_vector const& xs);
|
||||||
|
bool extract_pop_suffix(expr_ref_vector const& as, expr* b, expr* c, expr_ref& result);
|
||||||
bool extract_push_offset(expr_ref_vector const& as, expr* b, expr* c, expr_ref& result);
|
bool extract_push_offset(expr_ref_vector const& as, expr* b, expr* c, expr_ref& result);
|
||||||
bool extract_push_length(expr_ref_vector& as, expr* b, expr* c, expr_ref& result);
|
bool extract_push_length(expr_ref_vector& as, expr* b, expr* c, expr_ref& result);
|
||||||
br_status mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& result);
|
br_status mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& result);
|
||||||
|
@ -276,6 +277,7 @@ class seq_rewriter {
|
||||||
expr_ref minus_one() { return expr_ref(m_autil.mk_int(-1), m()); }
|
expr_ref minus_one() { return expr_ref(m_autil.mk_int(-1), m()); }
|
||||||
|
|
||||||
bool is_suffix(expr* s, expr* offset, expr* len);
|
bool is_suffix(expr* s, expr* offset, expr* len);
|
||||||
|
bool is_prefix(expr* s, expr* offset, expr* len);
|
||||||
bool sign_is_determined(expr* len, sign& s);
|
bool sign_is_determined(expr* len, sign& s);
|
||||||
|
|
||||||
bool set_empty(unsigned sz, expr* const* es, bool all, expr_ref_pair_vector& eqs);
|
bool set_empty(unsigned sz, expr* const* es, bool all, expr_ref_pair_vector& eqs);
|
||||||
|
@ -285,6 +287,7 @@ class seq_rewriter {
|
||||||
bool reduce_itos(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs);
|
bool reduce_itos(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs);
|
||||||
bool reduce_eq_empty(expr* l, expr* r, expr_ref& result);
|
bool reduce_eq_empty(expr* l, expr* r, expr_ref& result);
|
||||||
bool min_length(expr_ref_vector const& es, unsigned& len);
|
bool min_length(expr_ref_vector const& es, unsigned& len);
|
||||||
|
bool min_length(expr* e, unsigned& len);
|
||||||
bool max_length(expr* e, rational& len);
|
bool max_length(expr* e, rational& len);
|
||||||
expr* concat_non_empty(expr_ref_vector& es);
|
expr* concat_non_empty(expr_ref_vector& es);
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,17 @@ literal seq_axioms::mk_literal(expr* _e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void seq_axioms::add_clause(expr_ref_vector const& clause) {
|
void seq_axioms::add_clause(expr_ref_vector const& clause) {
|
||||||
|
expr* a = nullptr, *b = nullptr;
|
||||||
|
if (clause.size() == 1 && m.is_eq(clause[0], a, b)) {
|
||||||
|
enode* n1 = th.ensure_enode(a);
|
||||||
|
enode* n2 = th.ensure_enode(b);
|
||||||
|
justification* js =
|
||||||
|
ctx().mk_justification(
|
||||||
|
ext_theory_eq_propagation_justification(
|
||||||
|
th.get_id(), ctx().get_region(), 0, nullptr, 0, nullptr, n1, n2));
|
||||||
|
ctx().assign_eq(n1, n2, eq_justification(js));
|
||||||
|
return;
|
||||||
|
}
|
||||||
literal lits[5] = { null_literal, null_literal, null_literal, null_literal, null_literal };
|
literal lits[5] = { null_literal, null_literal, null_literal, null_literal, null_literal };
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
for (expr* e : clause) {
|
for (expr* e : clause) {
|
||||||
|
|
Loading…
Reference in a new issue