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

include disequality expansion for non-unit case.

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2024-11-04 09:26:32 -08:00
parent 6559584502
commit b870ed192a
5 changed files with 36 additions and 35 deletions

View file

@ -28,7 +28,7 @@ bit_blaster_cfg::bit_blaster_cfg(bv_util & u, bit_blaster_params const & p, bool
m_rw(rw) {
}
static void sort_args(expr * & l1, expr * & l2, expr * & l3) {
void bit_blaster_cfg::sort_args(expr * & l1, expr * & l2, expr * & l3) {
expr * args[3] = {l1, l2, l3};
// ast_lt_proc is based on the AST ids. So, it is a total order on AST nodes.
// No need for stable_sort
@ -41,7 +41,7 @@ void bit_blaster_cfg::mk_xor3(expr * l1, expr * l2, expr * l3, expr_ref & r) {
TRACE("xor3", tout << "#" << l1->get_id() << " #" << l2->get_id() << " #" << l3->get_id(););
sort_args(l1, l2, l3);
TRACE("xor3_sorted", tout << "#" << l1->get_id() << " #" << l2->get_id() << " #" << l3->get_id(););
if (m_params.m_bb_ext_gates) {
if (m_ext_gates || m_params.m_bb_ext_gates) {
if (l1 == l2)
r = l3;
else if (l1 == l3)
@ -80,7 +80,7 @@ void bit_blaster_cfg::mk_carry(expr * l1, expr * l2, expr * l3, expr_ref & r) {
TRACE("carry", tout << "#" << l1->get_id() << " #" << l2->get_id() << " #" << l3->get_id(););
sort_args(l1, l2, l3);
TRACE("carry_sorted", tout << "#" << l1->get_id() << " #" << l2->get_id() << " #" << l3->get_id(););
if (m_params.m_bb_ext_gates) {
if (m_ext_gates || m_params.m_bb_ext_gates) {
if ((m().is_false(l1) && m().is_false(l2)) ||
(m().is_false(l1) && m().is_false(l3)) ||
(m().is_false(l2) && m().is_false(l3)))

View file

@ -31,35 +31,39 @@ protected:
bv_util & m_util;
bit_blaster_params const & m_params;
bool_rewriter & m_rw;
bool m_ext_gates = false;
void sort(expr*& a, expr*& b) { if (a->get_id() > b->get_id()) std::swap(a, b); }
void sort_args(expr*& l1, expr*& l2, expr*& l3);
public:
bit_blaster_cfg(bv_util & u, bit_blaster_params const & p, bool_rewriter& rw);
ast_manager & m() const { return m_util.get_manager(); }
numeral power(unsigned n) const { return rational::power_of_two(n); }
void mk_xor(expr * a, expr * b, expr_ref & r) { m_rw.mk_xor(a, b, r); }
void mk_xor(expr * a, expr * b, expr_ref & r) { sort(a, b); m_rw.mk_xor(a, b, r); }
void mk_xor3(expr * a, expr * b, expr * c, expr_ref & r);
void mk_carry(expr * a, expr * b, expr * c, expr_ref & r);
void mk_iff(expr * a, expr * b, expr_ref & r) { m_rw.mk_iff(a, b, r); }
void mk_and(expr * a, expr * b, expr_ref & r) { m_rw.mk_and(a, b, r); }
void mk_and(expr * a, expr * b, expr * c, expr_ref & r) { m_rw.mk_and(a, b, c, r); }
void mk_iff(expr * a, expr * b, expr_ref & r) { sort(a, b); m_rw.mk_iff(a, b, r); }
void mk_and(expr * a, expr * b, expr_ref & r) { sort(a, b); m_rw.mk_and(a, b, r); }
void mk_and(expr* a, expr* b, expr* c, expr_ref& r) { sort_args(a, b, c); m_rw.mk_and(a, b, c, r); }
void mk_and(unsigned sz, expr * const * args, expr_ref & r) { m_rw.mk_and(sz, args, r); }
void mk_ge2(expr* a, expr* b, expr* c, expr_ref& r) { m_rw.mk_ge2(a, b, c, r); }
void mk_or(expr * a, expr * b, expr_ref & r) { m_rw.mk_or(a, b, r); }
void mk_or(expr * a, expr * b, expr * c, expr_ref & r) { m_rw.mk_or(a, b, c, r); }
void mk_or(expr * a, expr * b, expr_ref & r) { sort(a, b); m_rw.mk_or(a, b, r); }
void mk_or(expr * a, expr * b, expr * c, expr_ref & r) { sort_args(a, b, c); m_rw.mk_or(a, b, c, r); }
void mk_or(unsigned sz, expr * const * args, expr_ref & r) { m_rw.mk_or(sz, args, r); }
void mk_not(expr * a, expr_ref & r) { m_rw.mk_not(a, r); }
void mk_ite(expr * c, expr * t, expr * e, expr_ref & r) { m_rw.mk_ite(c, t, e, r); }
void mk_nand(expr * a, expr * b, expr_ref & r) { m_rw.mk_nand(a, b, r); }
void mk_nor(expr * a, expr * b, expr_ref & r) { m_rw.mk_nor(a, b, r); }
void mk_nand(expr * a, expr * b, expr_ref & r) { sort(a, b); m_rw.mk_nand(a, b, r); }
void mk_nor(expr * a, expr * b, expr_ref & r) { sort(a, b); m_rw.mk_nor(a, b, r); }
};
class bit_blaster : public bit_blaster_tpl<bit_blaster_cfg> {
class bit_blaster : public bit_blaster_tpl<bit_blaster_cfg> {
bv_util m_util;
bool_rewriter m_rw;
public:
bit_blaster(ast_manager & m, bit_blaster_params const & params);
bit_blaster_params const & get_params() const { return this->m_params; }
void set_flat_and_or(bool f) { m_rw.set_flat_and_or(f); }
void set_ext_gates(bool f) { m_ext_gates = f; }
};

View file

@ -56,6 +56,7 @@ namespace bv {
m_bb(m, get_config()),
m_find(*this) {
m_bb.set_flat_and_or(false);
m_bb.set_ext_gates(true);
}
bool solver::is_fixed(euf::theory_var v, expr_ref& val, sat::literal_vector& lits) {
@ -267,7 +268,7 @@ namespace bv {
++num_undef;
undef_idx = -static_cast<int>(i + 1);
}
if (num_undef > 1)
if (num_undef > 1 && false)
return;
}
if (num_undef == 0)
@ -533,12 +534,10 @@ namespace bv {
}
bool solver::unit_propagate() {
if (m_prop_queue_head == m_prop_queue.size())
if (m_prop_queue.empty())
return false;
force_push();
ctx.push(value_trail<unsigned>(m_prop_queue_head));
for (; m_prop_queue_head < m_prop_queue.size() && !s().inconsistent(); ++m_prop_queue_head) {
auto const p = m_prop_queue[m_prop_queue_head];
for (unsigned i = 0; i < m_prop_queue.size() && !s().inconsistent(); ++i) {
auto const p = m_prop_queue[i];
if (p.m_atom) {
for (auto vp : *p.m_atom)
propagate_bits(vp);
@ -548,6 +547,7 @@ namespace bv {
else
propagate_bits(p.m_vp);
}
m_prop_queue.reset();
// check_missing_propagation();
return true;
}
@ -587,6 +587,8 @@ namespace bv {
if (m_wpos[v1] == idx)
find_wpos(v1);
bool is_fixed = s().value(m_bits[v1][m_wpos[v1]]) != l_undef;
literal bit1 = m_bits[v1][idx];
lbool val = s().value(bit1);
TRACE("bv", tout << "propagating v" << v1 << " #" << var2enode(v1)->get_expr_id() << "[" << idx << "] = " << val << "\n";);
@ -613,7 +615,7 @@ namespace bv {
if (!assign_bit(bit2, v1, v2, idx, bit1, false))
break;
}
if (s().value(m_bits[v1][m_wpos[v1]]) != l_undef)
if (!is_fixed && s().value(m_bits[v1][m_wpos[v1]]) != l_undef)
find_wpos(v1);
return num_assigned > 0;
@ -626,7 +628,7 @@ namespace bv {
*/
sat::check_result solver::check() {
force_push();
SASSERT(m_prop_queue.size() == m_prop_queue_head);
SASSERT(m_prop_queue.empty());
bool ok = true;
svector<std::pair<expr*, internalize_mode>> delay;
for (auto kv : m_delay_internalize)
@ -651,22 +653,19 @@ namespace bv {
}
void solver::push_core() {
TRACE("bv", tout << "push: " << get_num_vars() << "@" << m_prop_queue_lim.size() << "\n";);
TRACE("bv", tout << "push: " << get_num_vars() << "@" << m_prop_queue.size() << "\n";);
th_euf_solver::push_core();
m_prop_queue_lim.push_back(m_prop_queue.size());
}
void solver::pop_core(unsigned n) {
SASSERT(m_num_scopes == 0);
unsigned old_sz = m_prop_queue_lim.size() - n;
m_prop_queue.shrink(m_prop_queue_lim[old_sz]);
m_prop_queue_lim.shrink(old_sz);
th_euf_solver::pop_core(n);
old_sz = get_num_vars();
unsigned old_sz = get_num_vars();
m_bits.shrink(old_sz);
m_wpos.shrink(old_sz);
m_zero_one_bits.shrink(old_sz);
TRACE("bv", tout << "num vars " << old_sz << "@" << m_prop_queue_lim.size() << "\n";);
m_prop_queue.reset();
TRACE("bv", tout << "num vars " << old_sz << "\n";);
}
void solver::simplify() {
@ -886,12 +885,14 @@ namespace bv {
void solver::merge_eh(theory_var r1, theory_var r2, theory_var v1, theory_var v2) {
TRACE("bv", tout << "merging: v" << v1 << " #" << var2enode(v1)->get_expr_id() << " v" << v2 << " #" << var2enode(v2)->get_expr_id() << "\n";);
if (!merge_zero_one_bits(r1, r2)) {
TRACE("bv", tout << "conflict detected\n";);
return; // conflict was detected
}
m_prop_queue.reset();
SASSERT(m_bits[v1].size() == m_bits[v2].size());
unsigned sz = m_bits[v1].size();
if (sz == 1)
@ -982,8 +983,9 @@ namespace bv {
force_push();
if (a)
for (auto curr : *a)
if (propagate_eqc || find(curr.first) != find(v2) || curr.second != idx)
m_prop_queue.push_back(propagation_item(curr));
if (propagate_eqc || find(curr.first) != find(v2) || curr.second != idx) {
m_prop_queue.push_back(propagation_item(curr));
}
return true;
}
}

View file

@ -234,8 +234,6 @@ namespace bv {
mutable vector<rational> m_power2;
literal_vector m_tmp_literals;
svector<propagation_item> m_prop_queue;
unsigned_vector m_prop_queue_lim;
unsigned m_prop_queue_head = 0;
sat::literal m_true = sat::null_literal;
euf::enode_vector m_bv2ints;
obj_map<app, lazy_mul*> m_lazymul;

View file

@ -155,9 +155,7 @@ namespace euf {
if (lit.sign()) {
v = si.add_bool_var(e);
s().set_external(v);
s().set_eliminated(v, false);
set_bool_var2expr(v, e);
m_var_trail.push_back(v);
s().set_eliminated(v, false);
sat::literal lit2 = literal(v, false);
th_proof_hint* ph1 = nullptr, * ph2 = nullptr;
if (use_drat()) {
@ -185,7 +183,6 @@ namespace euf {
return lit;
}
set_bool_var2expr(v, e);
enode* n = m_egraph.find(e);
if (!n)