mirror of
https://github.com/Z3Prover/z3
synced 2025-08-06 19:21:22 +00:00
register unhandled expressions
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
2613f74baa
commit
41430cd128
5 changed files with 63 additions and 25 deletions
|
@ -101,7 +101,7 @@ namespace smt {
|
|||
expr* e = ctx.bool_var2expr(lit.var());
|
||||
VERIFY(str().is_in_re(e, s, r));
|
||||
|
||||
TRACE("seq", tout << "propagate " << mk_pp(e, m) << "\n";);
|
||||
TRACE("seq", tout << "propagate " << lit.sign() << " " << mk_pp(e, m) << "\n";);
|
||||
|
||||
// convert negative negative membership literals to positive
|
||||
// ~(s in R) => s in C(R)
|
||||
|
@ -109,6 +109,10 @@ namespace smt {
|
|||
expr_ref fml(re().mk_in_re(s, re().mk_complement(r)), m);
|
||||
rewrite(fml);
|
||||
literal nlit = th.mk_literal(fml);
|
||||
if (lit == nlit) {
|
||||
// is-nullable doesn't simplify for regexes with uninterpreted subterms
|
||||
th.add_unhandled_expr(fml);
|
||||
}
|
||||
th.propagate_lit(nullptr, 1, &lit, nlit);
|
||||
return;
|
||||
}
|
||||
|
@ -138,6 +142,8 @@ namespace smt {
|
|||
expr_ref acc = sk().mk_accept(s, zero, r);
|
||||
literal acc_lit = th.mk_literal(acc);
|
||||
|
||||
TRACE("seq", tout << "propagate " << acc << "\n";);
|
||||
|
||||
th.propagate_lit(nullptr, 1, &lit, acc_lit);
|
||||
}
|
||||
|
||||
|
@ -177,7 +183,7 @@ namespace smt {
|
|||
if (block_unfolding(lit, idx))
|
||||
return true;
|
||||
|
||||
propagate_nullable(lit, e, s, idx, r);
|
||||
propagate_nullable(lit, s, idx, r);
|
||||
|
||||
return propagate_derivative(lit, e, s, i, idx, r);
|
||||
}
|
||||
|
@ -187,9 +193,21 @@ namespace smt {
|
|||
|
||||
(accept s i r) => len(s) >= i
|
||||
(accept s i r) & ~nullable(r) => len(s) >= i + 1
|
||||
|
||||
evaluate nullable(r):
|
||||
nullable(r) := true -> propagate: (accept s i r) => len(s) >= i
|
||||
nullable(r) := false -> propagate: (accept s i r) => len(s) >= i + 1
|
||||
|
||||
Otherwise:
|
||||
propagate: (accept s i r) => len(s) >= i
|
||||
evaluate len(s) <= i:
|
||||
len(s) <= i := undef -> axiom: (accept s i r) & len(s) <= i => nullable(r)
|
||||
len(s) <= i := true -> propagate: (accept s i r) & len(s) <= i => nullable(r)
|
||||
len(s) <= i := false -> noop.
|
||||
|
||||
*/
|
||||
|
||||
void seq_regex::propagate_nullable(literal lit, expr* e, expr* s, unsigned idx, expr* r) {
|
||||
void seq_regex::propagate_nullable(literal lit, expr* s, unsigned idx, expr* r) {
|
||||
expr_ref is_nullable = seq_rw().is_nullable(r);
|
||||
rewrite(is_nullable);
|
||||
literal len_s_ge_i = th.m_ax.mk_ge(th.mk_len(s), idx);
|
||||
|
@ -200,14 +218,16 @@ namespace smt {
|
|||
th.propagate_lit(nullptr, 1, &lit, th.m_ax.mk_ge(th.mk_len(s), idx + 1));
|
||||
}
|
||||
else {
|
||||
literal is_nullable_lit = th.mk_literal(is_nullable);
|
||||
ctx.mark_as_relevant(is_nullable_lit);
|
||||
literal len_s_le_i = th.m_ax.mk_le(th.mk_len(s), idx);
|
||||
switch (ctx.get_assignment(len_s_le_i)) {
|
||||
case l_undef:
|
||||
th.add_axiom(~lit, ~len_s_le_i, th.mk_literal(is_nullable));
|
||||
th.add_axiom(~lit, ~len_s_le_i, is_nullable_lit);
|
||||
break;
|
||||
case l_true: {
|
||||
literal lits[2] = { lit, len_s_le_i };
|
||||
th.propagate_lit(nullptr, 2, lits, th.mk_literal(is_nullable));
|
||||
th.propagate_lit(nullptr, 2, lits, is_nullable_lit);
|
||||
break;
|
||||
}
|
||||
case l_false:
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace smt {
|
|||
|
||||
bool block_unfolding(literal lit, unsigned i);
|
||||
|
||||
void propagate_nullable(literal lit, expr* e, expr* s, unsigned idx, expr* r);
|
||||
void propagate_nullable(literal lit, expr* s, unsigned idx, expr* r);
|
||||
|
||||
bool propagate_derivative(literal lit, expr* e, expr* s, expr* i, unsigned idx, expr* r);
|
||||
|
||||
|
@ -99,7 +99,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_is_empty(literal lit);
|
||||
|
|
|
@ -2878,8 +2878,11 @@ literal theory_seq::mk_simplified_literal(expr * _e) {
|
|||
|
||||
literal theory_seq::mk_literal(expr* _e) {
|
||||
expr_ref e(_e, m);
|
||||
ensure_enode(e);
|
||||
return ctx.get_literal(e);
|
||||
bool is_not = m.is_not(_e, _e);
|
||||
ensure_enode(_e);
|
||||
literal lit = ctx.get_literal(_e);
|
||||
if (is_not) lit.neg();
|
||||
return lit;
|
||||
}
|
||||
|
||||
literal theory_seq::mk_seq_eq(expr* a, expr* b) {
|
||||
|
@ -3338,10 +3341,14 @@ void theory_seq::relevant_eh(app* n) {
|
|||
m_util.str.is_from_code(n) ||
|
||||
m_util.str.is_to_code(n) ||
|
||||
m_util.str.is_is_digit(n)) {
|
||||
if (!m_unhandled_expr) {
|
||||
ctx.push_trail(value_trail<context, expr*>(m_unhandled_expr));
|
||||
m_unhandled_expr = n;
|
||||
}
|
||||
add_unhandled_expr(n);
|
||||
}
|
||||
}
|
||||
|
||||
void theory_seq::add_unhandled_expr(expr* n) {
|
||||
if (!m_unhandled_expr) {
|
||||
ctx.push_trail(value_trail<context, expr*>(m_unhandled_expr));
|
||||
m_unhandled_expr = n;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -506,6 +506,7 @@ namespace smt {
|
|||
bool set_empty(expr* x);
|
||||
bool is_complex(eq const& e);
|
||||
lbool regex_are_equal(expr* r1, expr* r2);
|
||||
void add_unhandled_expr(expr* e);
|
||||
|
||||
bool check_extensionality();
|
||||
bool check_contains();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue