mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
fix at-most-1 constraint compiler bug
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
bb6d826908
commit
23b9d3ef55
17 changed files with 369 additions and 62 deletions
|
@ -153,7 +153,7 @@ void mpq_manager<SYNCH>::display_smt2(std::ostream & out, mpq const & a, bool de
|
|||
}
|
||||
|
||||
template<bool SYNCH>
|
||||
void mpq_manager<SYNCH>::display_decimal(std::ostream & out, mpq const & a, unsigned prec) {
|
||||
void mpq_manager<SYNCH>::display_decimal(std::ostream & out, mpq const & a, unsigned prec, bool truncate) {
|
||||
mpz n1, d1, v1;
|
||||
get_numerator(a, n1);
|
||||
get_denominator(a, d1);
|
||||
|
@ -177,7 +177,7 @@ void mpq_manager<SYNCH>::display_decimal(std::ostream & out, mpq const & a, unsi
|
|||
if (is_zero(n1))
|
||||
goto end; // number is precise
|
||||
}
|
||||
out << "?";
|
||||
if (!truncate) out << "?";
|
||||
end:
|
||||
del(ten); del(n1); del(d1); del(v1);
|
||||
}
|
||||
|
|
|
@ -265,7 +265,7 @@ public:
|
|||
|
||||
void display_smt2(std::ostream & out, mpq const & a, bool decimal) const;
|
||||
|
||||
void display_decimal(std::ostream & out, mpq const & a, unsigned prec);
|
||||
void display_decimal(std::ostream & out, mpq const & a, unsigned prec, bool truncate = false);
|
||||
|
||||
void add(mpz const & a, mpz const & b, mpz & c) { mpz_manager<SYNCH>::add(a, b, c); }
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ public:
|
|||
|
||||
void display(std::ostream & out) const { return m().display(out, m_val); }
|
||||
|
||||
void display_decimal(std::ostream & out, unsigned prec) const { return m().display_decimal(out, m_val, prec); }
|
||||
void display_decimal(std::ostream & out, unsigned prec, bool truncate = false) const { return m().display_decimal(out, m_val, prec, truncate); }
|
||||
|
||||
bool is_uint64() const { return m().is_uint64(m_val); }
|
||||
|
||||
|
|
|
@ -234,19 +234,28 @@ Notes:
|
|||
private:
|
||||
|
||||
literal mk_at_most_1(bool full, unsigned n, literal const* xs) {
|
||||
TRACE("pb", tout << (full?"full":"partial") << " ";
|
||||
for (unsigned i = 0; i < n; ++i) tout << xs[i] << " ";
|
||||
tout << "\n";);
|
||||
|
||||
if (!full && n >= 4) {
|
||||
return mk_at_most_1_bimander(n, xs);
|
||||
}
|
||||
literal_vector in(n, xs);
|
||||
literal result = ctx.fresh();
|
||||
literal result = fresh();
|
||||
unsigned inc_size = 4;
|
||||
literal_vector ands;
|
||||
ands.push_back(result);
|
||||
while (!in.empty()) {
|
||||
literal_vector ors;
|
||||
unsigned i = 0;
|
||||
unsigned n = in.size();
|
||||
bool last = n <= inc_size;
|
||||
for (; i + inc_size < n; i += inc_size) {
|
||||
mk_at_most_1_small(full, last, inc_size, in.c_ptr() + i, result, ors);
|
||||
mk_at_most_1_small(full, last, inc_size, in.c_ptr() + i, result, ands, ors);
|
||||
}
|
||||
if (i < n) {
|
||||
mk_at_most_1_small(full, last, n - i, in.c_ptr() + i, result, ors);
|
||||
mk_at_most_1_small(full, last, n - i, in.c_ptr() + i, result, ands, ors);
|
||||
}
|
||||
if (last) {
|
||||
break;
|
||||
|
@ -255,12 +264,22 @@ Notes:
|
|||
in.append(ors);
|
||||
ors.reset();
|
||||
}
|
||||
if (full) {
|
||||
add_clause(ands);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void mk_at_most_1_small(bool full, bool last, unsigned n, literal const* xs, literal result, literal_vector& ors) {
|
||||
void mk_at_most_1_small(bool full, bool last, unsigned n, literal const* xs, literal result, literal_vector& ands, literal_vector& ors) {
|
||||
SASSERT(n > 0);
|
||||
if (n == 1) {
|
||||
if (!last) {
|
||||
ors.push_back(xs[0]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!last) {
|
||||
literal ex = ctx.fresh();
|
||||
literal ex = fresh();
|
||||
for (unsigned j = 0; j < n; ++j) {
|
||||
add_clause(ctx.mk_not(xs[j]), ex);
|
||||
}
|
||||
|
@ -271,16 +290,59 @@ Notes:
|
|||
}
|
||||
ors.push_back(ex);
|
||||
}
|
||||
// result => xs[0] + ... + xs[n-1] <= 1
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
for (unsigned j = i + 1; j < n; ++j) {
|
||||
add_clause(ctx.mk_not(result), ctx.mk_not(xs[i]), ctx.mk_not(xs[j]));
|
||||
}
|
||||
if (full) {
|
||||
add_clause(result, xs[i]);
|
||||
}
|
||||
// xs[0] + ... + xs[n-1] <= 1 => and_x
|
||||
if (full) {
|
||||
literal and_i = fresh();
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
literal_vector lits;
|
||||
lits.push_back(and_i);
|
||||
for (unsigned j = 0; j < n; ++j) {
|
||||
if (j != i) lits.push_back(xs[j]);
|
||||
}
|
||||
add_clause(lits);
|
||||
}
|
||||
ands.push_back(ctx.mk_not(and_i));
|
||||
}
|
||||
}
|
||||
|
||||
literal mk_at_most_1_bimander(unsigned n, literal const* xs) {
|
||||
literal_vector in(n, xs);
|
||||
literal result = fresh();
|
||||
unsigned inc_size = 2;
|
||||
bool last = false;
|
||||
bool full = false;
|
||||
literal_vector ors, ands;
|
||||
unsigned i = 0;
|
||||
for (; i + inc_size < n; i += inc_size) {
|
||||
mk_at_most_1_small(full, last, inc_size, in.c_ptr() + i, result, ands, ors);
|
||||
}
|
||||
if (i < n) {
|
||||
mk_at_most_1_small(full, last, n - i, in.c_ptr() + i, result, ands, ors);
|
||||
}
|
||||
|
||||
unsigned nbits = 0;
|
||||
while (static_cast<unsigned>(1 << nbits) < ors.size()) {
|
||||
++nbits;
|
||||
}
|
||||
literal_vector bits;
|
||||
for (unsigned k = 0; k < nbits; ++k) {
|
||||
bits.push_back(fresh());
|
||||
}
|
||||
for (i = 0; i < ors.size(); ++i) {
|
||||
for (unsigned k = 0; k < nbits; ++k) {
|
||||
bool bit_set = (i & (static_cast<unsigned>(1 << k))) != 0;
|
||||
add_clause(ctx.mk_not(result), ctx.mk_not(ors[i]), bit_set ? bits[k] : ctx.mk_not(bits[k]));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream& pp(std::ostream& out, unsigned n, literal const* lits) {
|
||||
for (unsigned i = 0; i < n; ++i) ctx.pp(out, lits[i]) << " ";
|
||||
return out;
|
||||
|
@ -344,9 +406,13 @@ Notes:
|
|||
literal lits[2] = { l1, l2 };
|
||||
add_clause(2, lits);
|
||||
}
|
||||
void add_clause(literal_vector const& lits) {
|
||||
add_clause(lits.size(), lits.c_ptr());
|
||||
}
|
||||
void add_clause(unsigned n, literal const* ls) {
|
||||
m_stats.m_num_compiled_clauses++;
|
||||
literal_vector tmp(n, ls);
|
||||
TRACE("pb", for (unsigned i = 0; i < n; ++i) tout << ls[i] << " "; tout << "\n";);
|
||||
ctx.mk_clause(n, tmp.c_ptr());
|
||||
}
|
||||
|
||||
|
@ -383,7 +449,7 @@ Notes:
|
|||
}
|
||||
|
||||
void card(unsigned k, unsigned n, literal const* xs, literal_vector& out) {
|
||||
TRACE("pb", tout << "card k:" << k << " n: " << n << "\n";);
|
||||
TRACE("pb", tout << "card k: " << k << " n: " << n << "\n";);
|
||||
if (n <= k) {
|
||||
psort_nw<psort_expr>::sorting(n, xs, out);
|
||||
}
|
||||
|
@ -397,7 +463,7 @@ Notes:
|
|||
card(k, n-l, xs + l, out2);
|
||||
smerge(k, out1.size(), out1.c_ptr(), out2.size(), out2.c_ptr(), out);
|
||||
}
|
||||
TRACE("pb", tout << "card k:" << k << " n: " << n << "\n";
|
||||
TRACE("pb", tout << "card k: " << k << " n: " << n << "\n";
|
||||
pp(tout << "in:", n, xs) << "\n";
|
||||
pp(tout << "out:", out) << "\n";);
|
||||
|
||||
|
@ -743,7 +809,7 @@ Notes:
|
|||
if (j < b) {
|
||||
ls.push_back(as[i]);
|
||||
ls.push_back(bs[j]);
|
||||
add_clause(ls.size(), ls.c_ptr());
|
||||
add_clause(ls);
|
||||
ls.pop_back();
|
||||
ls.pop_back();
|
||||
}
|
||||
|
@ -804,7 +870,7 @@ Notes:
|
|||
pp(tout, lits) << "\n";);
|
||||
SASSERT(k + offset <= n);
|
||||
if (k == 0) {
|
||||
add_clause(lits.size(), lits.c_ptr());
|
||||
add_clause(lits);
|
||||
return;
|
||||
}
|
||||
for (unsigned i = offset; i < n - k + 1; ++i) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue