3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 13:28:47 +00:00

tested network sorting

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2013-11-07 10:47:12 -08:00
parent 31e2d823c9
commit c57594d463
3 changed files with 140 additions and 42 deletions

View file

@ -15,11 +15,29 @@ Author:
Notes: Notes:
- count number of clauses per cardinality constraint. - Uses cutting plane simplification on 'k' for repeated literals.
- when number of conflicts exceeds n^2 or n*log(n), then create a sorting circuit. In other words, if the gcd of the multiplicity of literals in c3
where n is the arity of the cardinality constraint. is g, then divide through by g and truncate k.
- extra: do clauses get re-created? keep track of gc status of created clauses.
Example:
((_ at-most 3) x1 x1 x2 x2) == ((_ at-most 1) x1 x2)
- count number of clauses per cardinality constraint.
- TBD: when number of conflicts exceeds n^2 or n*log(n),
then create a sorting circuit.
where n is the arity of the cardinality constraint.
- TBD: do clauses get re-created? keep track of gc
status of created clauses.
- TBD: add conflict resolution
The idea is that if cardinality constraints c1, c2
are repeatedly asserted together, then
resolve them into combined cardinality constraint c3
c1 /\ c2 -> c3
--*/ --*/
#include "theory_card.h" #include "theory_card.h"

View file

@ -2,6 +2,9 @@
#include "sorting_network.h" #include "sorting_network.h"
#include "vector.h" #include "vector.h"
#include "ast.h" #include "ast.h"
#include "ast_pp.h"
#include "reg_decl_plugins.h"
struct ast_ext { struct ast_ext {
ast_manager& m; ast_manager& m;
@ -38,23 +41,100 @@ struct unsigned_ext {
} }
}; };
void tst_sorting_network() { static void is_sorted(svector<unsigned> const& v) {
svector<unsigned> vec; for (unsigned i = 0; i + 1 < v.size(); ++i) {
SASSERT(v[i] <= v[i+1]);
}
}
static void test_sorting1() {
svector<unsigned> in, out;
unsigned_ext uext; unsigned_ext uext;
sorting_network<unsigned_ext> sn(uext, vec); sorting_network<unsigned_ext> sn(uext);
svector<unsigned> in1; in.push_back(0);
in1.push_back(0); in.push_back(1);
in1.push_back(1); in.push_back(0);
in1.push_back(0); in.push_back(1);
in1.push_back(1); in.push_back(1);
in1.push_back(1); in.push_back(0);
in1.push_back(0);
sn(in1); sn(in, out);
for (unsigned i = 0; i < vec.size(); ++i) { is_sorted(out);
std::cout << vec[i]; for (unsigned i = 0; i < out.size(); ++i) {
std::cout << out[i];
} }
std::cout << "\n"; std::cout << "\n";
} }
static void test_sorting2() {
svector<unsigned> in, out;
unsigned_ext uext;
sorting_network<unsigned_ext> sn(uext);
in.push_back(0);
in.push_back(1);
in.push_back(2);
in.push_back(1);
in.push_back(1);
in.push_back(3);
sn(in, out);
is_sorted(out);
for (unsigned i = 0; i < out.size(); ++i) {
std::cout << out[i];
}
std::cout << "\n";
}
static void test_sorting4_r(unsigned i, svector<unsigned>& in) {
if (i == in.size()) {
svector<unsigned> out;
unsigned_ext uext;
sorting_network<unsigned_ext> sn(uext);
sn(in, out);
is_sorted(out);
std::cout << "sorted\n";
}
else {
in[i] = 0;
test_sorting4_r(i+1, in);
in[i] = 1;
test_sorting4_r(i+1, in);
}
}
static void test_sorting4() {
svector<unsigned> in;
in.resize(5);
test_sorting4_r(0, in);
}
void test_sorting3() {
ast_manager m;
reg_decl_plugins(m);
expr_ref_vector in(m), out(m);
for (unsigned i = 0; i < 7; ++i) {
in.push_back(m.mk_fresh_const("a",m.mk_bool_sort()));
}
for (unsigned i = 0; i < in.size(); ++i) {
std::cout << mk_pp(in[i].get(), m) << "\n";
}
ast_ext aext(m);
sorting_network<ast_ext> sn(aext);
sn(in, out);
std::cout << "size: " << out.size() << "\n";
for (unsigned i = 0; i < out.size(); ++i) {
std::cout << mk_pp(out[i].get(), m) << "\n";
}
}
void tst_sorting_network() {
test_sorting1();
test_sorting2();
test_sorting3();
test_sorting4();
}

View file

@ -7,7 +7,7 @@
template <typename Ext> template <typename Ext>
class sorting_network { class sorting_network {
typename Ext::vector& m_es; typedef typename Ext::vector vect;
Ext& m_ext; Ext& m_ext;
svector<unsigned> m_currentv; svector<unsigned> m_currentv;
svector<unsigned> m_nextv; svector<unsigned> m_nextv;
@ -17,21 +17,21 @@
unsigned& current(unsigned i) { return (*m_current)[i]; } unsigned& current(unsigned i) { return (*m_current)[i]; }
unsigned& next(unsigned i) { return (*m_next)[i]; } unsigned& next(unsigned i) { return (*m_next)[i]; }
void exchange(unsigned i, unsigned j) { void exchange(unsigned i, unsigned j, vect& out) {
SASSERT(i <= j); SASSERT(i <= j);
if (i < j) { if (i < j) {
Ext::T ei = m_es.get(i); Ext::T ei = out.get(i);
Ext::T ej = m_es.get(j); Ext::T ej = out.get(j);
m_es.set(i, m_ext.mk_ite(m_ext.mk_le(ei, ej), ei, ej)); out.set(i, m_ext.mk_ite(m_ext.mk_le(ei, ej), ei, ej));
m_es.set(j, m_ext.mk_ite(m_ext.mk_le(ej, ei), ei, ej)); out.set(j, m_ext.mk_ite(m_ext.mk_le(ej, ei), ei, ej));
} }
} }
void sort(unsigned k) { void sort(unsigned k, vect& out) {
SASSERT(is_power_of2(k) && k > 0); SASSERT(is_power_of2(k) && k > 0);
if (k == 2) { if (k == 2) {
for (unsigned i = 0; i < m_es.size()/2; ++i) { for (unsigned i = 0; i < out.size()/2; ++i) {
exchange(current(2*i), current(2*i+1)); exchange(current(2*i), current(2*i+1), out);
next(2*i) = current(2*i); next(2*i) = current(2*i);
next(2*i+1) = current(2*i+1); next(2*i+1) = current(2*i+1);
} }
@ -39,7 +39,7 @@
} }
else { else {
for (unsigned i = 0; i < m_es.size()/k; ++i) { for (unsigned i = 0; i < out.size()/k; ++i) {
unsigned ki = k * i; unsigned ki = k * i;
for (unsigned j = 0; j < k / 2; ++j) { for (unsigned j = 0; j < k / 2; ++j) {
next(ki + j) = current(ki + (2 * j)); next(ki + j) = current(ki + (2 * j));
@ -48,8 +48,8 @@
} }
std::swap(m_current, m_next); std::swap(m_current, m_next);
sort(k / 2); sort(k / 2, out);
for (unsigned i = 0; i < m_es.size() / k; ++i) { for (unsigned i = 0; i < out.size() / k; ++i) {
unsigned ki = k * i; unsigned ki = k * i;
for (unsigned j = 0; j < k / 2; ++j) { for (unsigned j = 0; j < k / 2; ++j) {
next(ki + (2 * j)) = current(ki + j); next(ki + (2 * j)) = current(ki + j);
@ -57,7 +57,7 @@
} }
for (unsigned j = 0; j < (k / 2) - 1; ++j) { for (unsigned j = 0; j < (k / 2) - 1; ++j) {
exchange(next(ki + (2 * j) + 1), next(ki + (2 * (j + 1)))); exchange(next(ki + (2 * j) + 1), next(ki + (2 * (j + 1))), out);
} }
} }
std::swap(m_current, m_next); std::swap(m_current, m_next);
@ -69,28 +69,28 @@
} }
public: public:
sorting_network(Ext& ext, typename Ext::vector& es): sorting_network(Ext& ext):
m_ext(ext), m_ext(ext),
m_es(es),
m_current(&m_currentv), m_current(&m_currentv),
m_next(&m_nextv) m_next(&m_nextv)
{} {}
void operator()(typename Ext::vector const& inputs) { void operator()(vect const& in, vect& out) {
if (inputs.size() <= 1) { if (in.size() <= 1) {
return; return;
} }
m_es.reset(); out.reset();
m_es.append(inputs); out.append(in);
while (!is_power_of2(m_es.size())) { while (!is_power_of2(out.size())) {
m_es.push_back(m_ext.mk_default()); out.push_back(m_ext.mk_default());
} }
for (unsigned i = 0; i < m_es.size(); ++i) { for (unsigned i = 0; i < out.size(); ++i) {
current(i) = i; m_currentv.push_back(i);
m_nextv.push_back(i);
} }
unsigned k = 2; unsigned k = 2;
while (k <= m_es.size()) { while (k <= out.size()) {
sort(k); sort(k, out);
k *= 2; k *= 2;
} }
} }