mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 17:45:32 +00:00
review and fix soundness bug in band rule
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
2704626a5d
commit
215a4e9bad
4 changed files with 21 additions and 17 deletions
|
@ -37,17 +37,12 @@ namespace polysat {
|
|||
|
||||
switch (c) {
|
||||
case code::and_op:
|
||||
case code::or_op:
|
||||
case code::xor_op:
|
||||
if (p.index() > q.index())
|
||||
std::swap(m_p, m_q);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// The following can currently not be used as standalone constraints
|
||||
SASSERT(c != code::or_op);
|
||||
SASSERT(c != code::xor_op);
|
||||
}
|
||||
|
||||
lbool op_constraint::eval() const {
|
||||
|
@ -89,10 +84,6 @@ namespace polysat {
|
|||
return out << "<<";
|
||||
case op_constraint::code::and_op:
|
||||
return out << "&";
|
||||
case op_constraint::code::or_op:
|
||||
return out << "|";
|
||||
case op_constraint::code::xor_op:
|
||||
return out << "^";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return out;
|
||||
|
@ -333,8 +324,8 @@ namespace polysat {
|
|||
* p[i] && q[i] = r[i]
|
||||
* p = 2^K - 1 => q = r
|
||||
* q = 2^K - 1 => p = r
|
||||
* r = 0 && p = 2^k - 1 => q >= 2^k (or: q > p)
|
||||
* r = 0 && q = 2^k - 1 => p >= 2^k (or: p > q)
|
||||
* r = 0 && q != 0 & p = 2^k - 1 => q >= 2^k
|
||||
* r = 0 && p != 0 & q = 2^k - 1 => p >= 2^k
|
||||
*/
|
||||
clause_ref op_constraint::lemma_and(solver& s, assignment const& a) {
|
||||
auto& m = p().manager();
|
||||
|
@ -344,21 +335,29 @@ namespace polysat {
|
|||
|
||||
signed_constraint const andc(this, true);
|
||||
|
||||
// r <= p
|
||||
if (pv.is_val() && rv.is_val() && rv.val() > pv.val())
|
||||
return s.mk_clause(~andc, s.ule(r(), p()), true);
|
||||
// r <= q
|
||||
if (qv.is_val() && rv.is_val() && rv.val() > qv.val())
|
||||
return s.mk_clause(~andc, s.ule(r(), q()), true);
|
||||
// p = q => r = p
|
||||
if (pv.is_val() && qv.is_val() && rv.is_val() && pv == qv && rv != pv)
|
||||
return s.mk_clause(~andc, ~s.eq(p(), q()), s.eq(r(), p()), true);
|
||||
if (pv.is_val() && qv.is_val() && rv.is_val()) {
|
||||
// p = -1 => r = q
|
||||
if (pv.val() == m.max_value() && qv != rv)
|
||||
return s.mk_clause(~andc, ~s.eq(p(), m.max_value()), s.eq(q(), r()), true);
|
||||
// q = -1 => r = p
|
||||
if (qv.val() == m.max_value() && pv != rv)
|
||||
return s.mk_clause(~andc, ~s.eq(q(), m.max_value()), s.eq(p(), r()), true);
|
||||
if (rv.is_zero() && (pv.val() + 1).is_power_of_two() && qv.val() <= pv.val())
|
||||
return s.mk_clause(~andc, ~s.eq(r()), ~s.eq(p(), pv.val()), s.ult(q(), p()), true);
|
||||
// r = 0 && q != 0 & p = 2^k - 1 => q >= 2^k
|
||||
if ((pv.val() + 1).is_power_of_two() && rv.val() > pv.val())
|
||||
return s.mk_clause(~andc, ~s.eq(r()), ~s.eq(p(), pv.val()), s.eq(q()), s.ult(p(), q()), true);
|
||||
// r = 0 && p != 0 & q = 2^k - 1 => p >= 2^k
|
||||
if (rv.is_zero() && (qv.val() + 1).is_power_of_two() && pv.val() <= qv.val())
|
||||
return s.mk_clause(~andc, ~s.eq(r()), ~s.eq(q(), qv.val()), s.ult(p(), q()), true);
|
||||
return s.mk_clause(~andc, ~s.eq(r()), ~s.eq(q(), qv.val()), s.eq(p()),s.ult(q(), p()), true);
|
||||
|
||||
unsigned K = p().manager().power_of_2();
|
||||
for (unsigned i = 0; i < K; ++i) {
|
||||
bool pb = pv.val().get_bit(i);
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace polysat {
|
|||
|
||||
class op_constraint final : public constraint {
|
||||
public:
|
||||
enum class code { lshr_op, ashr_op, shl_op, and_op, or_op, xor_op };
|
||||
enum class code { lshr_op, ashr_op, shl_op, and_op };
|
||||
protected:
|
||||
friend class constraint_manager;
|
||||
|
||||
|
|
|
@ -1080,7 +1080,7 @@ namespace polysat {
|
|||
}
|
||||
|
||||
void solver::add_clause(std::initializer_list<signed_constraint> cs, bool is_redundant) {
|
||||
add_clause(cs.size(), std::data(cs), is_redundant);
|
||||
add_clause(static_cast<unsigned>(cs.size()), std::data(cs), is_redundant);
|
||||
}
|
||||
|
||||
void solver::add_clause(signed_constraint c1, bool is_redundant) {
|
||||
|
@ -1100,7 +1100,7 @@ namespace polysat {
|
|||
}
|
||||
|
||||
clause_ref solver::mk_clause(std::initializer_list<signed_constraint> cs, bool is_redundant) {
|
||||
return mk_clause(cs.size(), std::data(cs), is_redundant);
|
||||
return mk_clause(static_cast<unsigned>(cs.size()), std::data(cs), is_redundant);
|
||||
}
|
||||
|
||||
clause_ref solver::mk_clause(unsigned n, signed_constraint const* cs, bool is_redundant) {
|
||||
|
@ -1127,6 +1127,10 @@ namespace polysat {
|
|||
return mk_clause({ c1, c2, c3, c4 }, is_redundant);
|
||||
}
|
||||
|
||||
clause_ref solver::mk_clause(signed_constraint c1, signed_constraint c2, signed_constraint c3, signed_constraint c4, signed_constraint c5, bool is_redundant) {
|
||||
return mk_clause({ c1, c2, c3, c4, c5 }, is_redundant);
|
||||
}
|
||||
|
||||
void solver::push() {
|
||||
LOG_H3("Push user scope");
|
||||
push_level();
|
||||
|
|
|
@ -294,6 +294,7 @@ namespace polysat {
|
|||
clause_ref mk_clause(signed_constraint c1, signed_constraint c2, bool is_redundant);
|
||||
clause_ref mk_clause(signed_constraint c1, signed_constraint c2, signed_constraint c3, bool is_redundant);
|
||||
clause_ref mk_clause(signed_constraint c1, signed_constraint c2, signed_constraint c3, signed_constraint c4, bool is_redundant);
|
||||
clause_ref mk_clause(signed_constraint c1, signed_constraint c2, signed_constraint c3, signed_constraint c4, signed_constraint c5, bool is_redundant);
|
||||
clause_ref mk_clause(std::initializer_list<signed_constraint> cs, bool is_redundant);
|
||||
clause_ref mk_clause(unsigned n, signed_constraint const* cs, bool is_redundant);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue