mirror of
https://github.com/Z3Prover/z3
synced 2025-06-08 15:13:23 +00:00
working on viable explanations
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
b706434282
commit
21236dc80a
5 changed files with 53 additions and 23 deletions
|
@ -1860,14 +1860,11 @@ namespace dd {
|
||||||
return (*this) * rational::power_of_two(n);
|
return (*this) * rational::power_of_two(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pdd::has_unit(pdd& x, pdd& rest) const {
|
bool pdd::has_unit(pdd& x) const {
|
||||||
if (is_val())
|
|
||||||
return false;
|
|
||||||
pdd r = *this;
|
pdd r = *this;
|
||||||
while (!r.is_val()) {
|
while (!r.is_val()) {
|
||||||
if (r.hi().is_one()) {
|
if (r.hi().is_one()) {
|
||||||
x = m->mk_var(r.var());
|
x = m->mk_var(r.var());
|
||||||
rest = *this - x;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
r = r.lo();
|
r = r.lo();
|
||||||
|
|
|
@ -441,7 +441,7 @@ namespace dd {
|
||||||
bool is_unary() const { return !is_val() && lo().is_zero() && hi().is_val(); }
|
bool is_unary() const { return !is_val() && lo().is_zero() && hi().is_val(); }
|
||||||
bool is_offset() const { return !is_val() && lo().is_val() && hi().is_one(); }
|
bool is_offset() const { return !is_val() && lo().is_val() && hi().is_one(); }
|
||||||
bool is_binary() const { return m->is_binary(root); }
|
bool is_binary() const { return m->is_binary(root); }
|
||||||
bool has_unit(pdd& x, pdd& rest) const;
|
bool has_unit(pdd& x) const;
|
||||||
bool is_monomial() const { return m->is_monomial(root); }
|
bool is_monomial() const { return m->is_monomial(root); }
|
||||||
bool is_univariate() const { return m->is_univariate(root); }
|
bool is_univariate() const { return m->is_univariate(root); }
|
||||||
bool is_univariate_in(unsigned v) const { return m->is_univariate_in(root, v); }
|
bool is_univariate_in(unsigned v) const { return m->is_univariate_in(root, v); }
|
||||||
|
|
|
@ -84,6 +84,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
find_t viable::find_viable(pvar v, rational& lo) {
|
find_t viable::find_viable(pvar v, rational& lo) {
|
||||||
|
verbose_stream() << "find viable v" << v << " starting with " << lo << "\n";
|
||||||
rational hi;
|
rational hi;
|
||||||
switch (find_viable(v, lo, hi)) {
|
switch (find_viable(v, lo, hi)) {
|
||||||
case l_true:
|
case l_true:
|
||||||
|
@ -103,7 +104,9 @@ namespace polysat {
|
||||||
|
|
||||||
lbool viable::find_viable(pvar v, rational& val1, rational& val2) {
|
lbool viable::find_viable(pvar v, rational& val1, rational& val2) {
|
||||||
m_explain.reset();
|
m_explain.reset();
|
||||||
|
m_ineqs.reset();
|
||||||
m_var = v;
|
m_var = v;
|
||||||
|
m_value = nullptr;
|
||||||
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);
|
||||||
|
@ -129,6 +132,9 @@ namespace polysat {
|
||||||
else
|
else
|
||||||
val2 = val1 + 1;
|
val2 = val1 + 1;
|
||||||
|
|
||||||
|
// instead of m_value use linked list of entries?
|
||||||
|
m_value = alloc(pdd, c.value(val2, m_num_bits));
|
||||||
|
|
||||||
r = next_viable(val2);
|
r = next_viable(val2);
|
||||||
|
|
||||||
if (r != l_false)
|
if (r != l_false)
|
||||||
|
@ -231,14 +237,29 @@ namespace polysat {
|
||||||
break;
|
break;
|
||||||
// TODO check if admitted: layer.entries = e;
|
// TODO check if admitted: layer.entries = e;
|
||||||
m_explain.push_back(e);
|
m_explain.push_back(e);
|
||||||
|
|
||||||
if (e->interval.is_full())
|
if (e->interval.is_full())
|
||||||
return l_false;
|
return l_false;
|
||||||
auto hi = e->interval.hi_val();
|
|
||||||
if (wrapped && start <= hi)
|
auto hi_val = e->interval.hi_val();
|
||||||
|
auto lo_val = e->interval.lo_val();
|
||||||
|
auto hi = e->interval.hi();
|
||||||
|
auto lo = e->interval.lo();
|
||||||
|
|
||||||
|
|
||||||
|
if (!m_value)
|
||||||
|
m_value = alloc(pdd, lo);
|
||||||
|
|
||||||
|
m_ineqs.push_back({ *m_value, lo, hi });
|
||||||
|
|
||||||
|
if (wrapped && start <= hi_val) {
|
||||||
|
verbose_stream() << "WRAPPED\n";
|
||||||
return l_false;
|
return l_false;
|
||||||
if (hi < e->interval.lo_val())
|
}
|
||||||
|
if (hi_val < lo_val)
|
||||||
wrapped = true;
|
wrapped = true;
|
||||||
val1 = hi;
|
val1 = hi_val;
|
||||||
|
m_value = alloc(pdd, hi);
|
||||||
SASSERT(val1 < p2b);
|
SASSERT(val1 < p2b);
|
||||||
}
|
}
|
||||||
SASSERT(val1 < p2b);
|
SASSERT(val1 < p2b);
|
||||||
|
@ -537,6 +558,13 @@ namespace polysat {
|
||||||
auto const& [sc, d, value] = c.m_constraint_index[index.id];
|
auto const& [sc, d, value] = c.m_constraint_index[index.id];
|
||||||
result.push_back(d);
|
result.push_back(d);
|
||||||
}
|
}
|
||||||
|
for (auto [t, lo, hi] : m_ineqs) {
|
||||||
|
auto sc = cs.ult(t - lo, hi - lo);
|
||||||
|
verbose_stream() << "Overlap " << t << " in [" << lo << ", " << hi << "[: " << sc << "\n";
|
||||||
|
if (!sc.is_always_true())
|
||||||
|
result.push_back(c.propagate(sc, c.explain_eval(sc)));
|
||||||
|
}
|
||||||
|
|
||||||
result.append(m_fixed_bits.explain());
|
result.append(m_fixed_bits.explain());
|
||||||
TRACE("bv", tout << "viable-explain v" << m_var << " - " << result.size() << "\n");
|
TRACE("bv", tout << "viable-explain v" << m_var << " - " << result.size() << "\n");
|
||||||
return result;
|
return result;
|
||||||
|
@ -656,6 +684,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
if (ne->interval.is_full()) {
|
if (ne->interval.is_full()) {
|
||||||
m_explain.reset();
|
m_explain.reset();
|
||||||
|
m_ineqs.reset();
|
||||||
m_explain.push_back(ne);
|
m_explain.push_back(ne);
|
||||||
m_fixed_bits.reset();
|
m_fixed_bits.reset();
|
||||||
m_var = v;
|
m_var = v;
|
||||||
|
|
|
@ -85,11 +85,15 @@ namespace polysat {
|
||||||
entry* get_entries(unsigned bit_width) const { layer const* l = get_layer(bit_width); return l ? l->entries : nullptr; }
|
entry* get_entries(unsigned bit_width) const { layer const* l = get_layer(bit_width); return l ? l->entries : nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// short for t in [lo,hi[
|
||||||
|
struct interval_member {
|
||||||
|
pdd t, lo, hi;
|
||||||
|
};
|
||||||
ptr_vector<entry> m_alloc;
|
ptr_vector<entry> m_alloc;
|
||||||
vector<layers> m_units; // set of viable values based on unit multipliers, layered by bit-width in descending order
|
vector<layers> m_units; // set of viable values based on unit multipliers, layered by bit-width in descending order
|
||||||
ptr_vector<entry> m_equal_lin; // entries that have non-unit multipliers, but are equal
|
ptr_vector<entry> m_equal_lin; // entries that have non-unit multipliers, but are equal
|
||||||
ptr_vector<entry> m_diseq_lin; // entries that have distinct non-zero multipliers
|
ptr_vector<entry> m_diseq_lin; // entries that have distinct non-zero multipliers
|
||||||
|
vector<interval_member> m_ineqs; // inequalities to justify that values are not viable.
|
||||||
ptr_vector<entry> m_explain; // entries that explain the current propagation or conflict
|
ptr_vector<entry> m_explain; // entries that explain the current propagation or conflict
|
||||||
|
|
||||||
bool well_formed(entry* e);
|
bool well_formed(entry* e);
|
||||||
|
@ -126,6 +130,7 @@ namespace polysat {
|
||||||
bool refine_equal_lin(pvar v, rational const& val);
|
bool refine_equal_lin(pvar v, rational const& val);
|
||||||
|
|
||||||
pvar m_var = null_var;
|
pvar m_var = null_var;
|
||||||
|
scoped_ptr<pdd> m_value; // the current symbolid value being checked for viability.
|
||||||
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;
|
||||||
|
|
|
@ -384,24 +384,23 @@ namespace polysat {
|
||||||
expr_ref result(m);
|
expr_ref result(m);
|
||||||
switch (sc.op()) {
|
switch (sc.op()) {
|
||||||
case ckind_t::ule_t: {
|
case ckind_t::ule_t: {
|
||||||
|
|
||||||
auto p = sc.to_ule().lhs();
|
auto p = sc.to_ule().lhs();
|
||||||
auto q = sc.to_ule().rhs();
|
auto q = sc.to_ule().rhs();
|
||||||
pdd x = p, r = p;
|
pdd x = p;
|
||||||
if (q.is_zero() && p.has_unit(x, r)) {
|
if (q.is_zero() && p.has_unit(x)) {
|
||||||
auto l = pdd2expr(x);
|
auto l = pdd2expr(x);
|
||||||
auto h = pdd2expr(-r);
|
auto r = pdd2expr(x - p);
|
||||||
result = m.mk_eq(l, h);
|
result = m.mk_eq(l, r);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto l = pdd2expr(p);
|
auto l = pdd2expr(p);
|
||||||
auto h = pdd2expr(q);
|
auto r = pdd2expr(q);
|
||||||
if (p == q)
|
if (p == q)
|
||||||
result = m.mk_true();
|
result = m.mk_true();
|
||||||
else if (q.is_zero())
|
else if (q.is_zero())
|
||||||
result = m.mk_eq(l, h);
|
result = m.mk_eq(l, r);
|
||||||
else
|
else
|
||||||
result = bv.mk_ule(l, h);
|
result = bv.mk_ule(l, r);
|
||||||
}
|
}
|
||||||
if (sc.sign())
|
if (sc.sign())
|
||||||
result = m.mk_not(result);
|
result = m.mk_not(result);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue