diff --git a/src/ast/rewriter/seq_skolem.cpp b/src/ast/rewriter/seq_skolem.cpp index c2e94821685..ff67ff0bd12 100644 --- a/src/ast/rewriter/seq_skolem.cpp +++ b/src/ast/rewriter/seq_skolem.cpp @@ -38,7 +38,6 @@ skolem::skolem(ast_manager& m, th_rewriter& rw): m_max_unfolding = "seq.max_unfolding"; m_length_limit = "seq.length_limit"; m_is_empty = "re.is_empty"; - m_is_non_empty = "re.is_non_empty"; } expr_ref skolem::mk(symbol const& s, expr* e1, expr* e2, expr* e3, expr* e4, sort* range, bool rw) { diff --git a/src/ast/rewriter/seq_skolem.h b/src/ast/rewriter/seq_skolem.h index 913942b8a93..799b5ca074e 100644 --- a/src/ast/rewriter/seq_skolem.h +++ b/src/ast/rewriter/seq_skolem.h @@ -36,7 +36,7 @@ namespace seq { symbol m_indexof_left, m_indexof_right; // inverse of indexof: (indexof_left s t) + s + (indexof_right s t) = t, for s in t. symbol m_aut_step; // regex unfolding state symbol m_accept; // regex - symbol m_is_empty, m_is_non_empty; // regex emptiness check + symbol m_is_empty; // regex emptiness check symbol m_pre, m_post; // inverse of at: (pre s i) + (at s i) + (post s i) = s if 0 <= i < (len s) symbol m_postp; symbol m_eq; // equality atom @@ -73,7 +73,6 @@ namespace seq { } expr_ref mk_accept(expr_ref_vector const& args) { return expr_ref(seq.mk_skolem(m_accept, args.size(), args.data(), m.mk_bool_sort()), m); } expr_ref mk_accept(expr* s, expr* i, expr* r) { return mk(m_accept, s, i, r, nullptr, m.mk_bool_sort()); } - expr_ref mk_is_non_empty(expr* r, expr* u, expr* n) { return mk(m_is_non_empty, r, u, n, m.mk_bool_sort(), false); } expr_ref mk_is_empty(expr* r, expr* u, expr* n) { return mk(m_is_empty, r, u, n, m.mk_bool_sort(), false); } expr_ref mk_indexof_left(expr* t, expr* s, expr* offset = nullptr) { return mk(m_indexof_left, t, s, offset); } @@ -153,13 +152,9 @@ namespace seq { bool is_length_limit(expr* e) const { return is_skolem(m_length_limit, e); } bool is_length_limit(expr* p, unsigned& lim, expr*& s) const; bool is_is_empty(expr* e) const { return is_skolem(m_is_empty, e); } - bool is_is_non_empty(expr* e) const { return is_skolem(m_is_non_empty, e); } bool is_is_empty(expr* e, expr*& r, expr*& u, expr*& n) const { return is_skolem(m_is_empty, e) && (r = to_app(e)->get_arg(0), u = to_app(e)->get_arg(1), n = to_app(e)->get_arg(2), true); } - bool is_is_non_empty(expr* e, expr*& r, expr*& u, expr*& n) const { - return is_skolem(m_is_non_empty, e) && (r = to_app(e)->get_arg(0), u = to_app(e)->get_arg(1), n = to_app(e)->get_arg(2), true); - } void decompose(expr* e, expr_ref& head, expr_ref& tail); diff --git a/src/smt/seq_regex.cpp b/src/smt/seq_regex.cpp index a6ce1884dfc..79bddf83ea1 100644 --- a/src/smt/seq_regex.cpp +++ b/src/smt/seq_regex.cpp @@ -246,8 +246,7 @@ namespace smt { } if (info.interpreted) { - update_state_graph(r); - + update_state_graph(r); if (m_state_graph.is_dead(get_state_id(r))) { STRACE("seq_regex_brief", tout << "(dead) ";); th.add_axiom(~lit); @@ -519,15 +518,12 @@ namespace smt { void seq_regex::propagate_ne(expr* r1, expr* r2) { TRACE("seq_regex", tout << "propagate NEQ: " << mk_pp(r1, m) << ", " << mk_pp(r2, m) << std::endl;); STRACE("seq_regex_brief", tout << "PNEQ ";); - // TBD: rewrite to use state_graph - // why is is_non_empty even needed, why not just not(in_empty) sort* seq_sort = nullptr; VERIFY(u().is_re(r1, seq_sort)); expr_ref r = symmetric_diff(r1, r2); - expr_ref emp(re().mk_empty(r->get_sort()), m); - expr_ref n(m.mk_fresh_const("re.char", seq_sort), m); - expr_ref is_non_empty = sk().mk_is_non_empty(r, r, n); - th.add_axiom(th.mk_eq(r1, r2, false), th.mk_literal(is_non_empty)); + expr_ref s(m.mk_fresh_const("re.member", seq_sort), m); + expr_ref is_member(re().mk_in_re(s, r), m); + th.add_axiom(th.mk_eq(r1, r2, false), th.mk_literal(is_member)); } bool seq_regex::is_member(expr* r, expr* u) { @@ -537,62 +533,7 @@ namespace smt { return true; } return r == u; - } - - /** - * is_non_empty(r, u) => nullable or \/_i (c_i and is_non_empty(r_i, u union r)) - * - * for each (c_i, r_i) in cofactors (min-terms) - * - * is_non_empty(r_i, u union r) := false if r_i in u - * - */ - void seq_regex::propagate_is_non_empty(literal lit) { - expr* e = ctx.bool_var2expr(lit.var()), *r = nullptr, *u = nullptr, *n = nullptr; - VERIFY(sk().is_is_non_empty(e, r, u, n)); - - if (block_if_empty(r, lit)) - return; - - - TRACE("seq_regex", tout << "propagate nonempty: " << mk_pp(e, m) << std::endl;); - STRACE("seq_regex_brief", tout - << std::endl << "PNE(" << expr_id_str(e) << "," << state_str(r) - << "," << expr_id_str(u) << "," << expr_id_str(n) << ") ";); - - expr_ref is_nullable = is_nullable_wrapper(r); - if (m.is_true(is_nullable)) - return; - - - literal null_lit = th.mk_literal(is_nullable); - expr_ref hd = mk_first(r, n); - expr_ref d(m); - d = mk_derivative_wrapper(hd, r); - - literal_vector lits; - lits.push_back(~lit); - if (null_lit != false_literal) - lits.push_back(null_lit); - - expr_ref_pair_vector cofactors(m); - get_cofactors(d, cofactors); - for (auto const& p : cofactors) { - if (is_member(p.second, u)) - continue; - expr_ref cond(p.first, m); - seq_rw().elim_condition(hd, cond); - rewrite(cond); - if (m.is_false(cond)) - continue; - expr_ref next_non_empty = sk().mk_is_non_empty(p.second, re().mk_union(u, p.second), n); - if (!m.is_true(cond)) - next_non_empty = m.mk_and(cond, next_non_empty); - lits.push_back(th.mk_literal(next_non_empty)); - } - - th.add_axiom(lits); - } + } /* Given a string s, index i, and a derivative r, return an @@ -915,6 +856,7 @@ namespace smt { } m_state_graph.mark_done(r_id); } + STRACE("seq_regex", m_state_graph.display(tout);); STRACE("seq_regex_brief", tout << std::endl;); STRACE("seq_regex_brief", m_state_graph.display(tout);); diff --git a/src/smt/seq_regex.h b/src/smt/seq_regex.h index 01dd6e4a2b3..8b6a3978267 100644 --- a/src/smt/seq_regex.h +++ b/src/smt/seq_regex.h @@ -203,9 +203,7 @@ namespace smt { void propagate_eq(expr* r1, expr* r2); - void propagate_ne(expr* r1, expr* r2); - - void propagate_is_non_empty(literal lit); + void propagate_ne(expr* r1, expr* r2); void propagate_is_empty(literal lit); diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index fe0d116ef93..842798bab74 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -3014,10 +3014,6 @@ void theory_seq::assign_eh(bool_var v, bool is_true) { if (is_true) m_regex.propagate_is_empty(lit); } - else if (m_sk.is_is_non_empty(e)) { - if (is_true) - m_regex.propagate_is_non_empty(lit); - } else if (m_sk.is_eq(e, e1, e2)) { if (is_true) { propagate_eq(lit, e1, e2, true);