mirror of
https://github.com/Z3Prover/z3
synced 2025-04-28 19:35:50 +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:
parent
09f31ebb0a
commit
12444c7e8b
7 changed files with 156 additions and 31 deletions
|
@ -937,6 +937,26 @@ namespace dd {
|
|||
bdd bdd_manager::mk_ult(bddv const& a, bddv const& b) { return mk_ule(a, b) && !mk_eq(a, b); }
|
||||
bdd bdd_manager::mk_ugt(bddv const& a, bddv const& b) { return mk_ult(b, a); }
|
||||
|
||||
bdd bdd_manager::mk_sle(bddv const& a, bddv const& b) {
|
||||
SASSERT(a.size() == b.size());
|
||||
// Note: sle can be reduced to ule by flipping the sign bits of both arguments
|
||||
bdd lt = mk_false();
|
||||
bdd eq = mk_true();
|
||||
unsigned const sz = a.size();
|
||||
if (sz > 0) {
|
||||
lt = a[sz - 1] && !b[sz - 1];
|
||||
eq = !(a[sz - 1] ^ b[sz - 1]);
|
||||
for (unsigned i = sz - 1; i-- > 0; ) {
|
||||
lt |= eq && (!a[i] && b[i]);
|
||||
eq &= !(a[i] ^ b[i]);
|
||||
}
|
||||
}
|
||||
return lt || eq;
|
||||
}
|
||||
bdd bdd_manager::mk_sge(bddv const& a, bddv const& b) { return mk_sle(b, a); }
|
||||
bdd bdd_manager::mk_slt(bddv const& a, bddv const& b) { return mk_sle(a, b) && !mk_eq(a, b); }
|
||||
bdd bdd_manager::mk_sgt(bddv const& a, bddv const& b) { return mk_slt(b, a); }
|
||||
|
||||
bddv bdd_manager::mk_add(bddv const& a, bddv const& b) {
|
||||
SASSERT(a.size() == b.size());
|
||||
bdd carry = mk_false();
|
||||
|
@ -1098,13 +1118,6 @@ namespace dd {
|
|||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bdd bdd_manager::mk_sle(bddv const& a, bddv const& b);
|
||||
bdd bdd_manager::mk_sge(bddv const& a, bddv const& b) { return mk_sle(b, a); }
|
||||
bdd bdd_manager::mk_slt(bddv const& a, bddv const& b) { return mk_sle(a, b) && !mk_eq(a, b); }
|
||||
bdd bdd_manager::mk_sgt(bddv const& a, bddv const& b) { return mk_slt(b, a); }
|
||||
#endif
|
||||
|
||||
void bddv::shl() {
|
||||
for (unsigned j = size(); j-- > 1;)
|
||||
m_bits[j] = m_bits[j - 1];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,13 +32,14 @@ namespace dd {
|
|||
class fdd {
|
||||
unsigned_vector m_pos2var; // pos -> BDD var
|
||||
unsigned_vector m_var2pos; // var -> pos (pos = place number in the bit representation, 0 is LSB's place)
|
||||
// bdd_manager* m; // NOTE: currently unused
|
||||
bdd_manager* m;
|
||||
bddv m_var;
|
||||
|
||||
static unsigned_vector seq(unsigned count) {
|
||||
static unsigned_vector seq(unsigned count, unsigned start = 0, unsigned step = 1) {
|
||||
unsigned_vector result;
|
||||
for (unsigned i = 0; i < count; ++i)
|
||||
result.push_back(i);
|
||||
unsigned k = start;
|
||||
for (unsigned i = 0; i < count; ++i, k += step)
|
||||
result.push_back(k);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -46,7 +47,7 @@ namespace dd {
|
|||
|
||||
public:
|
||||
/** Initialize FDD using BDD variables from 0 to num_bits-1. */
|
||||
fdd(bdd_manager& manager, unsigned num_bits) : fdd(manager, seq(num_bits)) { }
|
||||
fdd(bdd_manager& manager, unsigned num_bits, unsigned start = 0, unsigned step = 1) : fdd(manager, seq(num_bits, start, step)) { }
|
||||
fdd(bdd_manager& manager, unsigned_vector const& vars) : fdd(manager, unsigned_vector(vars)) { }
|
||||
fdd(bdd_manager& manager, unsigned_vector&& vars);
|
||||
|
||||
|
@ -55,6 +56,9 @@ namespace dd {
|
|||
|
||||
bddv const& var() const { return m_var; }
|
||||
|
||||
/** Equivalent to var() != 0 */
|
||||
bdd non_zero() const;
|
||||
|
||||
/** Checks whether the integer val is contained in the BDD when viewed as set of integers.
|
||||
* Precondition: the bdd only contains variables managed by this fdd.
|
||||
*/
|
||||
|
@ -64,6 +68,9 @@ namespace dd {
|
|||
* Precondition: the bdd only contains variables managed by this fdd.
|
||||
*/
|
||||
find_t find(bdd b, rational& out_val) const;
|
||||
|
||||
/** Like find, but returns hint if it is contained in the BDD. */
|
||||
find_t find_hint(bdd b, rational const& hint, rational& out_val) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue