3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 17:15:31 +00:00

remove v1 code

This commit is contained in:
Nikolaj Bjorner 2023-12-25 11:32:39 -08:00
parent f0c23f9b7b
commit 4f60dd7f3a
2 changed files with 19 additions and 342 deletions

View file

@ -101,7 +101,7 @@ namespace polysat {
#endif
}
void viable::init_overlays(pvar v) {
void viable::init_overlaps(pvar v) {
m_widths.reset();
m_overlaps.reset();
c.get_bitvector_suffixes(v, m_overlaps);
@ -121,320 +121,36 @@ namespace polysat {
LOG("widths: " << m_widths);
}
lbool viable::find_viable(pvar v, rational& lo, rational& hi) {
lbool viable::next_viable(pvar, rational& val1) {
return l_undef;
}
lbool viable::find_viable(pvar v, rational& val1, rational& val2) {
m_explain.reset();
m_fixed_bits.reset(v);
init_overlays(v);
return l_undef;
init_overlaps(v);
rational const& max_value = c.var2pdd(v).max_value();
lbool r = find_on_layers(v, m_widths, m_overlaps, rational::zero(), max_value, lo);
val1 = 0;
lbool r = next_viable(v, val1);
if (r != l_true)
return r;
if (lo == max_value) {
hi = lo;
if (val1 == max_value) {
val2 = val1;
return l_true;
}
val2 = val1 + 1;
r = find_on_layers(v, m_widths, m_overlaps, lo + 1, max_value, hi);
r = next_viable(v, val2);
if (r != l_false)
return r;
hi = lo;
val2 = val1;
return l_true;
}
// l_true ... found viable value
// l_false ... no viable value in [to_cover_lo;to_cover_hi[
// l_undef ... out of resources
lbool viable::find_on_layers(
pvar const v,
unsigned_vector const& widths,
offset_slices const& overlaps,
rational const& to_cover_lo,
rational const& to_cover_hi,
rational& val) {
ptr_vector<entry> refine_todo;
// max number of interval refinements before falling back to the univariate solver
unsigned const refinement_budget = 100;
unsigned refinements = refinement_budget;
unsigned explain_size = m_explain.size();
while (refinements--) {
m_explain.shrink(explain_size);
lbool result = find_on_layer(v, widths.size() - 1, widths, overlaps, to_cover_lo, to_cover_hi, val, refine_todo);
// store bit-intervals we have used
for (entry* e : refine_todo)
intersect(v, e);
refine_todo.clear();
if (result != l_true)
return l_false;
// overlaps are sorted by variable size in descending order
// start refinement on smallest variable
// however, we probably should rotate to avoid getting stuck in refinement loop on a 'bad' constraint
bool refined = false;
#if 0
for (unsigned i = overlaps.size(); i-- > 0; ) {
pvar x = overlaps[i].v;
rational const& mod_value = c.var2pdd(x).two_to_N();
rational x_val = mod(val, mod_value);
if (!refine_viable(x, x_val)) {
refined = true;
break;
}
}
#endif
if (!refined)
return l_true;
}
return l_undef;
}
// find viable values in half-open interval [to_cover_lo;to_cover_hi[ w.r.t. unit intervals on the given layer
//
// Returns:
// - l_true ... found value that is viable w.r.t. units and fixed bits
// - l_false ... found conflict
// - l_undef ... found no viable value in target interval [to_cover_lo;to_cover_hi[
lbool viable::find_on_layer(
pvar const v,
unsigned const w_idx,
unsigned_vector const& widths,
offset_slices const& overlaps,
rational const& to_cover_lo,
rational const& to_cover_hi,
rational& val,
ptr_vector<entry>& refine_todo) {
unsigned const w = widths[w_idx];
rational const& mod_value = rational::power_of_two(w);
unsigned const first_relevant_for_conflict = m_explain.size();
LOG("layer " << w << " bits, to_cover: [" << to_cover_lo << "; " << to_cover_hi << "[");
SASSERT(0 <= to_cover_lo);
SASSERT(0 <= to_cover_hi);
SASSERT(to_cover_lo < mod_value);
SASSERT(to_cover_hi <= mod_value); // full interval if to_cover_hi == mod_value
SASSERT(to_cover_lo != to_cover_hi); // non-empty search domain (but it may wrap)
// TODO: refinement of eq/diseq should happen only on the correct layer: where (one of) the coefficient(s) are odd
// for refinement, we have to choose an entry that is violated, but if there are multiple, we can choose the one on smallest domain (lowest bit-width).
// (by maintaining descending order by bit-width; and refine first that fails).
// but fixed-bit-refinement is cheap and could be done during the search.
// when we arrive at a hole the possibilities are:
// 1) go to lower bitwidth
// 2) refinement of some eq/diseq constraint (if one is violated at that point) -- defer this until point is viable for all layers and fixed bits.
// 3) refinement by using bit constraints? -- TODO: do this during search (another interval check after/before the entry_cursors)
// 4) (point is actually feasible)
// a complication is that we have to iterate over multiple lists of intervals.
// might be useful to merge them upfront to simplify the remainder of the algorithm?
// (non-trivial since prev/next pointers are embedded into entries and lists are updated by refinement)
struct entry_cursor {
entry* cur;
// entry* first;
// entry* last;
};
// find relevant interval lists
svector<entry_cursor> ecs;
for (auto const& [x, offset] : overlaps) {
if (c.size(x) < w) // note that overlaps are sorted by variable size descending
break;
if (entry* e = m_units[x].get_entries(w)) {
display_all(std::cerr << "units for width " << w << ":\n", 0, e, "\n");
entry_cursor ec;
ec.cur = e; // TODO: e->prev() probably makes it faster when querying 0 (can often save going around the interval list once)
// ec.first = nullptr;
// ec.last = nullptr;
ecs.push_back(ec);
}
}
rational const to_cover_len = r_interval::len(to_cover_lo, to_cover_hi, mod_value);
val = to_cover_lo;
rational progress; // = 0
SASSERT(progress.is_zero());
while (true) {
while (true) {
entry* e = nullptr;
// try to make progress using any of the relevant interval lists
for (entry_cursor& ec : ecs) {
// advance until current value 'val'
auto const [n, n_contains_val] = find_value(val, ec.cur);
// display_one(std::cerr << "found entry n: ", 0, n) << "\n";
// LOG("n_contains_val: " << n_contains_val << " val = " << val);
ec.cur = n;
if (n_contains_val) {
e = n;
break;
}
}
#if 0
// when we cannot make progress by existing intervals any more, try interval from fixed bits
if (!e) {
e = refine_bits<true>(v, val, w, fbi);
if (e) {
refine_todo.push_back(e);
display_one(std::cerr << "found entry by bits: ", 0, e) << "\n";
}
}
#endif
// no more progress on current layer
if (!e)
break;
m_explain.push_back(e);
if (e->interval.is_full()) {
m_explain.reset();
m_explain.push_back(e); // full interval e -> all other intervals are subsumed/irrelevant
set_conflict_by_interval(v, w, m_explain, 0);
return l_false;
}
SASSERT(e->interval.currently_contains(val));
rational const& new_val = e->interval.hi_val();
rational const dist = distance(val, new_val, mod_value);
SASSERT(dist > 0);
val = new_val;
progress += dist;
LOG("val: " << val << " progress: " << progress);
if (progress >= mod_value) {
// covered the whole domain => conflict
set_conflict_by_interval(v, w, m_explain, first_relevant_for_conflict);
return l_false;
}
if (progress >= to_cover_len) {
// we covered the hole left at larger bit-width
// TODO: maybe we want to keep trying a bit longer to see if we can cover the whole domain. or maybe only if we enter this layer multiple times.
return l_undef;
}
// (another way to compute 'progress')
SASSERT_EQ(progress, distance(to_cover_lo, val, mod_value));
}
// no more progress
// => 'val' is viable w.r.t. unit intervals until current layer
if (!w_idx) {
// we are at the lowest layer
// => found viable value w.r.t. unit intervals and fixed bits
return l_true;
}
// find next covered value
rational next_val = to_cover_hi;
for (entry_cursor& ec : ecs) {
// each ec.cur is now the next interval after 'lo'
rational const& n = ec.cur->interval.lo_val();
SASSERT(r_interval::contains(ec.cur->prev()->interval.hi_val(), n, val));
if (distance(val, n, mod_value) < distance(val, next_val, mod_value))
next_val = n;
}
#if 0
if (entry* e = refine_bits<false>(v, next_val, w, fbi)) {
refine_todo.push_back(e);
rational const& n = e->interval.lo_val();
SASSERT(distance(val, n, mod_value) < distance(val, next_val, mod_value));
next_val = n;
}
SASSERT(!refine_bits<true>(v, val, w, fbi));
#endif
SASSERT(val != next_val);
unsigned const lower_w = widths[w_idx - 1];
rational const lower_mod_value = rational::power_of_two(lower_w);
rational lower_cover_lo, lower_cover_hi;
if (distance(val, next_val, mod_value) >= lower_mod_value) {
// NOTE: in this case we do not get the first viable value, but the one with smallest value in the lower bits.
// this is because we start the search in the recursive case at 0.
// if this is a problem, adapt to lower_cover_lo = mod(val, lower_mod_value), lower_cover_hi = ...
lower_cover_lo = 0;
lower_cover_hi = lower_mod_value;
rational a;
lbool result = find_on_layer(v, w_idx - 1, widths, overlaps, lower_cover_lo, lower_cover_hi, a, refine_todo);
VERIFY(result != l_undef);
if (result == l_false) {
SASSERT(c.inconsistent());
return l_false; // conflict
}
SASSERT(result == l_true);
// replace lower bits of 'val' by 'a'
rational const val_lower = mod(val, lower_mod_value);
val = val - val_lower + a;
if (a < val_lower)
a += lower_mod_value;
LOG("distance(val, cover_hi) = " << distance(val, to_cover_hi, mod_value));
LOG("distance(next_val, cover_hi) = " << distance(next_val, to_cover_hi, mod_value));
SASSERT(distance(val, to_cover_hi, mod_value) >= distance(next_val, to_cover_hi, mod_value));
return l_true;
}
lower_cover_lo = mod(val, lower_mod_value);
lower_cover_hi = mod(next_val, lower_mod_value);
rational a;
lbool result = find_on_layer(v, w_idx - 1, widths, overlaps, lower_cover_lo, lower_cover_hi, a, refine_todo);
if (result == l_false) {
SASSERT(c.inconsistent());
return l_false; // conflict
}
// replace lower bits of 'val' by 'a'
rational const dist = distance(lower_cover_lo, a, lower_mod_value);
val += dist;
progress += dist;
LOG("distance(val, cover_hi) = " << distance(val, to_cover_hi, mod_value));
LOG("distance(next_val, cover_hi) = " << distance(next_val, to_cover_hi, mod_value));
SASSERT(distance(val, to_cover_hi, mod_value) >= distance(next_val, to_cover_hi, mod_value));
if (result == l_true)
return l_true; // done
SASSERT(result == l_undef);
if (progress >= mod_value) {
// covered the whole domain => conflict
set_conflict_by_interval(v, w, m_explain, first_relevant_for_conflict);
return l_false;
}
if (progress >= to_cover_len) {
// we covered the hole left at larger bit-width
return l_undef;
}
}
UNREACHABLE();
return l_undef;
}
void viable::set_conflict_by_interval(pvar v, unsigned w, ptr_vector<entry>& intervals, unsigned first_interval) {
SASSERT(!intervals.empty());
SASSERT(first_interval < intervals.size());
}
bool viable::set_conflict_by_interval_rec(pvar v, unsigned w, entry** intervals, unsigned num_intervals, bool& create_lemma, uint_set& vars_to_explain) {
return true;
}
/*
* Explain why the current variable is not viable or signleton.
*/
@ -634,16 +350,6 @@ namespace polysat {
return true;
}
void viable::log() {
for (pvar v = 0; v < m_units.size(); ++v)
log(v);
}
void viable::log(pvar v) {
//
}
viable::layer& viable::layers::ensure_layer(unsigned bit_width) {
for (unsigned i = 0; i < m_layers.size(); ++i) {
layer& l = m_layers[i];

View file

@ -94,7 +94,7 @@ namespace polysat {
};
class layers final {
svector<layer> m_layers;
svector<layer> m_layers;
public:
svector<layer> const& get_layers() const { return m_layers; }
layer& ensure_layer(unsigned bit_width);
@ -121,8 +121,6 @@ namespace polysat {
std::ostream& display_one(std::ostream& out, pvar v, entry const* e) const;
std::ostream& display_all(std::ostream& out, pvar v, entry const* e, char const* delimiter = "") const;
void log();
void log(pvar v);
struct pop_viable_trail;
void pop_viable(entry* e, entry_kind k);
@ -133,43 +131,16 @@ namespace polysat {
bool intersect(pvar v, entry* e);
lbool find_viable(pvar v, rational& lo, rational& hi);
lbool find_viable(pvar v, rational& val1, rational& val2);
lbool find_on_layers(
pvar v,
unsigned_vector const& widths,
offset_slices const& overlaps,
rational const& to_cover_lo,
rational const& to_cover_hi,
rational& out_val);
lbool find_on_layer(
pvar v,
unsigned w_idx,
unsigned_vector const& widths,
offset_slices const& overlaps,
rational const& to_cover_lo,
rational const& to_cover_hi,
rational& out_val,
ptr_vector<entry>& refine_todo);
void set_conflict_by_interval(pvar v, unsigned w, ptr_vector<entry>& intervals, unsigned first_interval);
bool set_conflict_by_interval_rec(pvar v, unsigned w, entry** intervals, unsigned num_intervals, bool& create_lemma, uint_set& vars_to_explain);
std::pair<entry*, bool> find_value(rational const& val, entry* entries) {
throw default_exception("fine_value nyi");
}
lbool next_viable(pvar, rational& val1);
fixed_bits m_fixed_bits;
void init_fixed_bits(pvar v);
unsigned_vector m_widths;
offset_slices m_overlaps;
void init_overlays(pvar v);
offset_slices m_overlaps;
void init_overlaps(pvar v);
public:
viable(core& c);