3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 17:15:31 +00:00

add circuit and unate encoding besides sorting option

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2018-07-06 21:09:13 -07:00
parent 0b30ddb769
commit 3ae0ea8246
8 changed files with 488 additions and 184 deletions

View file

@ -25,16 +25,22 @@ Notes:
#define SORTING_NETWORK_H_
enum sorting_network_encoding {
grouped_at_most_1,
bimander_at_most_1,
ordered_at_most_1
sorted_at_most,
grouped_at_most,
bimander_at_most,
ordered_at_most,
unate_at_most,
circuit_at_most
};
inline std::ostream& operator<<(std::ostream& out, sorting_network_encoding enc) {
switch (enc) {
case grouped_at_most_1: return out << "grouped";
case bimander_at_most_1: return out << "bimander";
case ordered_at_most_1: return out << "ordered";
case grouped_at_most: return out << "grouped";
case bimander_at_most: return out << "bimander";
case ordered_at_most: return out << "ordered";
case sorted_at_most: return out << "sorted";
case unate_at_most: return out << "unate";
case circuit_at_most: return out << "circuit";
}
return out << "???";
}
@ -42,7 +48,7 @@ Notes:
struct sorting_network_config {
sorting_network_encoding m_encoding;
sorting_network_config() {
m_encoding = grouped_at_most_1;
m_encoding = sorted_at_most;
}
};
@ -158,12 +164,19 @@ Notes:
vc operator+(vc const& other) const {
return vc(v + other.v, c + other.c);
}
vc operator-(vc const& other) const {
return vc(v - other.v, c - other.c);
}
unsigned to_int() const {
return lambda*v + c;
}
vc operator*(unsigned n) const {
return vc(n*v, n*c);
}
std::ostream& pp(std::ostream& out) const {
return out << "v: " << v << " c: " << c;
}
};
static vc mk_min(vc const& v1, vc const& v2) {
@ -176,13 +189,17 @@ Notes:
cmp_t m_t;
// for testing
static const bool m_disable_dcard = false;
static const bool m_disable_dsorting = true; // false;
static const bool m_disable_dsmerge = true; // false;
static const bool m_disable_dcard = false;
static const bool m_disable_dsorting = false;
static const bool m_disable_dsmerge = false;
static const bool m_force_dcard = false;
static const bool m_force_dsorting = false;
static const bool m_force_dsmerge = false;
bool is_power_of2(unsigned n) const {
return n != 0 && ((n-1) & n) == 0;
}
public:
struct stats {
unsigned m_num_compiled_vars;
@ -221,15 +238,31 @@ Notes:
}
SASSERT(0 < k && k <= n);
literal_vector in, out;
if (k == 1) {
return mk_or(n, xs);
}
if (dualize(k, n, xs, in)) {
return le(full, k, in.size(), in.c_ptr());
}
else {
SASSERT(2*k <= n);
m_t = full?GE_FULL:GE;
// scoped_stats _ss(m_stats, k, n);
psort_nw<psort_expr>::card(k, n, xs, out);
return out[k-1];
switch (m_cfg.m_encoding) {
case sorted_at_most:
case bimander_at_most:
case ordered_at_most:
case grouped_at_most:
SASSERT(2*k <= n);
m_t = full?GE_FULL:GE;
// scoped_stats _ss(m_stats, k, n);
psort_nw<psort_expr>::card(k, n, xs, out);
return out[k-1];
case unate_at_most:
return unate_ge(full, k, n, xs);
case circuit_at_most:
return circuit_ge(full, k, n, xs);
default:
UNREACHABLE();
return xs[0];
}
}
}
@ -246,23 +279,40 @@ Notes:
literal_vector ors;
// scoped_stats _ss(m_stats, k, n);
switch (m_cfg.m_encoding) {
case grouped_at_most_1:
case grouped_at_most:
case sorted_at_most:
case unate_at_most:
case circuit_at_most:
return mk_at_most_1(full, n, xs, ors, false);
case bimander_at_most_1:
case bimander_at_most:
return mk_at_most_1_bimander(full, n, xs, ors);
case ordered_at_most_1:
case ordered_at_most:
return mk_ordered_atmost_1(full, n, xs);
default:
UNREACHABLE();
return xs[0];
}
}
else {
SASSERT(2*k <= n);
m_t = full?LE_FULL:LE;
// scoped_stats _ss(m_stats, k, n);
card(k + 1, n, xs, out);
return ctx.mk_not(out[k]);
switch (m_cfg.m_encoding) {
case sorted_at_most:
case bimander_at_most:
case ordered_at_most:
case grouped_at_most:
SASSERT(2*k <= n);
m_t = full?LE_FULL:LE;
// scoped_stats _ss(m_stats, k, n);
card(k + 1, n, xs, out);
return mk_not(out[k]);
case unate_at_most:
return unate_le(full, k, n, xs);
case circuit_at_most:
return circuit_le(full, k, n, xs);
default:
UNREACHABLE();
return xs[0];
}
}
}
@ -280,16 +330,29 @@ Notes:
return mk_exactly_1(full, n, xs);
}
else {
// scoped_stats _ss(m_stats, k, n);
SASSERT(2*k <= n);
m_t = EQ;
card(k+1, n, xs, out);
SASSERT(out.size() >= k+1);
if (k == 0) {
return ctx.mk_not(out[k]);
}
else {
return ctx.mk_min(out[k-1], ctx.mk_not(out[k]));
switch (m_cfg.m_encoding) {
case sorted_at_most:
case bimander_at_most:
case grouped_at_most:
case ordered_at_most:
// scoped_stats _ss(m_stats, k, n);
SASSERT(2*k <= n);
m_t = EQ;
card(k+1, n, xs, out);
SASSERT(out.size() >= k+1);
if (k == 0) {
return mk_not(out[k]);
}
else {
return mk_min(out[k-1], mk_not(out[k]));
}
case unate_at_most:
return unate_eq(k, n, xs);
case circuit_at_most:
return circuit_eq(k, n, xs);
default:
UNREACHABLE();
return xs[0];
}
}
}
@ -297,49 +360,193 @@ Notes:
private:
// perform unate addition up to k.
literal unate_cmp(cmp_t cmp, unsigned k, unsigned n, literal const* xs) {
unsigned last = k;
if (cmp == LE || cmp == EQ || cmp == LE_FULL) {
last = k + 1;
}
bool full = cmp == LE_FULL || cmp == GE_FULL;
literal_vector carry;
for (unsigned i = 0; i < last; ++i) {
carry.push_back(ctx.mk_false());
}
for (unsigned i = 0; i < n; ++i) {
for (unsigned j = last; j-- > 0; ) {
// c'[j] <-> (xs[i] & c[j-1]) | c[j]
literal c0 = j > 0 ? carry[j-1] : ctx.mk_true();
carry[j] = mk_or(mk_and(xs[i], c0), carry[j]);
}
}
switch (cmp) {
case LE:
case LE_FULL:
return mk_not(carry[k]);
case GE:
case GE_FULL:
return carry[k-1];
case EQ:
return mk_and(mk_not(carry[k]), carry[k-1]);
default:
UNREACHABLE();
return xs[0];
}
}
literal unate_ge(bool full, unsigned k, unsigned n, literal const* xs) {
return unate_cmp(full ? GE_FULL : GE, k, n, xs);
}
literal unate_le(bool full, unsigned k, unsigned n, literal const* xs) {
return unate_cmp(full ? LE_FULL : LE, k, n, xs);
}
literal unate_eq(unsigned k, unsigned n, literal const* xs) {
return unate_cmp(EQ, k, n, xs);
}
// circuit encoding
void mk_unit_circuit(unsigned k, literal x, literal_vector& out) {
out.push_back(x);
for (unsigned i = 1; i < k; ++i) out.push_back(ctx.mk_false());
}
literal mk_add_circuit(literal_vector const& x, literal_vector const& y, literal_vector& out) {
literal c = ctx.mk_false();
SASSERT(x.size() == y.size());
for (unsigned i = 0; i < x.size(); ++i) {
// out[i] = c + x[i] + y[i]
// c' = c&x[i] | c&y[i] | x[i]&y[i];
literal_vector ors;
ors.push_back(mk_and(c, mk_not(x[i]), mk_not(y[i])));
ors.push_back(mk_and(x[i], mk_not(c), mk_not(y[i])));
ors.push_back(mk_and(y[i], mk_not(c), mk_not(x[i])));
ors.push_back(mk_and(c, x[i], y[i]));
literal o = mk_or(4, ors.c_ptr());
out.push_back(o);
ors[0] = mk_and(c, x[i]);
ors[1] = mk_and(c, y[i]);
ors[2] = mk_and(x[i], y[i]);
c = mk_or(3, ors.c_ptr());
}
return c;
}
literal circuit_add(unsigned k, unsigned n, literal const* xs, literal_vector& out) {
switch (n) {
case 0:
for (unsigned i = 0; i < k; ++i) {
out.push_back(ctx.mk_false());
}
return ctx.mk_false();
case 1:
mk_unit_circuit(k, xs[0], out);
return ctx.mk_false();
default: {
literal_vector o1, o2;
unsigned half = n / 2;
literal ovfl1 = circuit_add(k, half, xs, o1);
literal ovfl2 = circuit_add(k, n - half, xs + half, o2);
literal ovfl3 = mk_add_circuit(o1, o2, out);
return mk_or(ovfl1, ovfl2, ovfl3);
}
}
}
literal circuit_cmp(cmp_t cmp, unsigned k, unsigned n, literal const* xs) {
literal_vector out, kvec;
unsigned num_bits = 0;
unsigned k1 = (cmp == LE || cmp == LE_FULL) ? k + 1 : k;
unsigned k0 = k1;
while (k0 > 0) { ++num_bits; k0 >>= 1; }
for (unsigned i = 0; i < num_bits; ++i) {
kvec.push_back((0 != (k1 & (1 << i))) ? ctx.mk_true() : ctx.mk_false());
}
literal ovfl = circuit_add(num_bits, n, xs, out);
switch (cmp) {
case LE:
case LE_FULL:
return mk_not(mk_or(ovfl, mk_ge(out, kvec)));
case GE:
case GE_FULL:
return mk_or(ovfl, mk_ge(out, kvec));
case EQ: {
literal_vector eqs;
SASSERT(kvec.size() == out.size());
for (unsigned i = 0; i < num_bits; ++i) {
eqs.push_back(mk_or(mk_not(kvec[i]), out[i]));
eqs.push_back(mk_or(kvec[i], mk_not(out[i])));
}
eqs.push_back(mk_not(ovfl));
return mk_and(eqs);
}
default:
UNREACHABLE();
return xs[0];
}
}
literal mk_ge(literal_vector const& x, literal_vector const& y) {
literal r = ctx.mk_true();
literal g = ctx.mk_false();
for (unsigned j = x.size(); j-- > 0; ) {
g = mk_or(g, mk_and(r, mk_and(x[j], mk_not(y[j]))));
r = mk_or(g, mk_and(r, mk_or( x[j], mk_not(y[j]))));
}
return r;
}
literal circuit_ge(bool full, unsigned k, unsigned n, literal const* xs) {
return circuit_cmp(full ? GE_FULL : GE, k, n, xs);
}
literal circuit_le(bool full, unsigned k, unsigned n, literal const* xs) {
return circuit_cmp(full ? LE_FULL : LE, k, n, xs);
}
literal circuit_eq(unsigned k, unsigned n, literal const* xs) {
return circuit_cmp(EQ, k, n, xs);
}
void add_implies_or(literal l, unsigned n, literal const* xs) {
literal_vector lits(n, xs);
lits.push_back(ctx.mk_not(l));
lits.push_back(mk_not(l));
add_clause(lits);
}
void add_or_implies(literal l, unsigned n, literal const* xs) {
for (unsigned j = 0; j < n; ++j) {
add_clause(ctx.mk_not(xs[j]), l);
literal mk_or(unsigned n, literal const* _ors) {
literal_vector ors(n, _ors);
unsigned j = 0;
for (literal lit : ors) {
if (is_true(lit)) return lit;
if (!is_false(lit)) ors[j++] = lit;
}
}
literal mk_or(unsigned n, literal const* ors) {
if (n == 1) {
return ors[0];
ors.shrink(j);
switch (j) {
case 0: return ctx.mk_false();
case 1: return ors[0];
default: return ctx.mk_max(ors.size(), ors.c_ptr());
}
literal result = fresh("or");
add_implies_or(result, n, ors);
add_or_implies(result, n, ors);
return result;
}
literal mk_or(literal l1, literal l2) {
literal ors[2] = { l1, l2 };
return mk_or(2, ors);
}
literal mk_or(literal l1, literal l2, literal l3) {
literal ors[3] = { l1, l2, l3 };
return mk_or(3, ors);
}
literal mk_or(literal_vector const& ors) {
return mk_or(ors.size(), ors.c_ptr());
}
void add_implies_and(literal l, literal_vector const& xs) {
for (literal const& x : xs) {
add_clause(ctx.mk_not(l), x);
}
}
void add_and_implies(literal l, literal_vector const& xs) {
literal_vector lits;
for (literal const& x : xs) {
lits.push_back(ctx.mk_not(x));
}
lits.push_back(l);
add_clause(lits);
literal mk_not(literal lit) {
if (is_true(lit)) return ctx.mk_false();
if (is_false(lit)) return ctx.mk_true();
return ctx.mk_not(lit);
}
literal mk_and(literal l1, literal l2) {
@ -348,14 +555,39 @@ Notes:
return mk_and(xs);
}
literal mk_and(literal_vector const& ands) {
if (ands.size() == 1) {
return ands[0];
literal mk_and(literal l1, literal l2, literal l3) {
literal_vector xs;
xs.push_back(l1); xs.push_back(l2); xs.push_back(l3);
return mk_and(xs);
}
bool is_true(literal l) {
return l == ctx.mk_true();
}
bool is_false(literal l) {
return l == ctx.mk_false();
}
literal mk_and(literal_vector const& _ands) {
literal_vector ands(_ands);
unsigned j = 0;
for (literal lit : ands) {
if (is_false(lit)) return lit;
if (!is_true(lit)) ands[j++] = lit;
}
ands.shrink(j);
switch (j) {
case 0:
return ctx.mk_true();
case 1:
return ands[0];
case 2:
return mk_min(ands[0], ands[1]);
default: {
return ctx.mk_min(ands.size(), ands.c_ptr());
}
}
literal result = fresh("and");
add_implies_and(result, ands);
add_and_implies(result, ands);
return result;
}
literal mk_exactly_1(bool full, unsigned n, literal const* xs) {
@ -363,13 +595,16 @@ Notes:
literal_vector ors;
literal r1;
switch (m_cfg.m_encoding) {
case grouped_at_most_1:
case grouped_at_most:
case sorted_at_most:
case unate_at_most:
case circuit_at_most:
r1 = mk_at_most_1(full, n, xs, ors, true);
break;
case bimander_at_most_1:
case bimander_at_most:
r1 = mk_at_most_1_bimander(full, n, xs, ors);
break;
case ordered_at_most_1:
case ordered_at_most:
return mk_ordered_exactly_1(full, n, xs);
default:
UNREACHABLE();
@ -426,7 +661,7 @@ Notes:
// 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]));
add_clause(mk_not(result), mk_not(xs[i]), mk_not(xs[j]));
}
}
@ -441,7 +676,7 @@ Notes:
}
add_clause(lits);
}
ands.push_back(ctx.mk_not(and_i));
ands.push_back(mk_not(and_i));
}
}
@ -457,7 +692,7 @@ Notes:
literal_vector ands;
for (unsigned i = 0; i < n; ++i) {
for (unsigned j = i + 1; j < n; ++j) {
ands.push_back(mk_or(ctx.mk_not(xs[i]), ctx.mk_not(xs[j])));
ands.push_back(mk_or(mk_not(xs[i]), mk_not(xs[j])));
}
}
return mk_and(ands);
@ -513,36 +748,36 @@ Notes:
ys.push_back(fresh("y"));
}
for (unsigned i = 0; i + 2 < n; ++i) {
add_clause(ctx.mk_not(ys[i]), ys[i + 1]);
add_clause(mk_not(ys[i]), ys[i + 1]);
}
for (unsigned i = 0; i + 1 < n; ++i) {
add_clause(ctx.mk_not(xs[i]), ys[i]);
add_clause(ctx.mk_not(r), ctx.mk_not(ys[i]), ctx.mk_not(xs[i + 1]));
add_clause(mk_not(xs[i]), ys[i]);
add_clause(mk_not(r), mk_not(ys[i]), mk_not(xs[i + 1]));
}
if (is_eq) {
add_clause(ctx.mk_not(r), ys[n-2], xs[n-1]);
add_clause(mk_not(r), ys[n-2], xs[n-1]);
}
for (unsigned i = 1; i < n - 1; ++i) {
add_clause(ctx.mk_not(ys[i]), xs[i], ys[i-1]);
add_clause(mk_not(ys[i]), xs[i], ys[i-1]);
}
add_clause(ctx.mk_not(ys[0]), xs[0]);
add_clause(mk_not(ys[0]), xs[0]);
if (full) {
literal_vector twos;
for (unsigned i = 0; i < n - 1; ++i) {
twos.push_back(fresh("two"));
}
add_clause(ctx.mk_not(twos[0]), ys[0]);
add_clause(ctx.mk_not(twos[0]), xs[1]);
add_clause(mk_not(twos[0]), ys[0]);
add_clause(mk_not(twos[0]), xs[1]);
for (unsigned i = 1; i < n - 1; ++i) {
add_clause(ctx.mk_not(twos[i]), ys[i], twos[i-1]);
add_clause(ctx.mk_not(twos[i]), xs[i + 1], twos[i-1]);
add_clause(mk_not(twos[i]), ys[i], twos[i-1]);
add_clause(mk_not(twos[i]), xs[i + 1], twos[i-1]);
}
if (is_eq) {
literal zero = fresh("zero");
add_clause(ctx.mk_not(zero), ctx.mk_not(xs[n-1]));
add_clause(ctx.mk_not(zero), ctx.mk_not(ys[n-2]));
add_clause(mk_not(zero), mk_not(xs[n-1]));
add_clause(mk_not(zero), mk_not(ys[n-2]));
add_clause(r, zero, twos.back());
}
else {
@ -579,7 +814,7 @@ Notes:
for (unsigned 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]));
add_clause(mk_not(result), mk_not(ors[i]), bit_set ? bits[k] : mk_not(bits[k]));
}
}
return result;
@ -608,7 +843,7 @@ Notes:
}
k = N - k;
for (unsigned i = 0; i < N; ++i) {
in.push_back(ctx.mk_not(xs[i]));
in.push_back(mk_not(xs[i]));
}
TRACE("pb_verbose",
//pp(tout << N << ": ", in);
@ -627,13 +862,15 @@ Notes:
literal mk_max(literal a, literal b) {
if (a == b) return a;
m_stats.m_num_compiled_vars++;
return ctx.mk_max(a, b);
literal lits[2] = { a, b};
return ctx.mk_max(2, lits);
}
literal mk_min(literal a, literal b) {
if (a == b) return a;
m_stats.m_num_compiled_vars++;
return ctx.mk_min(a, b);
literal lits[2] = { a, b};
return ctx.mk_min(2, lits);
}
literal fresh(char const* n) {
@ -652,6 +889,9 @@ Notes:
add_clause(lits.size(), lits.c_ptr());
}
void add_clause(unsigned n, literal const* ls) {
for (unsigned i = 0; i < n; ++i) {
if (is_true(ls[i])) return;
}
m_stats.m_num_compiled_clauses++;
m_stats.m_num_clause_vars += n;
literal_vector tmp(n, ls);
@ -661,17 +901,17 @@ Notes:
// y1 <= mk_max(x1,x2)
// y2 <= mk_min(x1,x2)
void cmp_ge(literal x1, literal x2, literal y1, literal y2) {
add_clause(ctx.mk_not(y2), x1);
add_clause(ctx.mk_not(y2), x2);
add_clause(ctx.mk_not(y1), x1, x2);
add_clause(mk_not(y2), x1);
add_clause(mk_not(y2), x2);
add_clause(mk_not(y1), x1, x2);
}
// mk_max(x1,x2) <= y1
// mk_min(x1,x2) <= y2
void cmp_le(literal x1, literal x2, literal y1, literal y2) {
add_clause(ctx.mk_not(x1), y1);
add_clause(ctx.mk_not(x2), y1);
add_clause(ctx.mk_not(x1), ctx.mk_not(x2), y2);
add_clause(mk_not(x1), y1);
add_clause(mk_not(x2), y1);
add_clause(mk_not(x1), mk_not(x2), y2);
}
void cmp_eq(literal x1, literal x2, literal y1, literal y2) {
@ -773,6 +1013,8 @@ Notes:
}
TRACE("pb_verbose", tout << "merge a: " << a << " b: " << b << " ";
tout << "num clauses " << m_stats.m_num_compiled_clauses - nc << "\n";
vc_dsmerge(a, b, a + b).pp(tout << "vc_dsmerge ") << "\n";
vc_smerge_rec(a, b, a + b).pp(tout << "vc_smerge_rec ") << "\n";
//pp(tout << "a:", a, as) << "\n";
//pp(tout << "b:", b, bs) << "\n";
//pp(tout << "out:", out) << "\n";
@ -796,7 +1038,8 @@ Notes:
return
vc_merge(ceil2(a), ceil2(b)) +
vc_merge(floor2(a), floor2(b)) +
vc_interleave(ceil2(a) + ceil2(b), floor2(a) + floor2(b));
vc_interleave(ceil2(a) + ceil2(b), floor2(a) + floor2(b)) -
vc(0, 2);
}
void split(unsigned n, literal const* ls, literal_vector& even, literal_vector& odd) {
for (unsigned i = 0; i < n; i += 2) {
@ -914,12 +1157,12 @@ Notes:
if (m_t != GE) {
// x1 <= mk_max(x1,x2)
// x2 <= mk_max(x1,x2)
add_clause(ctx.mk_not(as[0]), y);
add_clause(ctx.mk_not(bs[0]), y);
add_clause(mk_not(as[0]), y);
add_clause(mk_not(bs[0]), y);
}
if (m_t != LE) {
// mk_max(x1,x2) <= x1, x2
add_clause(ctx.mk_not(y), as[0], bs[0]);
add_clause(mk_not(y), as[0], bs[0]);
}
out.push_back(y);
}
@ -970,11 +1213,11 @@ Notes:
out2.pop_back();
y = mk_max(z1, z2);
if (m_t != GE) {
add_clause(ctx.mk_not(z1), y);
add_clause(ctx.mk_not(z2), y);
add_clause(mk_not(z1), y);
add_clause(mk_not(z2), y);
}
if (m_t != LE) {
add_clause(ctx.mk_not(y), z1, z2);
add_clause(mk_not(y), z1, z2);
}
}
interleave(out1, out2, out);
@ -1018,7 +1261,7 @@ Notes:
return
m_force_dsmerge ||
(!m_disable_dsmerge &&
a < (1 << 7) && b < (1 << 7) &&
a < 10 && b < 10 &&
vc_dsmerge(a, b, a + b) < vc_smerge_rec(a, b, c));
}
@ -1027,7 +1270,7 @@ Notes:
unsigned a, literal const* as,
unsigned b, literal const* bs,
literal_vector& out) {
TRACE("pb_verbose", tout << "dsmerge: c:" << c << " a:" << a << " b:" << b << "\n";);
unsigned nc = m_stats.m_num_compiled_clauses;
SASSERT(a <= c);
SASSERT(b <= c);
SASSERT(a + b >= c);
@ -1036,14 +1279,14 @@ Notes:
}
if (m_t != GE) {
for (unsigned i = 0; i < a; ++i) {
add_clause(ctx.mk_not(as[i]), out[i]);
add_clause(mk_not(as[i]), out[i]);
}
for (unsigned i = 0; i < b; ++i) {
add_clause(ctx.mk_not(bs[i]), out[i]);
add_clause(mk_not(bs[i]), out[i]);
}
for (unsigned i = 1; i <= a; ++i) {
for (unsigned j = 1; j <= b && i + j <= c; ++j) {
add_clause(ctx.mk_not(as[i-1]),ctx.mk_not(bs[j-1]),out[i+j-1]);
add_clause(mk_not(as[i-1]),mk_not(bs[j-1]),out[i+j-1]);
}
}
}
@ -1051,12 +1294,12 @@ Notes:
literal_vector ls;
for (unsigned k = 0; k < c; ++k) {
ls.reset();
ls.push_back(ctx.mk_not(out[k]));
ls.push_back(mk_not(out[k]));
if (a <= k) {
add_clause(ctx.mk_not(out[k]), bs[k-a]);
add_clause(mk_not(out[k]), bs[k-a]);
}
if (b <= k) {
add_clause(ctx.mk_not(out[k]), as[k-b]);
add_clause(mk_not(out[k]), as[k-b]);
}
for (unsigned i = 0; i < std::min(a,k + 1); ++i) {
unsigned j = k - i;
@ -1071,7 +1314,13 @@ Notes:
}
}
}
TRACE("pb_verbose", tout << "dsmerge: c:" << c << " a:" << a << " b:" << b << " ";
tout << "num clauses: " << m_stats.m_num_compiled_clauses - nc << "\n";
vc_dsmerge(a, b, c).pp(tout << "vc_dsmerge ") << "\n";
vc_smerge_rec(a, b, c).pp(tout << "vc_smerge_rec ") << "\n";
);
}
vc vc_dsmerge(unsigned a, unsigned b, unsigned c) {
vc v(c, 0);
if (m_t != GE) {
@ -1101,7 +1350,7 @@ Notes:
}
if (m_t != LE) {
for (unsigned k = 1; k <= m; ++k) {
lits.push_back(ctx.mk_not(out[k-1]));
lits.push_back(mk_not(out[k-1]));
add_subset(false, n-k+1, 0, lits, n, xs);
lits.pop_back();
}
@ -1134,7 +1383,7 @@ Notes:
return;
}
for (unsigned i = offset; i < n - k + 1; ++i) {
lits.push_back(polarity?ctx.mk_not(xs[i]):xs[i]);
lits.push_back(polarity?mk_not(xs[i]):xs[i]);
add_subset(polarity, k-1, i+1, lits, n, xs);
lits.pop_back();
}