mirror of
https://github.com/Z3Prover/z3
synced 2025-07-19 10:52:02 +00:00
update viable
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
bff51b699d
commit
70bddb35be
2 changed files with 147 additions and 24 deletions
|
@ -45,44 +45,111 @@ namespace polysat {
|
||||||
struct viable::pop_viable_trail : public trail {
|
struct viable::pop_viable_trail : public trail {
|
||||||
viable& m_s;
|
viable& m_s;
|
||||||
entry* e;
|
entry* e;
|
||||||
pvar v;
|
|
||||||
entry_kind k;
|
entry_kind k;
|
||||||
public:
|
public:
|
||||||
pop_viable_trail(viable& s, entry* e, pvar v, entry_kind k)
|
pop_viable_trail(viable& s, entry* e, entry_kind k)
|
||||||
: m_s(s), e(e), v(v), k(k) {}
|
: m_s(s), e(e), k(k) {}
|
||||||
void undo() override {
|
void undo() override {
|
||||||
m_s.pop_viable(e, v, k);
|
m_s.pop_viable(e, k);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct viable::push_viable_trail : public trail {
|
struct viable::push_viable_trail : public trail {
|
||||||
viable& m_s;
|
viable& m_s;
|
||||||
entry* e;
|
entry* e;
|
||||||
pvar v;
|
|
||||||
entry_kind k;
|
|
||||||
public:
|
public:
|
||||||
push_viable_trail(viable& s, entry* e, pvar v, entry_kind k)
|
push_viable_trail(viable& s, entry* e)
|
||||||
: m_s(s), e(e), v(v), k(k) {}
|
: m_s(s), e(e) {}
|
||||||
void undo() override {
|
void undo() override {
|
||||||
m_s.push_viable(e, v, k);
|
m_s.push_viable(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
viable::entry* viable::alloc_entry(pvar var) {
|
viable::entry* viable::alloc_entry(pvar var, unsigned constraint_index) {
|
||||||
if (m_alloc.empty())
|
if (m_alloc.empty())
|
||||||
return alloc(entry);
|
return alloc(entry);
|
||||||
auto* e = m_alloc.back();
|
auto* e = m_alloc.back();
|
||||||
e->reset();
|
e->reset();
|
||||||
e->var = var;
|
e->var = var;
|
||||||
|
e->constraint_index = constraint_index;
|
||||||
m_alloc.pop_back();
|
m_alloc.pop_back();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
find_t viable::find_viable(pvar v, rational& out_val) {
|
find_t viable::find_viable(pvar v, rational& lo) {
|
||||||
|
rational hi;
|
||||||
ensure_var(v);
|
ensure_var(v);
|
||||||
throw default_exception("nyi");
|
switch (find_viable(v, lo, hi)) {
|
||||||
|
case l_true:
|
||||||
|
return (lo == hi) ? find_t::singleton : find_t::multiple;
|
||||||
|
case l_false:
|
||||||
|
return find_t::empty;
|
||||||
|
default:
|
||||||
|
return find_t::resource_out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lbool viable::find_viable(pvar v, rational& lo, rational& hi) {
|
||||||
|
fixed_bits_info fbi;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (!collect_bit_information(v, true, fbi))
|
||||||
|
return l_false; // conflict already added
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pvar_vector overlaps;
|
||||||
|
#if 0
|
||||||
|
// TODO s.m_slicing.collect_simple_overlaps(v, overlaps);
|
||||||
|
#endif
|
||||||
|
std::sort(overlaps.begin(), overlaps.end(), [&](pvar x, pvar y) { return c.size(x) > c.size(y); });
|
||||||
|
|
||||||
|
uint_set widths_set;
|
||||||
|
// max size should always be present, regardless of whether we have intervals there (to make sure all fixed bits are considered)
|
||||||
|
widths_set.insert(c.size(v));
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
LOG("Overlaps with v" << v << ":");
|
||||||
|
for (pvar x : overlaps) {
|
||||||
|
unsigned hi, lo;
|
||||||
|
if (s.m_slicing.is_extract(x, v, hi, lo))
|
||||||
|
LOG(" v" << x << " = v" << v << "[" << hi << ":" << lo << "]");
|
||||||
|
else
|
||||||
|
LOG(" v" << x << " not extracted from v" << v << "; size " << s.size(x));
|
||||||
|
for (layer const& l : m_units[x].get_layers()) {
|
||||||
|
widths_set.insert(l.bit_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned_vector widths;
|
||||||
|
for (unsigned w : widths_set)
|
||||||
|
widths.push_back(w);
|
||||||
|
LOG("widths: " << widths);
|
||||||
|
|
||||||
|
rational const& max_value = c.var2pdd(v).max_value();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
lbool result_lo = find_on_layers(v, widths, overlaps, fbi, rational::zero(), max_value, lo);
|
||||||
|
if (result_lo == l_false)
|
||||||
|
return l_false; // conflict
|
||||||
|
if (result_lo == l_undef)
|
||||||
|
return find_viable_fallback(v, overlaps, lo, hi);
|
||||||
|
|
||||||
|
if (lo == max_value) {
|
||||||
|
hi = lo;
|
||||||
|
return l_true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbool result_hi = find_on_layers(v, widths, overlaps, fbi, lo + 1, max_value, hi);
|
||||||
|
if (result_hi == l_false)
|
||||||
|
hi = lo; // no other viable value
|
||||||
|
if (result_hi == l_undef)
|
||||||
|
return find_viable_fallback(v, overlaps, lo, hi);
|
||||||
|
#endif
|
||||||
|
return l_true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Explain why the current variable is not viable or signleton.
|
* Explain why the current variable is not viable or signleton.
|
||||||
*/
|
*/
|
||||||
|
@ -99,7 +166,7 @@ namespace polysat {
|
||||||
return;
|
return;
|
||||||
auto [sc, d] = c.m_constraint_trail[idx];
|
auto [sc, d] = c.m_constraint_trail[idx];
|
||||||
|
|
||||||
entry* ne = alloc_entry(v);
|
entry* ne = alloc_entry(v, idx);
|
||||||
if (!m_forbidden_intervals.get_interval(sc, v, *ne)) {
|
if (!m_forbidden_intervals.get_interval(sc, v, *ne)) {
|
||||||
m_alloc.push_back(ne);
|
m_alloc.push_back(ne);
|
||||||
return;
|
return;
|
||||||
|
@ -211,13 +278,13 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto create_entry = [&]() {
|
auto create_entry = [&]() {
|
||||||
c.trail().push(pop_viable_trail(*this, ne, v, entry_kind::unit_e));
|
c.trail().push(pop_viable_trail(*this, ne, entry_kind::unit_e));
|
||||||
ne->init(ne);
|
ne->init(ne);
|
||||||
return ne;
|
return ne;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto remove_entry = [&](entry* e) {
|
auto remove_entry = [&](entry* e) {
|
||||||
c.trail().push(push_viable_trail(*this, e, v, entry_kind::unit_e));
|
c.trail().push(push_viable_trail(*this, e));
|
||||||
e->remove_from(entries, e);
|
e->remove_from(entries, e);
|
||||||
e->active = false;
|
e->active = false;
|
||||||
};
|
};
|
||||||
|
@ -311,7 +378,8 @@ namespace polysat {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void viable::pop_viable(entry* e, pvar v, entry_kind k) {
|
void viable::pop_viable(entry* e, entry_kind k) {
|
||||||
|
unsigned v = e->var;
|
||||||
SASSERT(well_formed(m_units[v]));
|
SASSERT(well_formed(m_units[v]));
|
||||||
SASSERT(e->active);
|
SASSERT(e->active);
|
||||||
e->active = false;
|
e->active = false;
|
||||||
|
@ -333,15 +401,15 @@ namespace polysat {
|
||||||
m_alloc.push_back(e);
|
m_alloc.push_back(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void viable::push_viable(entry* e, pvar v, entry_kind k) {
|
void viable::push_viable(entry* e) {
|
||||||
// display_one(verbose_stream() << "Push entry: ", v, e) << "\n";
|
// display_one(verbose_stream() << "Push entry: ", v, e) << "\n";
|
||||||
|
auto v = e->var;
|
||||||
entry*& entries = m_units[v].get_layer(e)->entries;
|
entry*& entries = m_units[v].get_layer(e)->entries;
|
||||||
SASSERT(e->prev() != e || !entries);
|
SASSERT(e->prev() != e || !entries);
|
||||||
SASSERT(e->prev() != e || e->next() == e);
|
SASSERT(e->prev() != e || e->next() == e);
|
||||||
SASSERT(k == entry_kind::unit_e);
|
|
||||||
SASSERT(!e->active);
|
SASSERT(!e->active);
|
||||||
e->active = true;
|
e->active = true;
|
||||||
(void)k;
|
|
||||||
SASSERT(well_formed(m_units[v]));
|
SASSERT(well_formed(m_units[v]));
|
||||||
if (e->prev() != e) {
|
if (e->prev() != e) {
|
||||||
entry* pos = e->prev();
|
entry* pos = e->prev();
|
||||||
|
@ -358,7 +426,7 @@ namespace polysat {
|
||||||
void viable::insert(entry* e, pvar v, ptr_vector<entry>& entries, entry_kind k) {
|
void viable::insert(entry* e, pvar v, ptr_vector<entry>& entries, entry_kind k) {
|
||||||
SASSERT(well_formed(m_units[v]));
|
SASSERT(well_formed(m_units[v]));
|
||||||
|
|
||||||
c.trail().push(pop_viable_trail(*this, e, v, k));
|
c.trail().push(pop_viable_trail(*this, e, k));
|
||||||
|
|
||||||
e->init(e);
|
e->init(e);
|
||||||
if (!entries[v])
|
if (!entries[v])
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace polysat {
|
||||||
bool active = true;
|
bool active = true;
|
||||||
bool valid_for_lemma = true;
|
bool valid_for_lemma = true;
|
||||||
pvar var = null_var;
|
pvar var = null_var;
|
||||||
|
unsigned constraint_index = UINT_MAX;
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
// dll_base<entry>::init(this); // we never did this in alloc_entry either
|
// dll_base<entry>::init(this); // we never did this in alloc_entry either
|
||||||
|
@ -58,6 +59,7 @@ namespace polysat {
|
||||||
active = true;
|
active = true;
|
||||||
valid_for_lemma = true;
|
valid_for_lemma = true;
|
||||||
var = null_var;
|
var = null_var;
|
||||||
|
constraint_index = UINT_MAX;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,7 +72,7 @@ namespace polysat {
|
||||||
};
|
};
|
||||||
|
|
||||||
class layers final {
|
class layers final {
|
||||||
svector<layer> m_layers;
|
svector<layer> m_layers;
|
||||||
public:
|
public:
|
||||||
svector<layer> const& get_layers() const { return m_layers; }
|
svector<layer> const& get_layers() const { return m_layers; }
|
||||||
layer& ensure_layer(unsigned bit_width);
|
layer& ensure_layer(unsigned bit_width);
|
||||||
|
@ -81,6 +83,57 @@ 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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fixed_bits_info {
|
||||||
|
svector<lbool> fixed;
|
||||||
|
vector<vector<signed_constraint>> just_src;
|
||||||
|
vector<vector<signed_constraint>> just_side_cond;
|
||||||
|
vector<svector<pvar>> just_slicing;
|
||||||
|
|
||||||
|
bool is_empty() const {
|
||||||
|
SASSERT_EQ(fixed.empty(), just_src.empty());
|
||||||
|
SASSERT_EQ(fixed.empty(), just_side_cond.empty());
|
||||||
|
return fixed.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_empty_at(unsigned i) const {
|
||||||
|
return fixed[i] == l_undef && just_src[i].empty() && just_side_cond[i].empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(unsigned num_bits) {
|
||||||
|
fixed.reset();
|
||||||
|
fixed.resize(num_bits, l_undef);
|
||||||
|
just_src.reset();
|
||||||
|
just_src.resize(num_bits);
|
||||||
|
just_side_cond.reset();
|
||||||
|
just_side_cond.resize(num_bits);
|
||||||
|
just_slicing.reset();
|
||||||
|
just_slicing.resize(num_bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_just(unsigned i) {
|
||||||
|
just_src[i].reset();
|
||||||
|
just_side_cond[i].reset();
|
||||||
|
just_slicing[i].reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_just(unsigned i, entry* e) {
|
||||||
|
reset_just(i);
|
||||||
|
push_just(i, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_just(unsigned i, entry* e) {
|
||||||
|
just_src[i].append(e->src);
|
||||||
|
just_side_cond[i].append(e->side_cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_from_bit(unsigned i, unsigned src) {
|
||||||
|
just_src[i].append(just_src[src]);
|
||||||
|
just_side_cond[i].append(just_side_cond[src]);
|
||||||
|
just_slicing[i].append(just_slicing[src]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -89,7 +142,7 @@ namespace polysat {
|
||||||
bool well_formed(entry* e);
|
bool well_formed(entry* e);
|
||||||
bool well_formed(layers const& ls);
|
bool well_formed(layers const& ls);
|
||||||
|
|
||||||
entry* alloc_entry(pvar v);
|
entry* alloc_entry(pvar v, unsigned constraint_index);
|
||||||
|
|
||||||
std::ostream& display_one(std::ostream& out, pvar v, entry const* e) const;
|
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;
|
std::ostream& display_all(std::ostream& out, pvar v, entry const* e, char const* delimiter = "") const;
|
||||||
|
@ -97,9 +150,9 @@ namespace polysat {
|
||||||
void log(pvar v);
|
void log(pvar v);
|
||||||
|
|
||||||
struct pop_viable_trail;
|
struct pop_viable_trail;
|
||||||
void pop_viable(entry* e, pvar v, entry_kind k);
|
void pop_viable(entry* e, entry_kind k);
|
||||||
struct push_viable_trail;
|
struct push_viable_trail;
|
||||||
void push_viable(entry* e, pvar v, entry_kind k);
|
void push_viable(entry* e);
|
||||||
|
|
||||||
void insert(entry* e, pvar v, ptr_vector<entry>& entries, entry_kind k);
|
void insert(entry* e, pvar v, ptr_vector<entry>& entries, entry_kind k);
|
||||||
|
|
||||||
|
@ -107,6 +160,8 @@ namespace polysat {
|
||||||
|
|
||||||
void ensure_var(pvar v);
|
void ensure_var(pvar v);
|
||||||
|
|
||||||
|
lbool find_viable(pvar v, rational& lo, rational& hi);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
viable(core& c);
|
viable(core& c);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue