mirror of
https://github.com/Z3Prover/z3
synced 2025-06-22 05:43:39 +00:00
add cofactoring functionality
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
1defbc8aa4
commit
b019477378
3 changed files with 67 additions and 1 deletions
|
@ -145,6 +145,13 @@ namespace dd {
|
||||||
if (is_true(a)) return mk_not_rec(b);
|
if (is_true(a)) return mk_not_rec(b);
|
||||||
if (is_true(b)) return mk_not_rec(a);
|
if (is_true(b)) return mk_not_rec(a);
|
||||||
break;
|
break;
|
||||||
|
case bdd_cofactor_op:
|
||||||
|
if (a == b) return a;
|
||||||
|
if (is_const(a)) return a;
|
||||||
|
if (level(a) == level(b))
|
||||||
|
|
||||||
|
SASSERT(!is_const(b));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -574,6 +581,46 @@ namespace dd {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* co-factor a using b.
|
||||||
|
* b must be a variable bdd (it can be generalized to a cube)
|
||||||
|
*/
|
||||||
|
|
||||||
|
bdd bdd_manager::mk_cofactor(bdd const& a, bdd const& b) {
|
||||||
|
bool first = true;
|
||||||
|
scoped_push _sp(*this);
|
||||||
|
SASSERT(!is_const(b) && is_const(lo(b)) && is_const(hi(b)));
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
return bdd(mk_cofactor_rec(a.root, b.root), this);
|
||||||
|
}
|
||||||
|
catch (const mem_out &) {
|
||||||
|
if (!first) throw;
|
||||||
|
try_reorder();
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bdd_manager::BDD bdd_manager::mk_cofactor_rec(BDD a, BDD b) {
|
||||||
|
if (is_const(a)) return a;
|
||||||
|
unsigned la = level(a), lb = level(b);
|
||||||
|
if (la < lb) return a;
|
||||||
|
if (la == lb) return is_true(hi(b)) ? hi(a) : lo(a);
|
||||||
|
op_entry* e1 = pop_entry(a, b, bdd_cofactor_op);
|
||||||
|
op_entry const* e2 = m_op_cache.insert_if_not_there(e1);
|
||||||
|
if (check_result(e1, e2, a, b, bdd_cofactor_op))
|
||||||
|
return e2->m_result;
|
||||||
|
SASSERT(la > lb);
|
||||||
|
push(mk_cofactor_rec(lo(a), b));
|
||||||
|
push(mk_cofactor_rec(hi(a), b));
|
||||||
|
BDD r = make_node(la, read(2), read(1));
|
||||||
|
pop(2);
|
||||||
|
e1->m_result = r;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bdd bdd_manager::mk_ite(bdd const& c, bdd const& t, bdd const& e) {
|
bdd bdd_manager::mk_ite(bdd const& c, bdd const& t, bdd const& e) {
|
||||||
bool first = true;
|
bool first = true;
|
||||||
scoped_push _sp(*this);
|
scoped_push _sp(*this);
|
||||||
|
@ -589,6 +636,7 @@ namespace dd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bdd_manager::BDD bdd_manager::mk_ite_rec(BDD a, BDD b, BDD c) {
|
bdd_manager::BDD bdd_manager::mk_ite_rec(BDD a, BDD b, BDD c) {
|
||||||
if (is_true(a)) return b;
|
if (is_true(a)) return b;
|
||||||
if (is_false(a)) return c;
|
if (is_false(a)) return c;
|
||||||
|
|
|
@ -45,7 +45,8 @@ namespace dd {
|
||||||
bdd_not_op = 5,
|
bdd_not_op = 5,
|
||||||
bdd_and_proj_op = 6,
|
bdd_and_proj_op = 6,
|
||||||
bdd_or_proj_op = 7,
|
bdd_or_proj_op = 7,
|
||||||
bdd_no_op = 8,
|
bdd_cofactor_op = 8,
|
||||||
|
bdd_no_op = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bdd_node {
|
struct bdd_node {
|
||||||
|
@ -146,6 +147,7 @@ namespace dd {
|
||||||
BDD mk_not_rec(BDD b);
|
BDD mk_not_rec(BDD b);
|
||||||
BDD mk_ite_rec(BDD a, BDD b, BDD c);
|
BDD mk_ite_rec(BDD a, BDD b, BDD c);
|
||||||
BDD mk_quant_rec(unsigned lvl, BDD b, bdd_op op);
|
BDD mk_quant_rec(unsigned lvl, BDD b, bdd_op op);
|
||||||
|
BDD mk_cofactor_rec(BDD a, BDD b);
|
||||||
|
|
||||||
void push(BDD b);
|
void push(BDD b);
|
||||||
void pop(unsigned num_scopes);
|
void pop(unsigned num_scopes);
|
||||||
|
@ -193,6 +195,7 @@ namespace dd {
|
||||||
bdd mk_and(bdd const& a, bdd const& b);
|
bdd mk_and(bdd const& a, bdd const& b);
|
||||||
bdd mk_or(bdd const& a, bdd const& b);
|
bdd mk_or(bdd const& a, bdd const& b);
|
||||||
bdd mk_xor(bdd const& a, bdd const& b);
|
bdd mk_xor(bdd const& a, bdd const& b);
|
||||||
|
bdd mk_cofactor(bdd const& a, bdd const& b);
|
||||||
|
|
||||||
void reserve_var(unsigned v);
|
void reserve_var(unsigned v);
|
||||||
bool well_formed();
|
bool well_formed();
|
||||||
|
@ -292,6 +295,7 @@ namespace dd {
|
||||||
bdd operator^(bdd const& other) const { return m->mk_xor(*this, other); }
|
bdd operator^(bdd const& other) const { return m->mk_xor(*this, other); }
|
||||||
bdd operator|=(bdd const& other) { return *this = *this || other; }
|
bdd operator|=(bdd const& other) { return *this = *this || other; }
|
||||||
bdd operator&=(bdd const& other) { return *this = *this && other; }
|
bdd operator&=(bdd const& other) { return *this = *this && other; }
|
||||||
|
bdd cofactor(bdd const& cube) { return m->mk_cofactor(*this, cube); }
|
||||||
std::ostream& display(std::ostream& out) const { return m->display(out, *this); }
|
std::ostream& display(std::ostream& out) const { return m->display(out, *this); }
|
||||||
bool operator==(bdd const& other) const { return root == other.root; }
|
bool operator==(bdd const& other) const { return root == other.root; }
|
||||||
bool operator!=(bdd const& other) const { return root != other.root; }
|
bool operator!=(bdd const& other) const { return root != other.root; }
|
||||||
|
|
|
@ -425,6 +425,19 @@ public:
|
||||||
SASSERT_EQ(x_dom.find_hint(s358 && (x == rational(4)), rational(5), r), find_t::empty);
|
SASSERT_EQ(x_dom.find_hint(s358 && (x == rational(4)), rational(5), r), find_t::empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_cofactor() {
|
||||||
|
std::cout << "test_cofactor\n";
|
||||||
|
bdd_manager m(20);
|
||||||
|
bdd v0 = m.mk_var(0);
|
||||||
|
bdd v1 = m.mk_var(1);
|
||||||
|
bdd v2 = m.mk_var(2);
|
||||||
|
bdd c1 = v0 && v1 && v2;
|
||||||
|
SASSERT(c1.cofactor(v0) == (v1 && v2));
|
||||||
|
SASSERT(c1.cofactor(v1) == (v0 && v2));
|
||||||
|
SASSERT(c1.cofactor(v2) == (v0 && v1));
|
||||||
|
SASSERT(c1.cofactor(!v1) == m.mk_false());
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -446,4 +459,5 @@ void tst_bdd() {
|
||||||
dd::test_bdd::test_fdd_reorder();
|
dd::test_bdd::test_fdd_reorder();
|
||||||
dd::test_bdd::test_fdd_twovars();
|
dd::test_bdd::test_fdd_twovars();
|
||||||
dd::test_bdd::test_fdd_find_hint();
|
dd::test_bdd::test_fdd_find_hint();
|
||||||
|
dd::test_bdd::test_cofactor();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue