3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 08:35:31 +00:00

propagate from containing slice: consider e->bit_width

This commit is contained in:
Jakob Rath 2024-02-02 15:00:24 +01:00
parent 394f25a42f
commit 52c6fd98fd
2 changed files with 47 additions and 18 deletions

View file

@ -183,7 +183,7 @@ namespace polysat {
// dependency_vector get_dependencies(constraint_id_vector const& ids) const;
lbool weak_eval(constraint_id id);
lbool strong_eval(constraint_id id);
dependency propagate(signed_constraint const& sc, dependency_vector const& deps) { return s.propagate(sc, deps, nullptr); }
dependency propagate(signed_constraint const& sc, dependency_vector const& deps, char const* hint = nullptr) { return s.propagate(sc, deps, hint); }
lbool weak_eval(signed_constraint const& sc);
lbool strong_eval(signed_constraint const& sc);
dependency_vector explain_weak_eval(signed_constraint const& sc);

View file

@ -633,20 +633,49 @@ namespace polysat {
}
void viable::propagate_from_containing_slice(entry* e, rational const& value, dependency_vector const& e_deps, offset_slice const& slice) {
auto [y, offset] = slice;
if (y == m_var)
auto [w, offset] = slice;
if (w == m_var)
return;
// v = vvvvvvvvvvvvvvvvvvvvvvv
// xxxxxxyyyyyyyyzzzzzzzzz
// y_sz offset
unsigned const v_sz = c.size(m_var);
unsigned const y_sz = c.size(y);
verbose_stream() << "v" << m_var << " size " << c.size(m_var) << ", v" << w << " size " << c.size(w) << " offset " << offset << "\n";
// Let:
// v = m_var[e->bit_width-1:0]
// v = concat(x, y, z)
// y = w[y_sz-1:0]
// e->bit_width
// m_var = ???????vvvvvvvvvvvvvvvvvvvvvvv
// wwwwwwww
// xxxxxxyyyyyyyyzzzzzzzzz
// y_sz offset
//
// or:
// m_var = ???????vvvvvvvvvvvvvvvvvvvvvvv
// wwwwwwwwwwwwwwwww
// yyyyyyyyyyyyyyzzzzzzzzz
//
// or:
// m_var = ?????????????????vvvvvvvvvvvvv
// wwwwwwwww
unsigned const v_sz = e->bit_width;
if (offset >= v_sz)
return;
unsigned const w_sz = c.size(w);
unsigned const z_sz = offset;
unsigned const x_sz = v_sz - y_sz - offset;
verbose_stream() << "v" << m_var << " size " << v_sz << ", v" << y << " size " << y_sz << " offset " << offset << "\n";
unsigned const y_sz = std::min(w_sz, v_sz - z_sz);
unsigned const x_sz = v_sz - y_sz;
rational const& w_shift = rational::power_of_two(w_sz - y_sz);
verbose_stream() << "v_sz " << v_sz << " w_sz " << w_sz << " / x_sz " << x_sz << " y_sz " << y_sz << " z_sz " << z_sz << "\n";
display_one(verbose_stream() << "entry: ", e) << "\n";
verbose_stream() << "value " << value << "\n";
SASSERT(!e->interval.is_full());
rational const& lo = e->interval.lo_val();
rational const& hi = e->interval.hi_val();
if (v_sz == y_sz) {
#if 0
// TODO: copy interval over?
@ -665,11 +694,11 @@ namespace polysat {
return;
}
r_interval const v_ivl = r_interval::proper(lo, hi);
verbose_stream() << "propagate interval " << v_ivl << " from v" << m_var << " to v" << y << "\n";
verbose_stream() << "propagate interval " << v_ivl << " from v" << m_var << " to v" << w << "[" << y_sz << "]" << "\n";
// more general interval, without taking into account fixed values
// TODO: should we always create this? (maybe not here?)
{
r_interval const yz_ivl = chop_off_upper(v_ivl, x_sz, y_sz + z_sz); // chop off x-part
r_interval const y_ivl = chop_off_lower(yz_ivl, y_sz, z_sz); // chop off z-part
@ -680,12 +709,12 @@ namespace polysat {
}
else if (!y_ivl.is_empty()) {
// proper interval
verbose_stream() << "=> v" << y << " not in " << y_ivl << "\n";
auto sc = ~cs.ult(c.var(y) - y_ivl.lo(), y_ivl.hi() - y_ivl.lo());
verbose_stream() << "=> v" << w << "[" << y_sz << "] not in " << y_ivl << "\n";
auto sc = ~cs.ult(w_shift * (c.var(w) - y_ivl.lo()), w_shift * (y_ivl.hi() - y_ivl.lo()));
dependency_vector deps;
deps.append(e_deps); // explains e
deps.push_back(offset_claim{m_var, slice}); // explains v[...] = y
auto exp = c.propagate(sc, deps);
auto exp = c.propagate(sc, deps, "propagate from containing slice (general)");
if (c.inconsistent()) {
verbose_stream() << "XXX1 inconsistent " << sc << " " << exp << "\n";
}
@ -710,8 +739,8 @@ namespace polysat {
}
else if (!y_ivl.is_empty()) {
// proper interval
verbose_stream() << "=> v" << y << " not in " << y_ivl << "\n";
auto sc = ~cs.ult(c.var(y) - y_ivl.lo(), y_ivl.hi() - y_ivl.lo());
verbose_stream() << "=> v" << w << "[" << y_sz << "] not in " << y_ivl << "\n";
auto sc = ~cs.ult(w_shift * (c.var(w) - y_ivl.lo()), w_shift * (y_ivl.hi() - y_ivl.lo()));
dependency_vector deps;
deps.append(e_deps); // explains e
deps.push_back(offset_claim{m_var, slice}); // explains v[...] = y
@ -719,7 +748,7 @@ namespace polysat {
deps.push_back(fixed_claim{m_var, x_value, y_sz + z_sz, x_sz}); // v[upper] = x_value
if (z_sz > 0)
deps.push_back(fixed_claim{m_var, z_value, 0, z_sz}); // v[lower] = z_value
auto exp = c.propagate(sc, deps);
auto exp = c.propagate(sc, deps, "propagate from containing slice (fixed)");
if (c.inconsistent()) {
verbose_stream() << "XXX2 inconsistent " << sc << " " << exp << "\n";
}