3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-29 20:05:51 +00:00

add binary_merge encoding option

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-02-28 08:35:22 -08:00
parent c4ee4ffae4
commit 4c76d43670
6 changed files with 283 additions and 4 deletions

View file

@ -357,6 +357,112 @@ Notes:
}
}
/**
\brief encode clauses for ws*xs >= k
- normalize inequality to ws'*xs' >= a*2^(bits-1)
- for each binary digit, sort contributions
- merge with even digits from lower layer - creating 2*n vector
- for last layer return that index a is on.
*/
literal le(unsigned k, unsigned n, unsigned const* ws, literal const* xs) {
unsigned sum = 0;
literal_vector Xs;
for (unsigned i = 0; i < n; ++i) {
sum += ws[i];
Xs.push_back(mk_not(xs[i]));
}
if (k >= sum) {
return ctx.mk_true();
}
return ge(sum - k, n, ws, Xs.begin());
}
literal ge(unsigned k, unsigned n, unsigned const* ws, literal const* xs) {
m_t = GE_FULL;
return cmp(k, n, ws, xs);
}
literal eq(unsigned k, unsigned n, unsigned const* ws, literal const* xs) {
return mk_and(ge(k, n, ws, xs), le(k, n, ws, xs));
#if 0
m_t = EQ;
return cmp(k, n, ws, xs);
#endif
}
literal cmp(unsigned k, unsigned n, unsigned const* ws, literal const* xs) {
unsigned w_max = 0, sum = 0;
literal_vector Xs;
unsigned_vector Ws;
for (unsigned i = 0; i < n; ++i) {
sum += ws[i];
w_max = std::max(ws[i], w_max);
Xs.push_back(xs[i]);
Ws.push_back(ws[i]);
}
if (sum < k) {
return ctx.mk_false();
}
// Normalize to form Ws*Xs ~ a*2^{q-1}
SASSERT(w_max > 0);
unsigned bits = 0;
while (w_max > 0) {
bits++;
w_max >>= 1;
}
unsigned pow = (1ul << (bits-1));
unsigned a = (k + pow - 1) / pow; // a*pow >= k
SASSERT(a*pow >= k);
SASSERT((a-1)*pow < k);
if (a*pow > k) {
Ws.push_back(a*pow - k);
Xs.push_back(ctx.mk_true());
++n;
k = a*pow;
}
literal_vector W, We, B, S, E;
for (unsigned i = 0; i < bits; ++i) {
// B is digits from Xs that are set at bit position i
B.reset();
for (unsigned j = 0; j < n; ++j) {
if (0 != ((1 << i) & Ws[j])) {
B.push_back(Xs[j]);
}
}
// We is every second position of W
We.reset();
for (unsigned j = 0; j + 2 <= W.size(); j += 2) {
We.push_back(W[j+1]);
}
// if we test for equality, then what is not included has to be false.
if (m_t == EQ && W.size() % 2 == 1) {
E.push_back(mk_not(W.back()));
}
// B is the sorted (from largest to smallest bit) version of S
S.reset();
sorting(B.size(), B.begin(), S);
// W is the merge of S and We
W.reset();
merge(S.size(), S.begin(), We.size(), We.begin(), W);
}
if (m_t == EQ) {
E.push_back(W[a - 1]);
if (a < W.size()) E.push_back(mk_not(W[a]));
return mk_and(E);
}
SASSERT(m_t == GE_FULL);
return W[a - 1];
}
private: