mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
fixes for #2513
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
de69b01e92
commit
a337a51374
28 changed files with 486 additions and 144 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue