3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 04:03:39 +00:00

updates to some_string_in_re per code review comments

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2025-01-11 17:47:27 -08:00
parent c572fc2e4f
commit c6f58c8bf7
4 changed files with 19 additions and 20 deletions

View file

@ -882,14 +882,13 @@ public:
return false; return false;
case OP_SEQ_IN_RE: case OP_SEQ_IN_RE:
if (uncnstr(args[0]) && seq.re.is_ground(args[1]) && seq.is_string(args[0]->get_sort())) { if (uncnstr(args[0]) && seq.re.is_ground(args[1]) && seq.is_string(args[0]->get_sort())) {
#if 1
zstring s1; zstring s1;
expr* re = args[1]; expr* re = args[1];
if (!rw.some_string_in_re(re, s1)) if (l_true != rw.some_string_in_re(re, s1))
return false; return false;
zstring s2; zstring s2;
expr_ref not_re(seq.re.mk_complement(re), m); expr_ref not_re(seq.re.mk_complement(re), m);
if (!rw.some_string_in_re(not_re, s2)) if (l_true != rw.some_string_in_re(not_re, s2))
return false; return false;
mk_fresh_uncnstr_var_for(f, r); mk_fresh_uncnstr_var_for(f, r);
@ -898,7 +897,6 @@ public:
if (m_mc) if (m_mc)
add_def(args[0], m.mk_ite(r, witness1, witness2)); add_def(args[0], m.mk_ite(r, witness1, witness2));
return true; return true;
#endif
} }
return false; return false;
default: default:

View file

@ -9,7 +9,7 @@ Abstract:
Basic rewriting rules for sequences constraints. Basic rewriting rules for sequences constraints.
Author: Authors:
Nikolaj Bjorner (nbjorner) 2015-12-5 Nikolaj Bjorner (nbjorner) 2015-12-5
Murphy Berzish 2017-02-21 Murphy Berzish 2017-02-21
@ -6146,17 +6146,17 @@ void seq_rewriter::op_cache::cleanup() {
} }
} }
bool seq_rewriter::some_string_in_re(expr* r, zstring& s) { lbool seq_rewriter::some_string_in_re(expr* r, zstring& s) {
sort* rs; sort* rs;
(void)rs; (void)rs;
// SASSERT(re().is_re(r, rs) && m_util.is_string(rs)); // SASSERT(re().is_re(r, rs) && m_util.is_string(rs));
expr_mark visited; expr_mark visited;
unsigned_vector str; unsigned_vector str;
if (!some_string_in_re(visited, r, str)) auto result = some_string_in_re(visited, r, str);
return false; if (result == l_true)
s = zstring(str.size(), str.data()); s = zstring(str.size(), str.data());
return true; return result;
} }
struct re_eval_pos { struct re_eval_pos {
@ -6166,7 +6166,7 @@ struct re_eval_pos {
bool needs_derivation; bool needs_derivation;
}; };
bool seq_rewriter::some_string_in_re(expr_mark& visited, expr* r, unsigned_vector& str) { lbool seq_rewriter::some_string_in_re(expr_mark& visited, expr* r, unsigned_vector& str) {
SASSERT(str.empty()); SASSERT(str.empty());
vector<re_eval_pos> todo; vector<re_eval_pos> todo;
todo.push_back({ expr_ref(r, m()), 0, {}, true }); todo.push_back({ expr_ref(r, m()), 0, {}, true });
@ -6184,7 +6184,7 @@ bool seq_rewriter::some_string_in_re(expr_mark& visited, expr* r, unsigned_vecto
continue; continue;
auto info = re().get_info(r); auto info = re().get_info(r);
if (info.nullable == l_true) if (info.nullable == l_true)
return true; return l_true;
visited.mark(r); visited.mark(r);
if (re().is_union(r)) { if (re().is_union(r)) {
for (expr* arg : *to_app(r)) { for (expr* arg : *to_app(r)) {
@ -6210,12 +6210,13 @@ bool seq_rewriter::some_string_in_re(expr_mark& visited, expr* r, unsigned_vecto
} }
if (m().is_ite(r, c, th, el)) { if (m().is_ite(r, c, th, el)) {
unsigned low = 0, high = zstring::unicode_max_char(); unsigned low = 0, high = zstring::unicode_max_char();
bool hasBounds = get_bounds(c, low, high); bool has_bounds = get_bounds(c, low, high);
if (!re().is_empty(el)) { if (!re().is_empty(el)) {
exclude.push_back({ low, high }); if (has_bounds)
exclude.push_back({ low, high });
todo.push_back({ expr_ref(el, m()), str.size(), std::move(exclude), false }); todo.push_back({ expr_ref(el, m()), str.size(), std::move(exclude), false });
} }
if (hasBounds) { if (has_bounds) {
// I want this case to be processed first => push it last // I want this case to be processed first => push it last
// reason: current string is only pruned // reason: current string is only pruned
SASSERT(low <= high); SASSERT(low <= high);
@ -6256,9 +6257,9 @@ bool seq_rewriter::some_string_in_re(expr_mark& visited, expr* r, unsigned_vecto
continue; continue;
} }
UNREACHABLE(); return l_undef;
} }
return false; return l_false;
} }
bool seq_rewriter::get_bounds(expr* e, unsigned& low, unsigned& high) { bool seq_rewriter::get_bounds(expr* e, unsigned& low, unsigned& high) {

View file

@ -354,7 +354,7 @@ class seq_rewriter {
void intersect(unsigned lo, unsigned hi, svector<std::pair<unsigned, unsigned>>& ranges); void intersect(unsigned lo, unsigned hi, svector<std::pair<unsigned, unsigned>>& ranges);
bool get_bounds(expr* e, unsigned& low, unsigned& high); bool get_bounds(expr* e, unsigned& low, unsigned& high);
bool some_string_in_re(expr_mark& visited, expr* r, unsigned_vector& str); lbool some_string_in_re(expr_mark& visited, expr* r, unsigned_vector& str);
public: public:
seq_rewriter(ast_manager & m, params_ref const & p = params_ref()): seq_rewriter(ast_manager & m, params_ref const & p = params_ref()):
@ -441,6 +441,6 @@ public:
* Return true if a valid string was extracted. * Return true if a valid string was extracted.
* Return false when giving up or the regular expression is empty. * Return false when giving up or the regular expression is empty.
*/ */
bool some_string_in_re(expr* r, zstring& s); lbool some_string_in_re(expr* r, zstring& s);
}; };

View file

@ -1847,7 +1847,7 @@ namespace sls {
{ {
zstring s1; zstring s1;
if (ctx.is_true(e) && rw.some_string_in_re(y, s1)) { if (ctx.is_true(e) && l_true == rw.some_string_in_re(y, s1)) {
m_str_updates.push_back({ x, s1, 1 }); m_str_updates.push_back({ x, s1, 1 });
return apply_update(); return apply_update();
} }