3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-30 12:25:51 +00:00

Phase saving and some minor changes (#5209)

* Implement phase saving

* Implement signed comparison on BDD vectors

* Add fdd::non_zero

* Simplify construction of fdds over disjoint variables

* Minor changes to adding constraint
This commit is contained in:
Jakob Rath 2021-04-22 18:47:46 +02:00 committed by GitHub
parent 09f31ebb0a
commit 12444c7e8b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 156 additions and 31 deletions

View file

@ -23,7 +23,7 @@ namespace dd {
fdd::fdd(bdd_manager& manager, unsigned_vector&& vars)
: m_pos2var(std::move(vars))
, m_var2pos()
// , m(&manager)
, m(&manager)
, m_var(manager.mk_var(m_pos2var))
{
for (unsigned pos = 0; pos < m_pos2var.size(); ++pos) {
@ -34,6 +34,14 @@ namespace dd {
}
}
bdd fdd::non_zero() const {
bdd non_zero = m->mk_false();
for (unsigned var : m_pos2var) {
non_zero |= m->mk_var(var);
}
return non_zero;
}
unsigned fdd::var2pos(unsigned var) const {
return var < m_var2pos.size() ? m_var2pos[var] : UINT_MAX;
}
@ -48,27 +56,54 @@ namespace dd {
}
find_t fdd::find(bdd b, rational& out_val) const {
return find_hint(b, rational::zero(), out_val);
}
find_t fdd::find_hint(bdd b, rational const& hint, rational& out_val) const {
out_val = 0;
if (b.is_false())
return find_t::empty;
bool is_unique = true;
bool hint_ok = !hint.is_zero(); // since we choose the 'lo' branch by default, we don't need to check the hint when it is 0.
unsigned num_vars = 0;
while (!b.is_true()) {
++num_vars;
unsigned const pos = var2pos(b.var());
SASSERT(pos != UINT_MAX && "Unexpected BDD variable");
bool go_hi = false;
if (b.lo().is_false()) {
go_hi = true;
if (hint_ok && !hint.get_bit(pos))
hint_ok = false;
}
else if (b.hi().is_false()) {
if (hint_ok && hint.get_bit(pos))
hint_ok = false;
}
else {
// This is the only case where we have a choice
// => follow the hint
SASSERT(!b.lo().is_false() && !b.hi().is_false());
is_unique = false;
if (hint_ok && hint.get_bit(pos))
go_hi = true;
}
if (go_hi) {
out_val += rational::power_of_two(pos);
b = b.hi();
}
else {
if (!b.hi().is_false())
is_unique = false;
else
b = b.lo();
}
}
if (num_vars != num_bits())
is_unique = false;
// If a variable corresponding to a 1-bit in hint does not appear in the BDD,
// out_val is wrong at this point, so we set it explicitly.
if (hint_ok)
out_val = hint;
// TODO: instead of computing out_val incrementally, we could mark the visited 'hi'-positions and only compute out_val from the marks when !hint_ok.
return is_unique ? find_t::singleton : find_t::multiple;
}