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

hilbert basis experiment

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2013-02-13 16:53:56 -08:00
parent 1317a71a1a
commit 0c641cdf95
3 changed files with 139 additions and 43 deletions

View file

@ -26,10 +26,10 @@ typedef u_map<unsigned> offset_refs_t;
template<typename Value> template<typename Value>
class rational_map : public map<rational, Value, rational::hash_proc, rational::eq_proc> {}; class rational_map : public map<rational, Value, rational::hash_proc, rational::eq_proc> {};
class rational_lt { class rational_abs_lt {
vector<rational> & m_values; vector<rational> & m_values;
public: public:
rational_lt(vector<rational> & values): rational_abs_lt(vector<rational> & values):
m_values(values) { m_values(values) {
} }
bool operator()(int v1, int v2) const { bool operator()(int v1, int v2) const {
@ -41,8 +41,8 @@ public:
class hilbert_basis::rational_heap { class hilbert_basis::rational_heap {
vector<numeral> m_u2r; // [index |-> weight] vector<numeral> m_u2r; // [index |-> weight]
rational_map<unsigned> m_r2u; // [weight |-> index] rational_map<unsigned> m_r2u; // [weight |-> index]
rational_lt m_lt; // less_than on indices rational_abs_lt m_lt; // less_than on indices
heap<rational_lt> m_heap; // binary heap over weights heap<rational_abs_lt> m_heap; // binary heap over weights
public: public:
rational_heap(): m_lt(m_u2r), m_heap(10, m_lt) {} rational_heap(): m_lt(m_u2r), m_heap(10, m_lt) {}
@ -76,9 +76,6 @@ public:
m_heap.find_le(val, result); m_heap.find_le(val, result);
} }
void find_le(numeral const& r, int_vector& result) {
find_le(m_r2u.find(r), result);
}
}; };
class hilbert_basis::weight_map { class hilbert_basis::weight_map {
@ -97,11 +94,12 @@ class hilbert_basis::weight_map {
unsigned m_cost; unsigned m_cost;
unsigned get_value(numeral const& w) { unsigned get_value(numeral const& w) {
numeral r = abs(w);
unsigned val; unsigned val;
if (!m_heap.is_declared(w, val)) { if (!m_heap.is_declared(r, val)) {
val = m_heap.declare(w); val = m_heap.declare(r);
SASSERT(val == m_offsets.size()); SASSERT(val == m_offsets.size());
if (w.is_nonneg()) { if (r.is_nonneg()) {
m_heap.insert(val); m_heap.insert(val);
} }
m_offsets.push_back(unsigned_vector()); m_offsets.push_back(unsigned_vector());
@ -121,6 +119,14 @@ public:
m_offsets[val].erase(idx.m_offset); m_offsets[val].erase(idx.m_offset);
} }
unsigned get_size() const {
unsigned sz = 0;
for (unsigned i = 0; i < m_offsets.size(); ++i) {
sz += m_offsets[i].size();
}
return sz;
}
void reset() { void reset() {
m_offsets.reset(); m_offsets.reset();
m_heap.reset(); m_heap.reset();
@ -129,6 +135,9 @@ public:
unsigned get_cost() const { return m_cost; } unsigned get_cost() const { return m_cost; }
/**
retrieve
*/
bool init_find(numeral const& w, offset_t idx) { bool init_find(numeral const& w, offset_t idx) {
m_le.reset(); m_le.reset();
m_found.reset(); m_found.reset();
@ -143,7 +152,7 @@ public:
m_le.push_back(val); m_le.push_back(val);
} }
for (unsigned i = 0; i < m_le.size(); ++i) { for (unsigned i = 0; i < m_le.size(); ++i) {
if (m_heap.u2r()[m_le[i]].is_zero() && w.is_pos()) { if (m_heap.u2r()[m_le[i]].is_zero() && !w.is_zero()) {
continue; continue;
} }
unsigned_vector const& offsets = m_offsets[m_le[i]]; unsigned_vector const& offsets = m_offsets[m_le[i]];
@ -159,16 +168,25 @@ public:
} }
return !m_found.empty(); return !m_found.empty();
} }
unsigned get_find_cost(numeral const& w) {
m_le.reset();
unsigned cost = 0;
unsigned val = get_value(w);
m_heap.find_le(val, m_le);
for (unsigned i = 0; i < m_le.size(); ++i) {
cost += m_offsets[m_le[i]].size();
}
return cost;
}
bool update_find(unsigned round, numeral const& w, offset_t idx) { bool update_find(unsigned round, numeral const& w, offset_t idx) {
//std::cout << "update find: " << w << "\n";
m_found.reset(); m_found.reset();
m_le.reset(); m_le.reset();
m_cost = 0; m_cost = 0;
m_heap.find_le(w, m_le); unsigned vl = get_value(w);
unsigned vl; m_heap.find_le(vl, m_le);
for (unsigned i = 0; i < m_le.size(); ++i) { for (unsigned i = 0; i < m_le.size(); ++i) {
//std::cout << "insert update find: " << m_weights[m_le[i]] << "\n";
unsigned_vector const& offsets = m_offsets[m_le[i]]; unsigned_vector const& offsets = m_offsets[m_le[i]];
for (unsigned j = 0; j < offsets.size(); ++j) { for (unsigned j = 0; j < offsets.size(); ++j) {
unsigned offs = offsets[j]; unsigned offs = offsets[j];
@ -255,9 +273,17 @@ public:
m_refs.reset(); m_refs.reset();
bool found = m_weight.init_find(vs.value(), idx); bool found = m_weight.init_find(vs.value(), idx);
TRACE("hilbert_basis", tout << "init: " << m_found.size() << " cost: " << m_weight.get_cost() << "\n";); TRACE("hilbert_basis", tout << "init: " << m_found.size() << " cost: " << m_weight.get_cost() << "\n";);
#if 0
std::cout << vs.value() << " " << m_found.size() << " ";
for (unsigned i = 0; i < m_values.size(); ++i) {
std::cout << vs[i] << ": " << m_values[i]->get_find_cost(vs[i]) << " ";
}
std::cout << "\n";
#endif
#if 0 #if 0
for (unsigned i = 0; found && i < m_values.size(); ++i) { for (unsigned i = 0; found && i < m_values.size(); ++i) {
found = m_values[i]->update_find(i, vs[i], idx); found = m_values[i]->update_find(i, vs[i], idx);
std::cout << vs[i] << ": " << m_found.size() << " ";
TRACE("hilbert_basis", tout << "update " << i << ": " << m_found.size() << " cost: " << m_values[i]->get_cost() << "\n";); TRACE("hilbert_basis", tout << "update " << i << ": " << m_found.size() << " cost: " << m_values[i]->get_cost() << "\n";);
} }
#else #else
@ -269,6 +295,7 @@ public:
} }
return false; return false;
#endif #endif
if (found) { if (found) {
found_idx = m_found[0]; found_idx = m_found[0];
} }
@ -290,6 +317,7 @@ public:
} }
st.update("hb.index.num_find", m_stats.m_num_find); st.update("hb.index.num_find", m_stats.m_num_find);
st.update("hb.index.num_insert", m_stats.m_num_insert); st.update("hb.index.num_insert", m_stats.m_num_insert);
st.update("hb.index.size", m_weight.get_size());
} }
void reset_statistics() { void reset_statistics() {
@ -363,12 +391,12 @@ public:
*/ */
class hilbert_basis::passive { class hilbert_basis::passive {
hilbert_basis& hb; hilbert_basis& hb;
svector<offset_t> m_passive; svector<offset_t> m_passive;
vector<numeral> m_weights; vector<numeral> m_weights;
unsigned_vector m_free_list; unsigned_vector m_free_list;
rational_lt m_lt; // less_than on indices rational_abs_lt m_lt; // less_than on indices
heap<rational_lt> m_heap; // binary heap over weights heap<rational_abs_lt> m_heap; // binary heap over weights
numeral get_weight(offset_t idx) { numeral get_weight(offset_t idx) {
numeral w(0); numeral w(0);
@ -487,6 +515,7 @@ void hilbert_basis::reset() {
void hilbert_basis::collect_statistics(statistics& st) const { void hilbert_basis::collect_statistics(statistics& st) const {
st.update("hb.num_subsumptions", m_stats.m_num_subsumptions); st.update("hb.num_subsumptions", m_stats.m_num_subsumptions);
st.update("hb.num_resolves", m_stats.m_num_resolves); st.update("hb.num_resolves", m_stats.m_num_resolves);
st.update("hb.num_saturations", m_stats.m_num_saturations);
m_index->collect_statistics(st); m_index->collect_statistics(st);
} }
@ -566,9 +595,11 @@ lbool hilbert_basis::saturate() {
init_basis(); init_basis();
for (unsigned i = 0; !m_cancel && i < m_ineqs.size(); ++i) { for (unsigned i = 0; !m_cancel && i < m_ineqs.size(); ++i) {
lbool r = saturate(m_ineqs[i]); lbool r = saturate(m_ineqs[i]);
++m_stats.m_num_saturations;
if (r != l_true) { if (r != l_true) {
return r; return r;
} }
} }
if (m_cancel) { if (m_cancel) {
return l_undef; return l_undef;
@ -650,6 +681,7 @@ void hilbert_basis::resolve(offset_t i, offset_t j, offset_t r) {
u[k] = v[k] + w[k]; u[k] = v[k] + w[k];
} }
u.value() = v.value() + w.value(); u.value() = v.value() + w.value();
// std::cout << "resolve: " << v.value() << " + " << w.value() << " = " << u.value() << "\n";
TRACE("hilbert_basis_verbose", TRACE("hilbert_basis_verbose",
display(tout, i); display(tout, i);
display(tout, j); display(tout, j);
@ -674,11 +706,12 @@ hilbert_basis::offset_t hilbert_basis::alloc_vector() {
void hilbert_basis::add_goal(offset_t idx) { void hilbert_basis::add_goal(offset_t idx) {
values v = vec(idx); values v = vec(idx);
if (is_subsumed(idx)) {
return;
}
m_index->insert(idx, v); m_index->insert(idx, v);
if (v.value().is_zero()) { if (v.value().is_zero()) {
if (!is_subsumed(idx)) { m_zero.push_back(idx);
m_zero.push_back(idx);
}
} }
else { else {
m_passive->insert(idx); m_passive->insert(idx);

View file

@ -50,6 +50,7 @@ private:
struct stats { struct stats {
unsigned m_num_subsumptions; unsigned m_num_subsumptions;
unsigned m_num_resolves; unsigned m_num_resolves;
unsigned m_num_saturations;
stats() { reset(); } stats() { reset(); }
void reset() { memset(this, 0, sizeof(*this)); } void reset() { memset(this, 0, sizeof(*this)); }
}; };

View file

@ -1,5 +1,78 @@
#include "hilbert_basis.h" #include "hilbert_basis.h"
#include<signal.h>
#include<time.h>
hilbert_basis* g_hb = 0;
static double g_start_time;
static void display_statistics(hilbert_basis& hb) {
double time = static_cast<double>(clock()) - g_start_time;
statistics st;
hb.collect_statistics(st);
st.display(std::cout);
std::cout << "time: " << (time / CLOCKS_PER_SEC) << " secs\n";
}
static void on_ctrl_c(int) {
signal (SIGINT, SIG_DFL);
display_statistics(*g_hb);
raise(SIGINT);
}
static void saturate_basis(hilbert_basis& hb) {
signal(SIGINT, on_ctrl_c);
g_hb = &hb;
g_start_time = static_cast<double>(clock());
lbool is_sat = hb.saturate();
switch(is_sat) {
case l_true:
std::cout << "sat\n";
hb.display(std::cout);
break;
case l_false:
std::cout << "unsat\n";
break;
case l_undef:
std::cout << "undef\n";
break;
}
display_statistics(hb);
}
/**
n - number of variables.
k - subset of variables to be non-zero
bound - numeric value of upper and lower bound
num_ineqs - number of inequalities to create
*/
static void gorrila_test(unsigned seed, unsigned n, unsigned k, unsigned bound, unsigned num_ineqs) {
std::cout << "Gorrila test\n";
random_gen rand(seed);
hilbert_basis hb;
SASSERT(0 < bound);
SASSERT(k <= n);
int ibound = static_cast<int>(bound);
for (unsigned i = 0; i < num_ineqs; ++i) {
vector<rational> nv;
nv.resize(n);
rational a0;
unsigned num_selected = 0;
while (num_selected < k) {
unsigned s = rand(n);
if (nv[s].is_zero()) {
nv[s] = rational(ibound - static_cast<int>(rand(2*bound+1)));
if (!nv[s].is_zero()) {
++num_selected;
}
}
}
a0 = rational(ibound - static_cast<int>(rand(2*bound+1)));
hb.add_ge(nv, a0);
}
hb.display(std::cout << "Saturate\n");
saturate_basis(hb);
}
static vector<rational> vec(int i, int j, int k) { static vector<rational> vec(int i, int j, int k) {
vector<rational> nv; vector<rational> nv;
@ -45,25 +118,6 @@ static vector<rational> vec(int i, int j, int k, int l, int x, int y, int z) {
} }
static void saturate_basis(hilbert_basis& hb) {
lbool is_sat = hb.saturate();
switch(is_sat) {
case l_true:
std::cout << "sat\n";
hb.display(std::cout);
break;
case l_false:
std::cout << "unsat\n";
break;
case l_undef:
std::cout << "undef\n";
break;
}
statistics st;
hb.collect_statistics(st);
st.display(std::cout);
}
// example 9, Ajili, Contenjean // example 9, Ajili, Contenjean
@ -191,6 +245,7 @@ static void tst11() {
void tst_hilbert_basis() { void tst_hilbert_basis() {
std::cout << "hilbert basis test\n"; std::cout << "hilbert basis test\n";
#if 0
tst1(); tst1();
tst2(); tst2();
tst3(); tst3();
@ -202,4 +257,11 @@ void tst_hilbert_basis() {
tst9(); tst9();
tst10(); tst10();
tst11(); tst11();
gorrila_test(0, 4, 3, 20, 5);
gorrila_test(1, 4, 3, 20, 5);
gorrila_test(2, 4, 3, 20, 5);
gorrila_test(0, 4, 2, 20, 5);
gorrila_test(0, 4, 2, 20, 5);
#endif
gorrila_test(0, 10, 7, 20, 11);
} }