3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-06 07:16:13 +00:00

hoist functionality

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2026-04-01 09:41:49 -07:00
parent 5f5a0ffbd8
commit 9a29a0fc24
2 changed files with 34 additions and 27 deletions

View file

@ -42,9 +42,7 @@ 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) {
@ -69,24 +67,29 @@ namespace seq {
// 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();
@ -127,8 +130,7 @@ 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 {
@ -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;

View file

@ -407,6 +407,8 @@ namespace seq {
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;
}; };