mirror of
https://github.com/Z3Prover/z3
synced 2026-03-09 14:54:53 +00:00
Changes before error encountered
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
parent
037d2da801
commit
a3baae5942
6 changed files with 72 additions and 136 deletions
|
|
@ -28,7 +28,8 @@ namespace euf {
|
|||
|
||||
// Check if enode is any kind of concat (str.++ or re.++)
|
||||
static bool is_any_concat(enode* n, seq_util const& seq) {
|
||||
return (seq.str.is_concat(n->get_expr()) || seq.re.is_concat(n->get_expr())) && n->num_args() == 2;
|
||||
expr* a = nullptr, *b = nullptr;
|
||||
return seq.str.is_concat(n->get_expr(), a, b) || seq.re.is_concat(n->get_expr(), a, b);
|
||||
}
|
||||
|
||||
// Collect leaves of a concat tree in left-to-right order.
|
||||
|
|
@ -57,8 +58,8 @@ namespace euf {
|
|||
|
||||
bool enode_concat_eq::operator()(enode* a, enode* b) const {
|
||||
if (a == b) return true;
|
||||
if (!is_any_concat(a, seq) && !is_any_concat(b, seq))
|
||||
return a->get_id() == b->get_id();
|
||||
if (!is_any_concat(a, seq) || !is_any_concat(b, seq))
|
||||
return false;
|
||||
enode_vector la, lb;
|
||||
collect_enode_leaves(a, seq, la);
|
||||
collect_enode_leaves(b, seq, lb);
|
||||
|
|
@ -101,11 +102,11 @@ namespace euf {
|
|||
if (g.inconsistent())
|
||||
break;
|
||||
if (std::holds_alternative<enode*>(m_queue[m_qhead])) {
|
||||
auto n = *std::get_if<enode*>(&m_queue[m_qhead]);
|
||||
auto n = std::get<enode*>(m_queue[m_qhead]);
|
||||
propagate_register_node(n);
|
||||
}
|
||||
else {
|
||||
auto [a, b] = *std::get_if<enode_pair>(&m_queue[m_qhead]);
|
||||
auto [a, b] = std::get<enode_pair>(m_queue[m_qhead]);
|
||||
propagate_merge(a, b);
|
||||
}
|
||||
}
|
||||
|
|
@ -122,14 +123,6 @@ namespace euf {
|
|||
propagate_simplify(n);
|
||||
}
|
||||
|
||||
// n-ary concat: concat(a, b, c) => concat(a, concat(b, c))
|
||||
if (is_concat(n) && n->num_args() > 2) {
|
||||
auto last = n->get_arg(n->num_args() - 1);
|
||||
for (unsigned i = n->num_args() - 1; i-- > 0; )
|
||||
last = mk_concat(n->get_arg(i), last);
|
||||
push_merge(last, n);
|
||||
}
|
||||
|
||||
// str.++ identity: concat(a, ε) = a, concat(ε, b) = b
|
||||
enode* a, *b;
|
||||
if (is_str_concat(n, a, b)) {
|
||||
|
|
@ -223,24 +216,15 @@ namespace euf {
|
|||
push_merge(n, b);
|
||||
|
||||
// concat(.*, concat(v, w)) = concat(.*, w) when v nullable
|
||||
if (is_full_seq(a) && is_concat(b, b1, b2) && is_nullable(b1)) {
|
||||
enode* simplified = mk_concat(a, b2);
|
||||
push_merge(n, simplified);
|
||||
}
|
||||
// handled by associativity + nullable absorption on sub-concats
|
||||
|
||||
// concat(concat(u, v), .*) = concat(u, .*) when v nullable
|
||||
enode* a1, *a2;
|
||||
if (is_concat(a, a1, a2) && is_nullable(a2) && is_full_seq(b)) {
|
||||
enode* simplified = mk_concat(a1, b);
|
||||
push_merge(n, simplified);
|
||||
}
|
||||
// handled by associativity + nullable absorption on sub-concats
|
||||
}
|
||||
|
||||
bool seq_plugin::is_nullable(expr* e) {
|
||||
// use existing seq_rewriter::is_nullable which handles all cases
|
||||
ast_manager& m = g.get_manager();
|
||||
expr_ref result = m_rewriter.is_nullable(e);
|
||||
return m.is_true(result);
|
||||
return g.get_manager().is_true(result);
|
||||
}
|
||||
|
||||
bool seq_plugin::same_star_body(enode* a, enode* b) {
|
||||
|
|
@ -267,34 +251,6 @@ namespace euf {
|
|||
return na->get_root() == nb->get_root();
|
||||
}
|
||||
|
||||
enode* seq_plugin::mk_str_concat(enode* a, enode* b) {
|
||||
expr* e = m_seq.str.mk_concat(a->get_expr(), b->get_expr());
|
||||
enode* args[2] = { a, b };
|
||||
return mk(e, 2, args);
|
||||
}
|
||||
|
||||
enode* seq_plugin::mk_re_concat(enode* a, enode* b) {
|
||||
expr* e = m_seq.re.mk_concat(a->get_expr(), b->get_expr());
|
||||
enode* args[2] = { a, b };
|
||||
return mk(e, 2, args);
|
||||
}
|
||||
|
||||
enode* seq_plugin::mk_concat(enode* a, enode* b) {
|
||||
if (m_seq.is_re(a->get_expr()))
|
||||
return mk_re_concat(a, b);
|
||||
return mk_str_concat(a, b);
|
||||
}
|
||||
|
||||
enode* seq_plugin::mk_str_empty(sort* s) {
|
||||
expr* e = m_seq.str.mk_empty(s);
|
||||
return mk(e, 0, nullptr);
|
||||
}
|
||||
|
||||
enode* seq_plugin::mk_re_epsilon(sort* seq_sort) {
|
||||
expr* e = m_seq.re.mk_epsilon(seq_sort);
|
||||
return mk(e, 0, nullptr);
|
||||
}
|
||||
|
||||
void seq_plugin::undo() {
|
||||
auto k = m_undo.back();
|
||||
m_undo.pop_back();
|
||||
|
|
|
|||
|
|
@ -92,14 +92,18 @@ namespace euf {
|
|||
// string concat predicates
|
||||
bool is_str_concat(enode* n) const { return m_seq.str.is_concat(n->get_expr()); }
|
||||
bool is_str_concat(enode* n, enode*& a, enode*& b) {
|
||||
return is_str_concat(n) && n->num_args() == 2 &&
|
||||
expr* ea = nullptr, *eb = nullptr;
|
||||
return m_seq.str.is_concat(n->get_expr(), ea, eb) &&
|
||||
n->num_args() == 2 &&
|
||||
(a = n->get_arg(0), b = n->get_arg(1), true);
|
||||
}
|
||||
|
||||
// regex concat predicates
|
||||
bool is_re_concat(enode* n) const { return m_seq.re.is_concat(n->get_expr()); }
|
||||
bool is_re_concat(enode* n, enode*& a, enode*& b) {
|
||||
return is_re_concat(n) && n->num_args() == 2 &&
|
||||
expr* ea = nullptr, *eb = nullptr;
|
||||
return m_seq.re.is_concat(n->get_expr(), ea, eb) &&
|
||||
n->num_args() == 2 &&
|
||||
(a = n->get_arg(0), b = n->get_arg(1), true);
|
||||
}
|
||||
|
||||
|
|
@ -122,12 +126,6 @@ namespace euf {
|
|||
bool is_to_re(enode* n) const { return m_seq.re.is_to_re(n->get_expr()); }
|
||||
bool is_full_seq(enode* n) const { return m_seq.re.is_full_seq(n->get_expr()); }
|
||||
|
||||
enode* mk_str_concat(enode* a, enode* b);
|
||||
enode* mk_re_concat(enode* a, enode* b);
|
||||
enode* mk_concat(enode* a, enode* b);
|
||||
enode* mk_str_empty(sort* s);
|
||||
enode* mk_re_epsilon(sort* seq_sort);
|
||||
|
||||
void push_undo(undo_kind k);
|
||||
|
||||
void propagate_register_node(enode* n);
|
||||
|
|
|
|||
|
|
@ -369,31 +369,6 @@ namespace euf {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
snode* sgraph::mk_empty(sort* s) {
|
||||
expr_ref e(m_seq.str.mk_empty(s), m);
|
||||
return mk(e);
|
||||
}
|
||||
|
||||
snode* sgraph::mk_concat(snode* a, snode* b) {
|
||||
SASSERT(a && b);
|
||||
if (a->is_empty()) return b;
|
||||
if (b->is_empty()) return a;
|
||||
expr_ref e(m_seq.str.mk_concat(a->get_expr(), b->get_expr()), m);
|
||||
snode* n = find(e);
|
||||
if (n) return n;
|
||||
snode* args[2] = { a, b };
|
||||
return mk_snode(e, snode_kind::s_concat, 2, args);
|
||||
}
|
||||
|
||||
snode* sgraph::mk_power(snode* base, snode* exp) {
|
||||
SASSERT(base && exp);
|
||||
expr_ref e(m_seq.str.mk_power(base->get_expr(), exp->get_expr()), m);
|
||||
snode* n = find(e);
|
||||
if (n) return n;
|
||||
snode* args[2] = { base, exp };
|
||||
return mk_snode(e, snode_kind::s_power, 2, args);
|
||||
}
|
||||
|
||||
enode* sgraph::mk_enode(expr* e) {
|
||||
enode* n = m_egraph.find(e);
|
||||
if (n) return n;
|
||||
|
|
|
|||
|
|
@ -141,11 +141,6 @@ namespace euf {
|
|||
// find an existing concat that is equal modulo associativity
|
||||
snode* find_assoc_equal(snode* n) const;
|
||||
|
||||
// build compound snodes
|
||||
snode* mk_empty(sort* s);
|
||||
snode* mk_concat(snode* a, snode* b);
|
||||
snode* mk_power(snode* base, snode* exp);
|
||||
|
||||
// register expression in both sgraph and egraph
|
||||
enode* mk_enode(expr* e);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue