From c0fbb3137904a5557e77d9aacf8f6ec07929af85 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 24 Jun 2020 12:07:29 -0700 Subject: [PATCH] use nonse based seed for transition characters Signed-off-by: Nikolaj Bjorner --- src/smt/seq_regex.cpp | 31 +++++++++++++++++++------------ src/smt/seq_regex.h | 2 +- src/smt/seq_skolem.h | 14 ++++++++------ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/smt/seq_regex.cpp b/src/smt/seq_regex.cpp index 9688e4648..5df4cdc92 100644 --- a/src/smt/seq_regex.cpp +++ b/src/smt/seq_regex.cpp @@ -413,16 +413,22 @@ namespace smt { } void seq_regex::propagate_eq(expr* r1, expr* r2) { + sort* seq_sort = nullptr; + VERIFY(u().is_re(r1, seq_sort)); expr_ref r = symmetric_diff(r1, r2); expr_ref emp(re().mk_empty(m.get_sort(r)), m); - expr_ref is_empty = sk().mk_is_empty(r, emp); + expr_ref n(m.mk_fresh_const("re.char", seq_sort), m); + expr_ref is_empty = sk().mk_is_empty(r, emp, n); th.add_axiom(~th.mk_eq(r1, r2, false), th.mk_literal(is_empty)); } void seq_regex::propagate_ne(expr* r1, expr* r2) { + sort* seq_sort = nullptr; + VERIFY(u().is_re(r1, seq_sort)); expr_ref r = symmetric_diff(r1, r2); expr_ref emp(re().mk_empty(m.get_sort(r)), m); - expr_ref is_non_empty = sk().mk_is_non_empty(r, emp); + expr_ref n(m.mk_fresh_const("re.char", seq_sort), m); + expr_ref is_non_empty = sk().mk_is_non_empty(r, emp, n); th.add_axiom(th.mk_eq(r1, r2, false), th.mk_literal(is_non_empty)); } @@ -444,14 +450,14 @@ namespace smt { * */ void seq_regex::propagate_is_non_empty(literal lit) { - expr* e = ctx.bool_var2expr(lit.var()), *r = nullptr, *u = nullptr; - VERIFY(sk().is_is_non_empty(e, r, u)); + expr* e = ctx.bool_var2expr(lit.var()), *r = nullptr, *u = nullptr, *n = nullptr; + VERIFY(sk().is_is_non_empty(e, r, u, n)); expr_ref is_nullable = seq_rw().is_nullable(r); rewrite(is_nullable); if (m.is_true(is_nullable)) return; literal null_lit = th.mk_literal(is_nullable); - expr_ref hd = mk_first(r); + expr_ref hd = mk_first(r, n); expr_ref d(m); d = derivative_wrapper(hd, r); literal_vector lits; @@ -468,7 +474,7 @@ namespace smt { rewrite(cond); if (m.is_false(cond)) continue; - expr_ref next_non_empty = sk().mk_is_non_empty(p.second, re().mk_union(u, r)); + 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)); @@ -499,8 +505,8 @@ namespace smt { is_empty(r, u) is true if r is a member of u */ void seq_regex::propagate_is_empty(literal lit) { - expr* e = ctx.bool_var2expr(lit.var()), *r = nullptr, *u = nullptr; - VERIFY(sk().is_is_empty(e, r, u)); + expr* e = ctx.bool_var2expr(lit.var()), *r = nullptr, *u = nullptr, *n = nullptr; + VERIFY(sk().is_is_empty(e, r, u, n)); expr_ref is_nullable = seq_rw().is_nullable(r); rewrite(is_nullable); if (m.is_true(is_nullable)) { @@ -508,7 +514,7 @@ namespace smt { return; } th.add_axiom(~lit, ~th.mk_literal(is_nullable)); - expr_ref hd = mk_first(r); + expr_ref hd = mk_first(r, n); expr_ref d(m); d = derivative_wrapper(hd, r); literal_vector lits; @@ -528,16 +534,17 @@ namespace smt { expr_ref ncond(mk_not(m, cond), m); lits.push_back(th.mk_literal(mk_forall(m, hd, ncond))); } - expr_ref is_empty1 = sk().mk_is_empty(p.second, re().mk_union(u, r)); + expr_ref is_empty1 = sk().mk_is_empty(p.second, re().mk_union(u, r), n); lits.push_back(th.mk_literal(is_empty1)); th.add_axiom(lits); } } - expr_ref seq_regex::mk_first(expr* r) { + expr_ref seq_regex::mk_first(expr* r, expr* n) { sort* elem_sort = nullptr, *seq_sort = nullptr; VERIFY(u().is_re(r, seq_sort)); VERIFY(u().is_seq(seq_sort, elem_sort)); - return expr_ref(m.mk_fresh_const("re.first", elem_sort), m); + sort* domain[2] = { m.get_sort(n), a().mk_int() }; + return sk().mk("re.first", n, a().mk_int(r->get_id()), elem_sort); } } diff --git a/src/smt/seq_regex.h b/src/smt/seq_regex.h index f339d36c9..1d77cf81d 100644 --- a/src/smt/seq_regex.h +++ b/src/smt/seq_regex.h @@ -71,7 +71,7 @@ namespace smt { bool propagate_derivative(literal lit, expr* e, expr* s, expr* i, unsigned idx, expr* r, literal& trigger); - expr_ref mk_first(expr* r); + expr_ref mk_first(expr* r, expr* n); expr_ref unroll_non_empty(expr* r, expr_mark& seen, unsigned depth); diff --git a/src/smt/seq_skolem.h b/src/smt/seq_skolem.h index 77233266d..18ad8e63d 100644 --- a/src/smt/seq_skolem.h +++ b/src/smt/seq_skolem.h @@ -48,11 +48,13 @@ namespace smt { expr_ref mk(symbol const& s, sort* range) { return mk(s, nullptr, nullptr, nullptr, nullptr, range); } expr_ref mk(symbol const& s, expr* e, sort* range) { return mk(s, e, nullptr, nullptr, nullptr, range); } expr_ref mk(symbol const& s, expr* e1, expr* e2, sort* range) { return mk(s, e1, e2, nullptr, nullptr, range); } + expr_ref mk(symbol const& s, expr* e1, expr* e2, expr* e3, sort* range) { return mk(s, e1, e2, e3, nullptr, range); } expr_ref mk(symbol const& s, expr* e1, expr* e2 = nullptr, expr* e3 = nullptr, expr* e4 = nullptr, sort* range = nullptr); expr_ref mk(char const* s, sort* range) { return mk(s, nullptr, nullptr, nullptr, nullptr, range); } expr_ref mk(char const* s, expr* e, sort* range) { return mk(s, e, nullptr, nullptr, nullptr, range); } expr_ref mk(char const* s, expr* e1, expr* e2, sort* range) { return mk(s, e1, e2, nullptr, nullptr, range); } + expr_ref mk(char const* s, expr* e1, expr* e2, expr* e3, sort* range) { return mk(s, e1, e2, e3, nullptr, range); } expr_ref mk(char const* s , expr* e1, expr* e2 = nullptr, expr* e3 = nullptr, expr* e4 = nullptr, sort* range = nullptr) { return mk(symbol(s), e1, e2, e3, e4, range); } @@ -70,8 +72,8 @@ namespace smt { } expr_ref mk_accept(expr_ref_vector const& args) { return expr_ref(seq.mk_skolem(m_accept, args.size(), args.c_ptr(), 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) { return mk(m_is_non_empty, r, u, m.mk_bool_sort()); } - expr_ref mk_is_empty(expr* r, expr* u) { return mk(m_is_empty, r, u, 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()); } + expr_ref mk_is_empty(expr* r, expr* u, expr* n) { return mk(m_is_empty, r, u, n, m.mk_bool_sort()); } expr_ref mk_indexof_left(expr* t, expr* s, expr* offset = nullptr) { return mk(m_indexof_left, t, s, offset); } expr_ref mk_indexof_right(expr* t, expr* s, expr* offset = nullptr) { return mk(m_indexof_right, t, s, offset); } @@ -135,11 +137,11 @@ namespace smt { 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) const { - return is_skolem(m_is_empty, e) && (r = to_app(e)->get_arg(0), u = to_app(e)->get_arg(1), true); + 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) const { - return is_skolem(m_is_non_empty, e) && (r = to_app(e)->get_arg(0), u = to_app(e)->get_arg(1), 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);