3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-27 08:28:44 +00:00
This commit is contained in:
Nikolaj Bjorner 2024-01-04 10:54:02 -08:00
parent f71219a9d0
commit 7b0c04a3e8
8 changed files with 67 additions and 48 deletions

View file

@ -216,17 +216,6 @@ namespace polysat {
// break; // break;
} }
switch (m_monomials.refine()) {
case l_true:
break;
case l_false:
TRACE("bv", tout << "refine\n");
return sat::check_result::CR_CONTINUE;
case l_undef:
r = l_undef;
break;
}
saturation saturate(*this); saturation saturate(*this);
switch (saturate()) { switch (saturate()) {
case l_true: case l_true:
@ -239,6 +228,17 @@ namespace polysat {
break; break;
} }
switch (m_monomials.refine()) {
case l_true:
break;
case l_false:
TRACE("bv", tout << "refine\n");
return sat::check_result::CR_CONTINUE;
case l_undef:
r = l_undef;
break;
}
switch (m_monomials.bit_blast()) { switch (m_monomials.bit_blast()) {
case l_true: case l_true:
break; break;

View file

@ -59,19 +59,21 @@ namespace polysat {
if (m_to_refine.empty()) if (m_to_refine.empty())
return l_true; return l_true;
shuffle(m_to_refine.size(), m_to_refine.data(), c.rand()); shuffle(m_to_refine.size(), m_to_refine.data(), c.rand());
if (any_of(m_to_refine, [&](auto i) { return prefix_overflow(m_monomials[i]); }))
return l_false;
if (any_of(m_to_refine, [&](auto i) { return mul0(m_monomials[i]); })) if (any_of(m_to_refine, [&](auto i) { return mul0(m_monomials[i]); }))
return l_false; return l_false;
if (any_of(m_to_refine, [&](auto i) { return mul1(m_monomials[i]); })) if (any_of(m_to_refine, [&](auto i) { return mul1(m_monomials[i]); }))
return l_false; return l_false;
if (any_of(m_to_refine, [&](auto i) { return non_overflow_unit(m_monomials[i]); })) if (any_of(m_to_refine, [&](auto i) { return non_overflow_unit(m_monomials[i]); }))
return l_false; return l_false;
if (any_of(m_to_refine, [&](auto i) { return non_overflow_zero(m_monomials[i]); })) if (any_of(m_to_refine, [&](auto i) { return non_overflow_zero(m_monomials[i]); }))
return l_false; return l_false;
if (any_of(m_to_refine, [&](auto i) { return parity0(m_monomials[i]); })) if (false && any_of(m_to_refine, [&](auto i) { return parity0(m_monomials[i]); }))
return l_false; return l_false;
if (any_of(m_to_refine, [&](auto i) { return parity(m_monomials[i]); })) if (false && any_of(m_to_refine, [&](auto i) { return parity(m_monomials[i]); }))
return l_false;
if (any_of(m_to_refine, [&](auto i) { return prefix_overflow(m_monomials[i]); }))
return l_false; return l_false;
if (any_of(m_to_refine, [&](auto i) { return non_overflow_monotone(m_monomials[i]); })) if (any_of(m_to_refine, [&](auto i) { return non_overflow_monotone(m_monomials[i]); }))
return l_false; return l_false;
@ -153,15 +155,15 @@ namespace polysat {
} }
constraint_or_dependency_vector cs; constraint_or_dependency_vector cs;
pdd offset = c.value(rational(1), mon.num_bits()); pdd offset = c.value(rational(1), mon.num_bits());
if (free_index == UINT_MAX)
free_index = c.rand()() % mon.size();
for (unsigned j = mon.size(); j-- > 0; ) { for (unsigned j = mon.size(); j-- > 0; ) {
if (j != free_index) { if (j != free_index) {
cs.push_back(~C.eq(mon.args[j], mon.arg_vals[j])); cs.push_back(~C.eq(mon.args[j], mon.arg_vals[j]));
offset *= mon.arg_vals[j]; offset *= mon.arg_vals[j];
} }
} }
if (free_index == UINT_MAX)
cs.push_back(C.eq(mon.var, offset));
else
cs.push_back(C.eq(mon.var, offset * mon.args[free_index])); cs.push_back(C.eq(mon.var, offset * mon.args[free_index]));
return c.add_axiom("p = k => p * q = k * q", cs, true); return c.add_axiom("p = k => p * q = k * q", cs, true);

View file

@ -58,13 +58,13 @@ namespace polysat {
void saturation::resolve(pvar v, inequality const& i) { void saturation::resolve(pvar v, inequality const& i) {
if (c.size(v) != i.lhs().power_of_2()) if (c.size(v) != i.lhs().power_of_2())
return; return;
if (!c.inconsistent()) if (false && !c.inconsistent())
try_ugt_x(v, i); try_ugt_x(v, i);
if (!c.inconsistent()) if (false && !c.inconsistent())
try_ugt_y(v, i); try_ugt_y(v, i);
if (!c.inconsistent()) if (false && !c.inconsistent())
try_ugt_z(v, i); try_ugt_z(v, i);
if (!c.inconsistent()) if (false && !c.inconsistent())
try_eq_resolve(v, i); try_eq_resolve(v, i);
} }

View file

@ -358,7 +358,7 @@ namespace polysat {
auto p = c.subst(lhs()); auto p = c.subst(lhs());
auto q = c.subst(rhs()); auto q = c.subst(rhs());
auto& C = c.cs(); auto& C = c.cs();
if (sign && !lhs().is_val() && !rhs().is_val()) { if (false && sign && !lhs().is_val() && !rhs().is_val()) {
c.add_axiom("lhs > rhs ==> -1 > rhs", { d, C.ult(rhs(), -1) }, false); c.add_axiom("lhs > rhs ==> -1 > rhs", { d, C.ult(rhs(), -1) }, false);
c.add_axiom("lhs > rhs ==> lhs > 0", { d, C.ult(0, lhs()) }, false); c.add_axiom("lhs > rhs ==> lhs > 0", { d, C.ult(0, lhs()) }, false);
} }

View file

@ -89,7 +89,7 @@ namespace polysat {
m_num_bits = c.size(v); m_num_bits = c.size(v);
m_fixed_bits.reset(v); m_fixed_bits.reset(v);
init_overlaps(v); init_overlaps(v);
m_start = lo; m_conflict = false;
// verbose_stream() << "find viable v" << v << " starting with " << lo << "\n"; // verbose_stream() << "find viable v" << v << " starting with " << lo << "\n";
@ -97,18 +97,15 @@ namespace polysat {
auto n = find_overlap(lo); auto n = find_overlap(lo);
if (m_conflict)
return find_t::empty;
if (!n) { if (!n) {
if (refine_disequal_lin(v, lo) && if (refine_disequal_lin(v, lo) &&
refine_equal_lin(v, lo)) refine_equal_lin(v, lo))
return find_t::multiple; return find_t::multiple;
++rounds; ++rounds;
continue;
} }
update_value_to_high(lo, n);
m_explain.push_back({ n, lo });
if (is_conflict())
return find_t::empty;
} }
return find_t::resource_out; return find_t::resource_out;
@ -137,15 +134,23 @@ namespace polysat {
VERIFY(m_fixed_bits.next(val)); VERIFY(m_fixed_bits.next(val));
} }
entry* last = nullptr;
for (auto const& [w, offset] : m_overlaps) { for (auto const& [w, offset] : m_overlaps) {
for (auto& layer : m_units[w].get_layers()) { for (auto& layer : m_units[w].get_layers()) {
entry* e = find_overlap(w, layer, val); entry* e = find_overlap(w, layer, val);
if (e) if (!e)
return e; continue;
} last = e;
} update_value_to_high(val, e);
m_explain.push_back({ e, val });
if (is_conflict()) {
m_conflict = true;
return nullptr; return nullptr;
} }
}
}
return last;
}
viable::entry* viable::find_overlap(pvar w, layer& l, rational& val) { viable::entry* viable::find_overlap(pvar w, layer& l, rational& val) {
if (!l.entries) if (!l.entries)
@ -521,34 +526,43 @@ namespace polysat {
* *
* - 2^kx \not\in [lo, hi[, * - 2^kx \not\in [lo, hi[,
* - 2^k'y \not\in [lo', hi'[ * - 2^k'y \not\in [lo', hi'[
* - a value v such that
* - 2^kv \not\in [lo, hi[
* - 2^k'v \in [lo', hi'[
* - hi \in ] (v - 1) * 2^{bw - ebw} ; v * 2^{bw - ebw} ]
* *
* Where: * Where:
* - w is the width of x, w' the width of y * - bw is the width of x, aw the width of y
* - bw is the bit-width of x, bw' the bit-width of y * - ebw is the bit-width of x, abw the bit-width of y
* - k = w - bwx, k' = w' - bw' * - k = bw - ebw, k' = aw - abw
* *
* We want to encode the constraint that (2^k' hi)[w'] in [lo', hi'[ * We want to encode the constraint that (2^k' hi)[w'] in [lo', hi'[
* *
* Note that x in [lo, hi[ <=> x - lo < hi - lo * Note that x in [lo, hi[ <=> x - lo < hi - lo
* If k' = 0, w' = w, there is nothing to do. * If bw = aw, ebw = abw there is nothing else to do.
* - hi \in [lo', hi'[
* *
* TODO - describe. * If bw != aw or aw < bw:
* - hi \in ] (v - 1) * 2^{bw - ebw} ; v * 2^{bw - ebw} ]
* - hi := v mod aw
*
* - 2^k'hi \in [lo', hi'[
* *
*/ */
void viable::explain_overlap(explanation const& e, explanation const& after, dependency_vector& deps) { void viable::explain_overlap(explanation const& e, explanation const& after, dependency_vector& deps) {
auto bw = c.size(e.e->var); auto bw = c.size(e.e->var);
auto ebw = e.e->bit_width; auto ebw = e.e->bit_width;
auto bw_after = c.size(after.e->var); auto aw = c.size(after.e->var);
auto abw = after.e->bit_width; auto abw = after.e->bit_width;
auto t = e.e->interval.hi(); auto t = e.e->interval.hi();
auto lo = after.e->interval.lo(); auto lo = after.e->interval.lo();
auto hi = after.e->interval.hi(); auto hi = after.e->interval.hi();
SASSERT(abw <= bw_after); SASSERT(abw <= aw);
SASSERT(ebw <= bw); SASSERT(ebw <= bw);
if (ebw < bw || bw_after != bw) { if (ebw < bw || aw != bw) {
auto const& p2b = rational::power_of_two(bw); auto const& p2b = rational::power_of_two(bw);
auto const& p2eb = rational::power_of_two(bw - ebw); auto const& p2eb = rational::power_of_two(bw - ebw);
auto vhi = c.value(mod(e.value * p2eb + 1, p2b), bw); auto vhi = c.value(mod(e.value * p2eb + 1, p2b), bw);
@ -563,11 +577,11 @@ namespace polysat {
if (!sc.is_always_true()) if (!sc.is_always_true())
deps.push_back(c.propagate(sc, c.explain_eval(sc))); deps.push_back(c.propagate(sc, c.explain_eval(sc)));
t.reset(lo.manager()); t.reset(lo.manager());
t = c.value(mod(e.value, rational::power_of_two(bw_after)), bw_after); t = c.value(mod(e.value, rational::power_of_two(aw)), aw);
} }
if (abw < bw_after) if (abw < aw)
t *= rational::power_of_two(bw_after - abw); t *= rational::power_of_two(aw - abw);
auto sc = cs.ult(t - lo, hi - lo); auto sc = cs.ult(t - lo, hi - lo);
SASSERT(!sc.is_always_false()); SASSERT(!sc.is_always_false());

View file

@ -135,7 +135,7 @@ namespace polysat {
pvar m_var = null_var; pvar m_var = null_var;
rational m_start; bool m_conflict = false;
unsigned m_num_bits = 0; unsigned m_num_bits = 0;
fixed_bits m_fixed_bits; fixed_bits m_fixed_bits;
offset_slices m_overlaps; offset_slices m_overlaps;

View file

@ -658,6 +658,7 @@ namespace polysat {
auto eq0 = eq_internalize(e, bv.mk_numeral(0, sz_e)); auto eq0 = eq_internalize(e, bv.mk_numeral(0, sz_e));
auto gelo = mk_literal(bv.mk_ule(bv.mk_numeral(rational::power_of_two(lo), sz_x), x)); auto gelo = mk_literal(bv.mk_ule(bv.mk_numeral(rational::power_of_two(lo), sz_x), x));
auto name = "extract"; auto name = "extract";
verbose_stream() << "extract axiom " << mk_pp(e, m) << " " << eq0 << " " << s().value(eq0) << " " << gelo << " " << s().value(gelo) << "\n";
add_axiom(name, { eq0, gelo }); add_axiom(name, { eq0, gelo });
if (hi + 1 == sz_e) if (hi + 1 == sz_e)
add_axiom(name, { ~eq0, ~gelo }); add_axiom(name, { ~eq0, ~gelo });

View file

@ -346,6 +346,7 @@ namespace polysat {
return false; return false;
} }
TRACE("bv", tout << name << ": "; for (auto lit : lits) tout << ctx.literal2expr(lit) << " "; tout << "\n"); TRACE("bv", tout << name << ": "; for (auto lit : lits) tout << ctx.literal2expr(lit) << " "; tout << "\n");
IF_VERBOSE(1, verbose_stream() << name << ": "; for (auto lit : lits) verbose_stream() << ctx.literal2expr(lit) << " "; verbose_stream() << "\n");
validate_axiom(lits); validate_axiom(lits);
s().add_clause(lits.size(), lits.data(), sat::status::th(is_redundant, get_id(), hint)); s().add_clause(lits.size(), lits.data(), sat::status::th(is_redundant, get_id(), hint));
return true; return true;
@ -367,6 +368,7 @@ namespace polysat {
lits.push_back(lit); lits.push_back(lit);
} }
validate_axiom(lits); validate_axiom(lits);
IF_VERBOSE(1, verbose_stream() << name << ": "; for (auto lit : lits) verbose_stream() << ctx.literal2expr(lit) << " "; verbose_stream() << "\n");
s().add_clause(lits.size(), lits.data(), sat::status::th(is_redundant, get_id(), hint)); s().add_clause(lits.size(), lits.data(), sat::status::th(is_redundant, get_id(), hint));
} }