3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-02-08 10:07:59 +00:00

working on sub/super slices

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2023-12-22 17:45:23 -08:00
parent 9a7e50c1e8
commit 5bbec43235
4 changed files with 134 additions and 24 deletions

View file

@ -36,7 +36,7 @@ namespace polysat {
}
};
void solver::get_subslices(pvar pv, subslice_infos& slices) {
void solver::get_sub_slices(pvar pv, slice_infos& slices) {
theory_var v = m_pddvar2var[pv];
unsigned lo, hi;
expr* e = nullptr;
@ -60,11 +60,11 @@ namespace polysat {
}
}
for (auto p : euf::enode_parents(n->get_root())) {
if (p->is_marked1())
if (p->get_root()->is_marked1())
continue;
if (bv.is_extract(p->get_expr(), lo, hi, e)) {
auto child = expr2enode(e);
SASSERT(n == child->get_root());
SASSERT(n->get_root() == child->get_root());
scoped_eq_justification sp(*this, just, child, n);
slices.push_back({ p, offset + lo, just });
}
@ -74,41 +74,136 @@ namespace polysat {
n->get_root()->unmark1();
}
void solver::get_super_slices(pvar pv, slice_infos& slices) {
theory_var v = m_pddvar2var[pv];
unsigned lo, hi;
expr* e = nullptr;
euf::enode* n = var2enode(v);
slices.push_back({ n, 0, {} });
// walk the egraph starting with pvar for overlaps.
for (unsigned i = 0; i < slices.size(); ++i) {
auto [n, offset, just] = slices[i];
if (n->get_root()->is_marked1())
continue;
n->get_root()->mark1();
for (auto sib : euf::enode_class(n)) {
if (bv.is_extract(sib->get_expr(), lo, hi, e)) {
auto child = expr2enode(e);
SASSERT(n->get_root() == child->get_root());
scoped_eq_justification sp(*this, just, child, n);
slices.push_back({ sib, offset + lo, just });
}
}
for (auto p : euf::enode_parents(n->get_root())) {
if (p->get_root()->is_marked1())
continue;
if (bv.is_concat(p->get_expr())) {
unsigned delta = 0;
for (unsigned j = p->num_args(); j-- > 0; ) {
auto arg = p->get_arg(j);
if (arg->get_root() == n->get_root()) {
scoped_eq_justification sp(*this, just, arg, n);
slices.push_back({ p, offset + delta, just });
}
delta += bv.get_bv_size(arg->get_expr());
}
}
}
}
for (auto const& [n, offset, d] : slices)
n->get_root()->unmark1();
}
// walk the egraph starting with pvar for suffix overlaps.
void solver::get_bitvector_suffixes(pvar pv, justified_slices& out) {
subslice_infos slices;
get_subslices(pv, slices);
slice_infos slices;
get_sub_slices(pv, slices);
uint_set seen;
for (auto& [n, offset, just] : slices) {
if (offset != 0)
continue;
auto w = n->get_th_var(get_id());
if (w == euf::null_theory_var)
continue;
auto const& p = m_var2pdd[w];
if (p.is_var())
out.push_back({ p.var(), dependency(just, s().scope_lvl())}); // approximate to current scope
for (auto sib : euf::enode_class(n)) {
auto w = sib->get_th_var(get_id());
if (w == euf::null_theory_var)
continue;
if (seen.contains(w))
continue;
seen.insert(w);
auto const& p = m_var2pdd[w];
if (!p.is_var())
continue;
scoped_eq_justification sp(*this, just, sib, n);
out.push_back({ p.var(), offset, dependency(just, s().scope_lvl()) }); // approximate to current scope
}
}
}
// walk the egraph starting with pvar for any overlaps.
void solver::get_bitvector_sub_slices(pvar pv, justified_slices& out) {
slice_infos slices;
get_sub_slices(pv, slices);
uint_set seen;
for (auto& [n, offset, just] : slices) {
for (auto sib : euf::enode_class(n)) {
auto w = sib->get_th_var(get_id());
if (w == euf::null_theory_var)
continue;
if (seen.contains(w))
continue;
seen.insert(w);
auto const& p = m_var2pdd[w];
if (!p.is_var())
continue;
scoped_eq_justification sp(*this, just, sib, n);
out.push_back({ p.var(), offset, dependency(just, s().scope_lvl()) }); // approximate to current scope
}
}
}
// walk the egraph for bit-vectors that contain pv.
void solver::get_bitvector_super_slices(pvar pv, justified_slices& out) {
slice_infos slices;
get_super_slices(pv, slices);
uint_set seen;
for (auto& [n, offset, just] : slices) {
for (auto sib : euf::enode_class(n)) {
auto w = sib->get_th_var(get_id());
if (w == euf::null_theory_var)
continue;
if (seen.contains(w))
continue;
seen.insert(w);
auto const& p = m_var2pdd[w];
if (!p.is_var())
continue;
scoped_eq_justification sp(*this, just, sib, n);
out.push_back({ p.var(), offset, dependency(just, s().scope_lvl()) }); // approximate to current scope
}
}
}
// walk the e-graph to retrieve fixed overlaps
void solver::get_fixed_bits(pvar pv, justified_fixed_bits& out) {
subslice_infos slices;
get_subslices(pv, slices);
slice_infos slices;
get_sub_slices(pv, slices);
for (auto& [n, offset, just] : slices) {
if (offset != 0)
continue;
n = n->get_root();
if (!n->interpreted())
if (!n->get_root()->interpreted())
continue;
auto w = n->get_th_var(get_id());
auto w = n->get_root()->get_th_var(get_id());
if (w == euf::null_theory_var)
continue;
auto const& p = m_var2pdd[w];
if (!p.is_var())
continue;
scoped_eq_justification sp(*this, just, n, n->get_root());
unsigned lo = offset, hi = bv.get_bv_size(n->get_expr());
rational value;
VERIFY(bv.is_numeral(n->get_expr(), value));