mirror of
https://github.com/Z3Prover/z3
synced 2026-04-26 13:53:33 +00:00
hoist functionality
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
5f5a0ffbd8
commit
9a29a0fc24
2 changed files with 34 additions and 27 deletions
|
|
@ -42,12 +42,10 @@ NSB review:
|
||||||
|
|
||||||
namespace seq {
|
namespace seq {
|
||||||
|
|
||||||
void deps_to_lits(dep_tracker const& deps,
|
void deps_to_lits(dep_tracker const &deps, svector<enode_pair> &eqs, svector<sat::literal> &lits) {
|
||||||
svector<enode_pair>& eqs,
|
|
||||||
svector<sat::literal>& lits) {
|
|
||||||
vector<dep_source, false> vs;
|
vector<dep_source, false> vs;
|
||||||
dep_manager::s_linearize(deps, vs);
|
dep_manager::s_linearize(deps, vs);
|
||||||
for (dep_source const& d : vs) {
|
for (dep_source const &d : vs) {
|
||||||
if (std::holds_alternative<enode_pair>(d))
|
if (std::holds_alternative<enode_pair>(d))
|
||||||
eqs.push_back(std::get<enode_pair>(d));
|
eqs.push_back(std::get<enode_pair>(d));
|
||||||
else
|
else
|
||||||
|
|
@ -58,7 +56,7 @@ namespace seq {
|
||||||
// Normalize an arithmetic expression using th_rewriter.
|
// Normalize an arithmetic expression using th_rewriter.
|
||||||
// Simplifies e.g. (n - 1 + 1) to n, preventing unbounded growth
|
// Simplifies e.g. (n - 1 + 1) to n, preventing unbounded growth
|
||||||
// of power exponents during unwind/merge cycles.
|
// of power exponents during unwind/merge cycles.
|
||||||
static expr_ref normalize_arith(ast_manager& m, expr* e) {
|
static expr_ref normalize_arith(ast_manager &m, expr *e) {
|
||||||
expr_ref result(e, m);
|
expr_ref result(e, m);
|
||||||
th_rewriter rw(m);
|
th_rewriter rw(m);
|
||||||
rw(result);
|
rw(result);
|
||||||
|
|
@ -68,25 +66,30 @@ namespace seq {
|
||||||
// Directional helpers mirroring ZIPT's fwd flag:
|
// Directional helpers mirroring ZIPT's fwd flag:
|
||||||
// fwd=true -> left-to-right (prefix/head)
|
// fwd=true -> left-to-right (prefix/head)
|
||||||
// fwd=false -> right-to-left (suffix/tail)
|
// fwd=false -> right-to-left (suffix/tail)
|
||||||
static euf::snode* dir_token(euf::snode* s, bool fwd) {
|
static euf::snode *dir_token(euf::snode *s, bool fwd) {
|
||||||
if (!s) return nullptr;
|
if (!s)
|
||||||
|
return nullptr;
|
||||||
return fwd ? s->first() : s->last();
|
return fwd ? s->first() : s->last();
|
||||||
}
|
}
|
||||||
|
|
||||||
static euf::snode* dir_drop(euf::sgraph& sg, euf::snode* s, unsigned count, bool fwd) {
|
static euf::snode *dir_drop(euf::sgraph &sg, euf::snode *s, unsigned count, bool fwd) {
|
||||||
if (!s || count == 0) return s;
|
if (!s || count == 0)
|
||||||
|
return s;
|
||||||
return fwd ? sg.drop_left(s, count) : sg.drop_right(s, count);
|
return fwd ? sg.drop_left(s, count) : sg.drop_right(s, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static euf::snode* dir_concat(euf::sgraph& sg, euf::snode* a, euf::snode* b, bool fwd) {
|
static euf::snode *dir_concat(euf::sgraph &sg, euf::snode *a, euf::snode *b, bool fwd) {
|
||||||
if (!a) return b;
|
if (!a)
|
||||||
if (!b) return a;
|
return b;
|
||||||
|
if (!b)
|
||||||
|
return a;
|
||||||
return fwd ? sg.mk_concat(a, b) : sg.mk_concat(b, a);
|
return fwd ? sg.mk_concat(a, b) : sg.mk_concat(b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void collect_tokens_dir(euf::snode* s, bool fwd, euf::snode_vector& toks) {
|
static void collect_tokens_dir(euf::snode *s, bool fwd, euf::snode_vector &toks) {
|
||||||
toks.reset();
|
toks.reset();
|
||||||
if (!s) return;
|
if (!s)
|
||||||
|
return;
|
||||||
s->collect_tokens(toks);
|
s->collect_tokens(toks);
|
||||||
if (!fwd)
|
if (!fwd)
|
||||||
toks.reverse();
|
toks.reverse();
|
||||||
|
|
@ -94,15 +97,15 @@ namespace seq {
|
||||||
|
|
||||||
// Right-derivative helper used by backward str_mem simplification:
|
// Right-derivative helper used by backward str_mem simplification:
|
||||||
// dR(re, c) = reverse( derivative(c, reverse(re)) ).
|
// dR(re, c) = reverse( derivative(c, reverse(re)) ).
|
||||||
static euf::snode* reverse_brzozowski_deriv(euf::sgraph& sg, euf::snode* re, euf::snode* elem) {
|
static euf::snode *reverse_brzozowski_deriv(euf::sgraph &sg, euf::snode *re, euf::snode *elem) {
|
||||||
if (!re || !elem || !re->get_expr() || !elem->get_expr())
|
if (!re || !elem || !re->get_expr() || !elem->get_expr())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
ast_manager& m = sg.get_manager();
|
ast_manager &m = sg.get_manager();
|
||||||
seq_util& seq = sg.get_seq_util();
|
seq_util &seq = sg.get_seq_util();
|
||||||
seq_rewriter rw(m);
|
seq_rewriter rw(m);
|
||||||
|
|
||||||
expr* elem_expr = elem->get_expr();
|
expr *elem_expr = elem->get_expr();
|
||||||
expr* ch = nullptr;
|
expr *ch = nullptr;
|
||||||
if (seq.str.is_unit(elem_expr, ch))
|
if (seq.str.is_unit(elem_expr, ch))
|
||||||
elem_expr = ch;
|
elem_expr = ch;
|
||||||
|
|
||||||
|
|
@ -127,18 +130,17 @@ namespace seq {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool str_eq::is_trivial() const {
|
bool str_eq::is_trivial() const {
|
||||||
return m_lhs == m_rhs ||
|
return m_lhs == m_rhs || (m_lhs && m_rhs && m_lhs->is_empty() && m_rhs->is_empty());
|
||||||
(m_lhs && m_rhs && m_lhs->is_empty() && m_rhs->is_empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool str_eq::contains_var(euf::snode* var) const {
|
bool str_eq::contains_var(euf::snode *var) const {
|
||||||
if (!var)
|
if (!var)
|
||||||
return false;
|
return false;
|
||||||
// check if var appears in the token list of lhs or rhs
|
// check if var appears in the token list of lhs or rhs
|
||||||
if (m_lhs) {
|
if (m_lhs) {
|
||||||
euf::snode_vector tokens;
|
euf::snode_vector tokens;
|
||||||
m_lhs->collect_tokens(tokens);
|
m_lhs->collect_tokens(tokens);
|
||||||
for (euf::snode* t : tokens) {
|
for (euf::snode *t : tokens) {
|
||||||
if (t == var)
|
if (t == var)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -146,7 +148,7 @@ namespace seq {
|
||||||
if (m_rhs) {
|
if (m_rhs) {
|
||||||
euf::snode_vector tokens;
|
euf::snode_vector tokens;
|
||||||
m_rhs->collect_tokens(tokens);
|
m_rhs->collect_tokens(tokens);
|
||||||
for (euf::snode* t : tokens) {
|
for (euf::snode *t : tokens) {
|
||||||
if (t == var)
|
if (t == var)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -166,6 +168,10 @@ namespace seq {
|
||||||
return m_str && m_regex && m_str->is_empty() && m_regex->is_nullable();
|
return m_str && m_regex && m_str->is_empty() && m_regex->is_nullable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool str_mem::is_contradiction() const {
|
||||||
|
return (m_str && m_regex && m_str->is_empty() && !m_regex->is_nullable());
|
||||||
|
}
|
||||||
|
|
||||||
bool str_mem::contains_var(euf::snode* var) const {
|
bool str_mem::contains_var(euf::snode* var) const {
|
||||||
SASSERT(var);
|
SASSERT(var);
|
||||||
if (m_str) {
|
if (m_str) {
|
||||||
|
|
@ -1173,8 +1179,7 @@ namespace seq {
|
||||||
|
|
||||||
// check for regex memberships that are immediately infeasible
|
// check for regex memberships that are immediately infeasible
|
||||||
for (str_mem& mem : m_str_mem) {
|
for (str_mem& mem : m_str_mem) {
|
||||||
SASSERT(mem.m_str && mem.m_regex);
|
if (mem.is_contradiction()) {
|
||||||
if (mem.m_str->is_empty() && !mem.m_regex->is_nullable()) {
|
|
||||||
m_is_general_conflict = true;
|
m_is_general_conflict = true;
|
||||||
m_reason = backtrack_reason::regex;
|
m_reason = backtrack_reason::regex;
|
||||||
return simplify_result::conflict;
|
return simplify_result::conflict;
|
||||||
|
|
|
||||||
|
|
@ -405,7 +405,9 @@ namespace seq {
|
||||||
// check if the constraint has the form x in R with x a single variable
|
// check if the constraint has the form x in R with x a single variable
|
||||||
bool is_primitive() const;
|
bool is_primitive() const;
|
||||||
|
|
||||||
bool is_trivial() const;
|
bool is_trivial() const;
|
||||||
|
|
||||||
|
bool is_contradiction() const;
|
||||||
|
|
||||||
// check if the constraint contains a given variable
|
// check if the constraint contains a given variable
|
||||||
bool contains_var(euf::snode* var) const;
|
bool contains_var(euf::snode* var) const;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue