3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 01:25:31 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-08-23 23:29:10 +03:00
parent de69b01e92
commit a337a51374
28 changed files with 486 additions and 144 deletions

View file

@ -21,6 +21,7 @@ Notes:
#include "ast/rewriter/seq_rewriter.h"
#include "ast/arith_decl_plugin.h"
#include "ast/ast_pp.h"
#include "ast/ast_ll_pp.h"
#include "ast/ast_util.h"
#include "util/uint_set.h"
#include "math/automata/automaton.h"
@ -546,7 +547,7 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
case _OP_STRING_STRIDOF:
UNREACHABLE();
}
CTRACE("seq", st != BR_FAILED, tout << result << "\n";);
CTRACE("seq_verbose", st != BR_FAILED, tout << result << "\n";);
return st;
}
@ -643,14 +644,38 @@ br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) {
result = m_autil.mk_add(es.size(), es.c_ptr());
return BR_REWRITE2;
}
expr* c = nullptr, *t = nullptr, *e = nullptr;
if (m().is_ite(a, c, t, e) && (t->get_ref_count() == 1 || e->get_ref_count() == 1)) {
result = m().mk_ite(c, m_util.str.mk_length(t), m_util.str.mk_length(e));
return BR_REWRITE3;
}
#if 0
expr* s = nullptr, *offs = nullptr, *l = nullptr;
// len(extract(s, offs, len(s) - offs)) = max(0, len(s) - offs)
//
if (m_util.str.is_extract(a, s, offs, l) && is_suffix(s, offs, l)) {
expr_ref zero(m_autil.mk_int(0), m());
result = m_autil.mk_sub(m_util.str.mk_length(s), offs);
result = m().mk_ite(m_autil.mk_ge(result, zero), result, zero);
return BR_REWRITE_FULL;
}
#endif
return BR_FAILED;
}
bool seq_rewriter::is_suffix(expr* s, expr* offset, expr* len) {
expr_ref_vector lens(m());
rational a, b;
return
get_lengths(len, lens, a) &&
(a.neg(), m_autil.is_numeral(offset, b) && b.is_pos() && a == b);
}
br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& result) {
zstring s;
rational pos, len;
TRACE("seq", tout << mk_pp(a, m()) << " " << mk_pp(b, m()) << " " << mk_pp(c, m()) << "\n";);
TRACE("seq_verbose", tout << mk_pp(a, m()) << " " << mk_pp(b, m()) << " " << mk_pp(c, m()) << "\n";);
bool constantBase = m_util.str.is_string(a, s);
bool constantPos = m_autil.is_numeral(b, pos);
bool constantLen = m_autil.is_numeral(c, len);
@ -702,7 +727,8 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
m_lhs.reset();
expr_ref_vector lens(m());
m_util.str.get_concat(a, m_lhs);
if (!get_lengths(b, lens, pos)) {
TRACE("seq", tout << m_lhs << " " << pos << " " << lens << "\n";);
if (!get_lengths(b, lens, pos) || pos.is_neg()) {
return BR_FAILED;
}
unsigned i = 0;
@ -742,9 +768,20 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
// (extract s 0 (len s)) = s
expr* a2 = nullptr;
if (_pos == 0 && m_util.str.is_length(c, a2) && a == a2) {
result = a;
return BR_DONE;
if (_pos == 0 && m_util.str.is_length(c, a2)) {
m_lhs.reset();
m_util.str.get_concat(a, m_lhs);
if (!m_lhs.empty() && m_lhs.get(0) == a2) {
result = a2;
return BR_DONE;
}
}
expr* a1 = nullptr, *b1 = nullptr, *c1 = nullptr;
if (m_util.str.is_extract(a, a1, b1, c1) &&
is_suffix(a1, b1, c1) && is_suffix(a, b, c)) {
result = m_util.str.mk_substr(a1, m_autil.mk_add(b1, b), m_autil.mk_sub(c1, b));
return BR_REWRITE3;
}
unsigned offset = 0;
@ -799,7 +836,7 @@ bool seq_rewriter::get_lengths(expr* e, expr_ref_vector& lens, rational& pos) {
else {
return false;
}
return !pos.is_neg();
return true;
}
bool seq_rewriter::cannot_contain_suffix(expr* a, expr* b) {
@ -992,9 +1029,28 @@ br_status seq_rewriter::mk_seq_at(expr* a, expr* b, expr_ref& result) {
}
br_status seq_rewriter::mk_seq_nth(expr* a, expr* b, expr_ref& result) {
rational pos1, pos2;
expr* s = nullptr, *p = nullptr, *len = nullptr;
if (m_util.str.is_unit(a, s) && m_autil.is_numeral(b, pos1) && pos1.is_zero()) {
result = s;
return BR_DONE;
}
if (m_util.str.is_extract(a, s, p, len) && m_autil.is_numeral(p, pos1)) {
expr_ref_vector lens(m());
rational pos2;
if (get_lengths(len, lens, pos2) && (pos1 == -pos2) && (lens.size() == 1) && (lens.get(0) == s)) {
expr_ref idx(m_autil.mk_int(pos1), m());
idx = m_autil.mk_add(b, idx);
expr* es[2] = { s, idx };
result = m().mk_app(m_util.get_family_id(), OP_SEQ_NTH, 2, es);
return BR_REWRITE_FULL;
}
}
expr* es[2] = { a, b};
expr* la = m_util.str.mk_length(a);
result = m().mk_ite(m().mk_and(m_autil.mk_le(m_autil.mk_int(0), b), m_autil.mk_lt(b, la)),
result = m().mk_ite(m().mk_and(m_autil.mk_ge(b, m_autil.mk_int(0)), m().mk_not(m_autil.mk_ge(b, la))),
m().mk_app(m_util.get_family_id(), OP_SEQ_NTH_I, 2, es),
m().mk_app(m_util.get_family_id(), OP_SEQ_NTH_U, 2, es));
return BR_REWRITE_FULL;
@ -1078,10 +1134,26 @@ br_status seq_rewriter::mk_seq_replace(expr* a, expr* b, expr* c, expr_ref& resu
result = a;
return BR_DONE;
}
if (a == b) {
result = c;
return BR_DONE;
}
if (m_util.str.is_empty(b)) {
result = m_util.str.mk_concat(c, a);
return BR_REWRITE1;
}
if (m_util.str.is_string(b, s2)) {
m_lhs.reset();
m_util.str.get_concat(a, m_lhs);
if (!m_lhs.empty() && m_util.str.is_string(m_lhs.get(0), s1) &&
s1.contains(s2)) {
m_lhs[0] = m_util.str.mk_string(s1.replace(s2, s3));
result = m_util.str.mk_concat(m_lhs.size(), m_lhs.c_ptr());
return BR_REWRITE1;
}
}
return BR_FAILED;
}
@ -1835,7 +1907,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
zstring s;
bool lchange = false;
SASSERT(lhs.empty());
TRACE("seq", tout << ls << "\n"; tout << rs << "\n";);
TRACE("seq_verbose", tout << ls << "\n"; tout << rs << "\n";);
// solve from back
while (true) {
while (!rs.empty() && m_util.str.is_empty(rs.back())) {
@ -1943,7 +2015,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
else {
break;
}
TRACE("seq", tout << ls << " == " << rs << "\n";);
TRACE("seq_verbose", tout << ls << " == " << rs << "\n";);
change = true;
lchange = true;
@ -2106,7 +2178,7 @@ bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_ve
return true;
}
else {
TRACE("seq", tout << mk_pp(l, m()) << " != " << mk_pp(r, m()) << "\n";);
TRACE("seq", tout << mk_bounded_pp(l, m()) << " != " << mk_bounded_pp(r, m()) << "\n";);
return false;
}
}

View file

@ -139,6 +139,8 @@ class seq_rewriter {
bool cannot_contain_prefix(expr* a, expr* b);
bool cannot_contain_suffix(expr* a, expr* b);
bool is_suffix(expr* s, expr* offset, expr* len);
bool set_empty(unsigned sz, expr* const* es, bool all, expr_ref_vector& lhs, expr_ref_vector& rhs);
bool is_subsequence(unsigned n, expr* const* l, unsigned m, expr* const* r,
expr_ref_vector& lhs, expr_ref_vector& rhs, bool& is_sat);

View file

@ -346,9 +346,7 @@ void static_features::update_core(expr * e) {
m_num_uninterpreted_functions++;
}
if (!_is_eq && !_is_gate) {
unsigned num_args = to_app(e)->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
expr * arg = to_app(e)->get_arg(i);
for (expr * arg : *to_app(e)) {
sort * arg_s = m_manager.get_sort(arg);
if (!m_manager.is_uninterp(arg_s)) {
family_id fid_arg = arg_s->get_family_id();