mirror of
https://github.com/Z3Prover/z3
synced 2025-04-29 11:55:51 +00:00
updates to sorting networks
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
3c4ac9aee5
commit
edb3569599
18 changed files with 2070 additions and 170 deletions
|
@ -24,6 +24,28 @@ Notes:
|
|||
#ifndef SORTING_NETWORK_H_
|
||||
#define SORTING_NETWORK_H_
|
||||
|
||||
enum sorting_network_encoding {
|
||||
grouped_at_most_1,
|
||||
bimander_at_most_1,
|
||||
ordered_at_most_1
|
||||
};
|
||||
|
||||
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";
|
||||
}
|
||||
return out << "???";
|
||||
}
|
||||
|
||||
struct sorting_network_config {
|
||||
sorting_network_encoding m_encoding;
|
||||
sorting_network_config() {
|
||||
m_encoding = grouped_at_most_1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Ext>
|
||||
class sorting_network {
|
||||
typedef typename Ext::vector vect;
|
||||
|
@ -88,7 +110,7 @@ Notes:
|
|||
}
|
||||
|
||||
public:
|
||||
sorting_network(Ext& ext):
|
||||
sorting_network(Ext& ext):
|
||||
m_ext(ext),
|
||||
m_current(&m_currentv),
|
||||
m_next(&m_nextv)
|
||||
|
@ -121,6 +143,7 @@ Notes:
|
|||
class psort_nw {
|
||||
typedef typename psort_expr::literal literal;
|
||||
typedef typename psort_expr::literal_vector literal_vector;
|
||||
sorting_network_config m_cfg;
|
||||
|
||||
class vc {
|
||||
unsigned v; // number of vertices
|
||||
|
@ -185,7 +208,7 @@ Notes:
|
|||
}
|
||||
};
|
||||
|
||||
psort_nw(psort_expr& c): ctx(c) {}
|
||||
psort_nw(psort_expr& c, sorting_network_config const& cfg): ctx(c), m_cfg(cfg) {}
|
||||
|
||||
literal ge(bool full, unsigned k, unsigned n, literal const* xs) {
|
||||
if (k > n) {
|
||||
|
@ -220,7 +243,17 @@ Notes:
|
|||
else if (k == 1) {
|
||||
literal_vector ors;
|
||||
// scoped_stats _ss(m_stats, k, n);
|
||||
return mk_at_most_1(full, n, xs, ors, false);
|
||||
switch (m_cfg.m_encoding) {
|
||||
case grouped_at_most_1:
|
||||
return mk_at_most_1(full, n, xs, ors, false);
|
||||
case bimander_at_most_1:
|
||||
return mk_at_most_1_bimander(full, n, xs, ors);
|
||||
case ordered_at_most_1:
|
||||
return mk_ordered_atmost_1(full, n, xs);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return xs[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
SASSERT(2*k <= n);
|
||||
|
@ -278,7 +311,7 @@ Notes:
|
|||
if (n == 1) {
|
||||
return ors[0];
|
||||
}
|
||||
literal result = fresh();
|
||||
literal result = fresh("or");
|
||||
add_implies_or(result, n, ors);
|
||||
add_or_implies(result, n, ors);
|
||||
return result;
|
||||
|
@ -317,15 +350,26 @@ Notes:
|
|||
if (ands.size() == 1) {
|
||||
return ands[0];
|
||||
}
|
||||
literal result = fresh();
|
||||
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) {
|
||||
TRACE("pb", tout << "exactly 1 with " << n << " arguments " << (full?"full":"not full") << "\n";);
|
||||
literal_vector ors;
|
||||
literal r1 = mk_at_most_1(full, n, xs, ors, true);
|
||||
literal r1;
|
||||
switch (m_cfg.m_encoding) {
|
||||
case grouped_at_most_1:
|
||||
r1 = mk_at_most_1(full, n, xs, ors, true);
|
||||
break;
|
||||
case bimander_at_most_1:
|
||||
r1 = mk_at_most_1_bimander(full, n, xs, ors);
|
||||
break;
|
||||
case ordered_at_most_1:
|
||||
return mk_ordered_exactly_1(full, n, xs);
|
||||
}
|
||||
|
||||
if (full) {
|
||||
r1 = mk_and(r1, mk_or(ors));
|
||||
|
@ -340,12 +384,8 @@ Notes:
|
|||
TRACE("pb_verbose", tout << (full?"full":"partial") << " ";
|
||||
for (unsigned i = 0; i < n; ++i) tout << xs[i] << " ";
|
||||
tout << "\n";);
|
||||
|
||||
if (n >= 4 && false) {
|
||||
return mk_at_most_1_bimander(full, n, xs, ors);
|
||||
}
|
||||
literal_vector in(n, xs);
|
||||
literal result = fresh();
|
||||
literal result = fresh("at-most-1");
|
||||
unsigned inc_size = 4;
|
||||
literal_vector ands;
|
||||
ands.push_back(result);
|
||||
|
@ -387,7 +427,7 @@ Notes:
|
|||
|
||||
// xs[0] + ... + xs[n-1] <= 1 => and_x
|
||||
if (full) {
|
||||
literal and_i = fresh();
|
||||
literal and_i = fresh("and");
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
literal_vector lits;
|
||||
lits.push_back(and_i);
|
||||
|
@ -407,29 +447,6 @@ Notes:
|
|||
}
|
||||
|
||||
|
||||
#if 0
|
||||
literal result = fresh();
|
||||
|
||||
// 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]));
|
||||
}
|
||||
}
|
||||
|
||||
// xs[0] + ... + xs[n-1] <= 1 => result
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
literal_vector lits;
|
||||
lits.push_back(result);
|
||||
for (unsigned j = 0; j < n; ++j) {
|
||||
if (j != i) lits.push_back(xs[j]);
|
||||
}
|
||||
add_clause(lits);
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif
|
||||
#if 1
|
||||
// r <=> and( or(!xi,!xj))
|
||||
//
|
||||
literal_vector ands;
|
||||
|
@ -439,30 +456,100 @@ Notes:
|
|||
}
|
||||
}
|
||||
return mk_and(ands);
|
||||
#else
|
||||
// r <=> or (and !x_{j != i})
|
||||
|
||||
literal_vector ors;
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
literal_vector ands;
|
||||
for (unsigned j = 0; j < n; ++j) {
|
||||
if (j != i) {
|
||||
ands.push_back(ctx.mk_not(xs[j]));
|
||||
}
|
||||
}
|
||||
ors.push_back(mk_and(ands));
|
||||
}
|
||||
return mk_or(ors);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
literal mk_ordered_exactly_1(bool full, unsigned n, literal const* xs) {
|
||||
return mk_ordered_1(full, true, n, xs);
|
||||
}
|
||||
|
||||
literal mk_ordered_atmost_1(bool full, unsigned n, literal const* xs) {
|
||||
return mk_ordered_1(full, false, n, xs);
|
||||
}
|
||||
|
||||
literal mk_ordered_1(bool full, bool is_eq, unsigned n, literal const* xs) {
|
||||
if (n <= 1 && !is_eq) return ctx.mk_true();
|
||||
if (n == 0) {
|
||||
return ctx.mk_false();
|
||||
}
|
||||
if (n == 1) {
|
||||
return xs[0];
|
||||
}
|
||||
|
||||
// y0 -> y1
|
||||
// x0 -> y0
|
||||
// x1 -> y1
|
||||
// r, y0 -> ~x1
|
||||
// r, y1 -> ~x2
|
||||
// r -> x3 | y1
|
||||
// r -> ~x3 | ~y1
|
||||
|
||||
// x0,x1,x2, .., x_{n-1}, x_n
|
||||
// y0,y1,y2, .., y_{n-1}
|
||||
// y_i -> y_{i+1} i = 0, ..., n - 2
|
||||
// x_i -> y_i i = 0, ..., n - 1
|
||||
// r, y_i -> ~x_{i+1} i = 0, ..., n - 1
|
||||
// exactly 1:
|
||||
// r -> x_n | y_{n-1}
|
||||
// full (exactly 1):
|
||||
// two_i -> y_i & x_{i+1}
|
||||
// zero -> ~x_n
|
||||
// zero -> ~y_{n-1}
|
||||
// r | zero | two_0 | ... | two_{n-1}
|
||||
// full atmost 1:
|
||||
// r | two | two_0 | ... | two_{n-1}
|
||||
|
||||
literal r = fresh("ordered");
|
||||
literal_vector ys;
|
||||
for (unsigned i = 0; i + 1 < n; ++i) {
|
||||
ys.push_back(fresh("y"));
|
||||
}
|
||||
for (unsigned i = 0; i + 2 < n; ++i) {
|
||||
add_clause(ctx.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(ctx.mk_not(r), ys[n-2], xs[n-1]);
|
||||
add_clause(ctx.mk_not(r), ctx.mk_not(ys[n-2]), ctx.mk_not(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(ctx.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]);
|
||||
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]);
|
||||
}
|
||||
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(r, zero, twos.back());
|
||||
}
|
||||
else {
|
||||
add_clause(r, twos.back());
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
literal mk_at_most_1_bimander(bool full, unsigned n, literal const* xs, literal_vector& ors) {
|
||||
if (full) {
|
||||
return mk_at_most_1(full, n, xs, ors, true);
|
||||
}
|
||||
literal_vector in(n, xs);
|
||||
literal result = fresh();
|
||||
literal result = fresh("bimander");
|
||||
unsigned inc_size = 2;
|
||||
literal_vector ands;
|
||||
for (unsigned i = 0; i < n; i += inc_size) {
|
||||
|
@ -477,7 +564,7 @@ Notes:
|
|||
}
|
||||
literal_vector bits;
|
||||
for (unsigned k = 0; k < nbits; ++k) {
|
||||
bits.push_back(fresh());
|
||||
bits.push_back(fresh("bit"));
|
||||
}
|
||||
for (unsigned i = 0; i < ors.size(); ++i) {
|
||||
for (unsigned k = 0; k < nbits; ++k) {
|
||||
|
@ -539,9 +626,9 @@ Notes:
|
|||
return ctx.mk_min(a, b);
|
||||
}
|
||||
|
||||
literal fresh() {
|
||||
literal fresh(char const* n) {
|
||||
m_stats.m_num_compiled_vars++;
|
||||
return ctx.fresh();
|
||||
return ctx.fresh(n);
|
||||
}
|
||||
void add_clause(literal l1, literal l2, literal l3) {
|
||||
literal lits[3] = { l1, l2, l3 };
|
||||
|
@ -558,7 +645,6 @@ Notes:
|
|||
m_stats.m_num_compiled_clauses++;
|
||||
m_stats.m_num_clause_vars += n;
|
||||
literal_vector tmp(n, ls);
|
||||
TRACE("pb_verbose", for (unsigned i = 0; i < n; ++i) tout << ls[i] << " "; tout << "\n";);
|
||||
ctx.mk_clause(n, tmp.c_ptr());
|
||||
}
|
||||
|
||||
|
@ -925,7 +1011,7 @@ Notes:
|
|||
SASSERT(b <= c);
|
||||
SASSERT(a + b >= c);
|
||||
for (unsigned i = 0; i < c; ++i) {
|
||||
out.push_back(fresh());
|
||||
out.push_back(fresh("dsmerge"));
|
||||
}
|
||||
if (m_t != GE) {
|
||||
for (unsigned i = 0; i < a; ++i) {
|
||||
|
@ -983,7 +1069,7 @@ Notes:
|
|||
SASSERT(m <= n);
|
||||
literal_vector lits;
|
||||
for (unsigned i = 0; i < m; ++i) {
|
||||
out.push_back(fresh());
|
||||
out.push_back(fresh("dsort"));
|
||||
}
|
||||
if (m_t != GE) {
|
||||
for (unsigned k = 1; k <= m; ++k) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue