mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 20:18:18 +00:00
parent
3aea4ebf42
commit
50d76a2fe3
|
@ -243,8 +243,8 @@ namespace euf {
|
||||||
|
|
||||||
void solve_context_eqs::collect_nested_equalities(dependent_expr const& df, expr_mark& visited, dep_eq_vector& eqs) {
|
void solve_context_eqs::collect_nested_equalities(dependent_expr const& df, expr_mark& visited, dep_eq_vector& eqs) {
|
||||||
|
|
||||||
svector<std::tuple<bool,unsigned,expr*>> todo;
|
svector<std::tuple<bool,unsigned,expr*, unsigned>> todo;
|
||||||
todo.push_back({ false, 0, df.fml()});
|
todo.push_back({ false, 0, df.fml(), 0});
|
||||||
|
|
||||||
// even depth is conjunctive context, odd is disjunctive
|
// even depth is conjunctive context, odd is disjunctive
|
||||||
// when alternating between conjunctive and disjunctive context, increment depth.
|
// when alternating between conjunctive and disjunctive context, increment depth.
|
||||||
|
@ -255,37 +255,84 @@ namespace euf {
|
||||||
return (0 == depth % 2) ? depth : depth + 1;
|
return (0 == depth % 2) ? depth : depth + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
while (!todo.empty()) {
|
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||||
auto [s, depth, f] = todo.back();
|
auto [s, depth, f, p] = todo[i];
|
||||||
todo.pop_back();
|
|
||||||
if (visited.is_marked(f))
|
if (visited.is_marked(f))
|
||||||
continue;
|
continue;
|
||||||
visited.mark(f, true);
|
visited.mark(f, true);
|
||||||
if (s && m.is_and(f)) {
|
if (s && m.is_and(f)) {
|
||||||
for (auto* arg : *to_app(f))
|
for (auto* arg : *to_app(f))
|
||||||
todo.push_back({ s, inc_or(depth), arg });
|
todo.push_back({ s, inc_or(depth), arg, i });
|
||||||
}
|
}
|
||||||
else if (!s && m.is_or(f)) {
|
else if (!s && m.is_or(f)) {
|
||||||
for (auto* arg : *to_app(f))
|
for (auto* arg : *to_app(f))
|
||||||
todo.push_back({ s, inc_or(depth), arg });
|
todo.push_back({ s, inc_or(depth), arg, i });
|
||||||
}
|
}
|
||||||
if (!s && m.is_and(f)) {
|
if (!s && m.is_and(f)) {
|
||||||
for (auto* arg : *to_app(f))
|
for (auto* arg : *to_app(f))
|
||||||
todo.push_back({ s, inc_and(depth), arg });
|
todo.push_back({ s, inc_and(depth), arg, i });
|
||||||
}
|
}
|
||||||
else if (s && m.is_or(f)) {
|
else if (s && m.is_or(f)) {
|
||||||
for (auto* arg : *to_app(f))
|
for (auto* arg : *to_app(f))
|
||||||
todo.push_back({ s, inc_and(depth), arg });
|
todo.push_back({ s, inc_and(depth), arg, i });
|
||||||
}
|
}
|
||||||
else if (m.is_not(f, f))
|
else if (m.is_not(f, f))
|
||||||
todo.push_back({ !s, depth, f });
|
todo.push_back({ !s, depth, f, i });
|
||||||
else if (!s && 1 <= depth) {
|
else if (!s && 1 <= depth) {
|
||||||
|
unsigned sz = eqs.size();
|
||||||
for (extract_eq* ex : m_solve_eqs.m_extract_plugins) {
|
for (extract_eq* ex : m_solve_eqs.m_extract_plugins) {
|
||||||
ex->set_allow_booleans(false);
|
ex->set_allow_booleans(false);
|
||||||
ex->get_eqs(dependent_expr(m, f, nullptr, df.dep()), eqs);
|
ex->get_eqs(dependent_expr(m, f, nullptr, df.dep()), eqs);
|
||||||
ex->set_allow_booleans(true);
|
ex->set_allow_booleans(true);
|
||||||
}
|
}
|
||||||
|
// prune eqs for solutions that are not safe in df.fml()
|
||||||
|
for (; sz < eqs.size(); ++sz) {
|
||||||
|
if (!is_safe_var(eqs[sz].var, i, df.fml(), todo)) {
|
||||||
|
eqs[sz] = eqs.back();
|
||||||
|
--sz;
|
||||||
|
eqs.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool solve_context_eqs::is_safe_var(expr* x, unsigned i, expr* f, svector<std::tuple<bool,unsigned,expr*,unsigned>> const& todo) {
|
||||||
|
m_contains_v.reset();
|
||||||
|
m_todo.push_back(f);
|
||||||
|
mark_occurs(m_todo, x, m_contains_v);
|
||||||
|
SASSERT(m_todo.empty());
|
||||||
|
|
||||||
|
auto is_parent = [&](unsigned p, unsigned i) {
|
||||||
|
while (p != i && i != 0) {
|
||||||
|
auto [_s,_depth, _f, _p] = todo[i];
|
||||||
|
i = _p;
|
||||||
|
}
|
||||||
|
return p == i;
|
||||||
|
};
|
||||||
|
|
||||||
|
// retrieve oldest parent of i whose sign is false
|
||||||
|
unsigned pi = i;
|
||||||
|
while (pi != 0) {
|
||||||
|
auto [s, depth, f, p] = todo[pi];
|
||||||
|
if (s)
|
||||||
|
break;
|
||||||
|
pi = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine if j and j have common conjunctive parent
|
||||||
|
// for every j in todo.
|
||||||
|
for (unsigned j = 0; j < todo.size(); ++j) {
|
||||||
|
auto [s, depth, f, p] = todo[j];
|
||||||
|
if (i == j || !m_contains_v.is_marked(f))
|
||||||
|
continue;
|
||||||
|
if (is_parent(j, i)) // j is a parent if i
|
||||||
|
continue;
|
||||||
|
if (is_parent(pi, j)) // pi is a parent of j
|
||||||
|
continue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ namespace euf {
|
||||||
|
|
||||||
void collect_nested_equalities(dependent_expr const& f, expr_mark& visited, dep_eq_vector& eqs);
|
void collect_nested_equalities(dependent_expr const& f, expr_mark& visited, dep_eq_vector& eqs);
|
||||||
|
|
||||||
|
bool is_safe_var(expr* x, unsigned i, expr* f, svector<std::tuple<bool,unsigned,expr*,unsigned>> const& todo);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
solve_context_eqs(solve_eqs& s);
|
solve_context_eqs(solve_eqs& s);
|
||||||
|
|
Loading…
Reference in a new issue