3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 06:03:23 +00:00

optimizing hilbert basis

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2013-02-18 18:58:43 -08:00
parent 306855ba55
commit 0aa8df98a1
5 changed files with 238 additions and 120 deletions

View file

@ -29,6 +29,9 @@ Notes:
Maintaining sorted ranges for larger domains is another option. Maintaining sorted ranges for larger domains is another option.
Another possible enhancement is to resplay the tree.
Keep current key index in the nodes.
--*/ --*/
#ifndef _HEAP_TRIE_H_ #ifndef _HEAP_TRIE_H_
@ -36,10 +39,12 @@ Notes:
#include "map.h" #include "map.h"
#include "vector.h" #include "vector.h"
#include "buffer.h"
#include "statistics.h" #include "statistics.h"
#include "small_object_allocator.h"
template<typename Key, typename Value> template<typename Key, typename KeyLE, typename Value>
class heap_trie { class heap_trie {
struct stats { struct stats {
@ -68,7 +73,8 @@ class heap_trie {
void dec_ref() { SASSERT(m_ref > 0); --m_ref; } void dec_ref() { SASSERT(m_ref > 0); --m_ref; }
unsigned ref_count() const { return m_ref; } unsigned ref_count() const { return m_ref; }
virtual void display(std::ostream& out, unsigned indent) const = 0; virtual void display(std::ostream& out, unsigned indent) const = 0;
virtual unsigned size() const = 0; virtual unsigned num_nodes() const = 0;
virtual unsigned num_leaves() const = 0;
}; };
class leaf : public node { class leaf : public node {
@ -81,19 +87,19 @@ class heap_trie {
virtual void display(std::ostream& out, unsigned indent) const { virtual void display(std::ostream& out, unsigned indent) const {
out << " value: " << m_value; out << " value: " << m_value;
} }
virtual unsigned size() const { return 1; } virtual unsigned num_nodes() const { return 1; }
virtual unsigned num_leaves() const { return ref_count()>0?1:0; }
}; };
typedef buffer<std::pair<Key,node*>, true, 2> children_t;
// lean trie node // lean trie node
class trie : public node { class trie : public node {
vector<std::pair<Key,node*> > m_nodes; children_t m_nodes;
public: public:
trie(): node(trie_t) {} trie(): node(trie_t) {}
virtual ~trie() { virtual ~trie() {
for (unsigned i = 0; i < m_nodes.size(); ++i) {
dealloc(m_nodes[i].second);
}
} }
node* find_or_insert(Key k, node* n) { node* find_or_insert(Key k, node* n) {
@ -119,7 +125,7 @@ class heap_trie {
// push nodes whose keys are <= key into vector. // push nodes whose keys are <= key into vector.
void find_le(Key key, ptr_vector<node>& nodes) { void find_le(Key key, ptr_vector<node>& nodes) {
for (unsigned i = 0; i < m_nodes.size(); ++i) { for (unsigned i = 0; i < m_nodes.size(); ++i) {
if (m_nodes[i].first <= key) { if (KeyLE::le(m_nodes[i].first, key)) {
node* n = m_nodes[i].second; node* n = m_nodes[i].second;
if (n->ref_count() > 0){ if (n->ref_count() > 0){
nodes.push_back(n); nodes.push_back(n);
@ -128,22 +134,35 @@ class heap_trie {
} }
} }
children_t const& nodes() const { return m_nodes; }
children_t & nodes() { return m_nodes; }
virtual void display(std::ostream& out, unsigned indent) const { virtual void display(std::ostream& out, unsigned indent) const {
for (unsigned j = 0; j < m_nodes.size(); ++j) { for (unsigned j = 0; j < m_nodes.size(); ++j) {
if (j != 0 || indent > 0) {
out << "\n"; out << "\n";
}
for (unsigned i = 0; i < indent; ++i) { for (unsigned i = 0; i < indent; ++i) {
out << " "; out << " ";
} }
node* n = m_nodes[j].second; node* n = m_nodes[j].second;
out << m_nodes[j].first << " count: " << n->ref_count(); out << m_nodes[j].first << " refs: " << n->ref_count();
n->display(out, indent + 1); n->display(out, indent + 1);
} }
} }
virtual unsigned size() const { virtual unsigned num_nodes() const {
unsigned sz = 1; unsigned sz = 1;
for (unsigned j = 0; j < m_nodes.size(); ++j) { for (unsigned j = 0; j < m_nodes.size(); ++j) {
sz += m_nodes[j].second->size(); sz += m_nodes[j].second->num_nodes();
}
return sz;
}
virtual unsigned num_leaves() const {
unsigned sz = 0;
for (unsigned j = 0; j < m_nodes.size(); ++j) {
sz += m_nodes[j].second->num_leaves();
} }
return sz; return sz;
} }
@ -157,18 +176,19 @@ class heap_trie {
} }
return false; return false;
} }
}; };
small_object_allocator m_alloc;
unsigned m_num_keys; unsigned m_num_keys;
node* m_root; node* m_root;
stats m_stats; stats m_stats;
node* m_spare_leaf; node* m_spare_leaf;
node* m_spare_trie; node* m_spare_trie;
vector<ptr_vector<node> > m_children;
public: public:
heap_trie(): heap_trie():
m_alloc("heap_trie"),
m_num_keys(0), m_num_keys(0),
m_root(0), m_root(0),
m_spare_leaf(0), m_spare_leaf(0),
@ -176,19 +196,19 @@ public:
{} {}
~heap_trie() { ~heap_trie() {
dealloc(m_root); del_node(m_root);
dealloc(m_spare_leaf); del_node(m_spare_leaf);
dealloc(m_spare_trie); del_node(m_spare_trie);
} }
unsigned size() const { unsigned size() const {
return m_root->size(); return m_root->num_leaves();
} }
void reset(unsigned num_keys) { void reset(unsigned num_keys) {
dealloc(m_root); del_node(m_root);
dealloc(m_spare_leaf); del_node(m_spare_leaf);
dealloc(m_spare_trie); del_node(m_spare_trie);
m_num_keys = num_keys; m_num_keys = num_keys;
m_root = mk_trie(); m_root = mk_trie();
m_spare_trie = mk_trie(); m_spare_trie = mk_trie();
@ -214,7 +234,7 @@ public:
return true; return true;
} }
void find_le(Key const* keys, vector<Value>& values) { void find_all_le(Key const* keys, vector<Value>& values) {
++m_stats.m_num_find_le; ++m_stats.m_num_find_le;
ptr_vector<node> todo[2]; ptr_vector<node> todo[2];
todo[0].push_back(m_root); todo[0].push_back(m_root);
@ -232,7 +252,6 @@ public:
} }
} }
// callback based find function // callback based find function
class check_value { class check_value {
public: public:
@ -241,28 +260,8 @@ public:
bool find_le(Key const* keys, check_value& check) { bool find_le(Key const* keys, check_value& check) {
++m_stats.m_num_find_le; ++m_stats.m_num_find_le;
if (m_children.size() < num_keys()) {
m_children.resize(num_keys());
}
return find_le(m_root, 0, keys, check);
}
bool find_le(node* n, unsigned index, Key const* keys, check_value& check) {
++m_stats.m_num_find_le_nodes; ++m_stats.m_num_find_le_nodes;
if (index == num_keys()) { return find_le(m_root, 0, keys, check);
SASSERT(n->ref_count() > 0);
return check(to_leaf(n)->get_value());
}
else {
m_children[index].reset();
to_trie(n)->find_le(keys[index], m_children[index]);
for (unsigned i = 0; i < m_children[index].size(); ++i) {
if (find_le(m_children[index][i], index + 1, keys, check)) {
return true;
}
}
return false;
}
} }
void remove(Key const* keys) { void remove(Key const* keys) {
@ -288,9 +287,49 @@ public:
st.update("heap_trie.num_find_eq", m_stats.m_num_find_eq); st.update("heap_trie.num_find_eq", m_stats.m_num_find_eq);
st.update("heap_trie.num_find_le", m_stats.m_num_find_le); st.update("heap_trie.num_find_le", m_stats.m_num_find_le);
st.update("heap_trie.num_find_le_nodes", m_stats.m_num_find_le_nodes); st.update("heap_trie.num_find_le_nodes", m_stats.m_num_find_le_nodes);
st.update("heap_trie.num_nodes", m_root->num_nodes());
unsigned_vector nums;
ptr_vector<node> todo;
todo.push_back(m_root);
while (!todo.empty()) {
node* n = todo.back();
todo.pop_back();
if (n->type() == trie_t) {
trie* t = to_trie(n);
unsigned sz = t->nodes().size();
if (nums.size() <= sz) {
nums.resize(sz+1);
}
++nums[sz];
for (unsigned i = 0; i < sz; ++i) {
todo.push_back(t->nodes()[i].second);
}
}
}
if (nums.size() < 16) nums.resize(16);
st.update("heap_trie.num_1_children", nums[1]);
st.update("heap_trie.num_2_children", nums[2]);
st.update("heap_trie.num_3_children", nums[3]);
st.update("heap_trie.num_4_children", nums[4]);
st.update("heap_trie.num_5_children", nums[5]);
st.update("heap_trie.num_6_children", nums[6]);
st.update("heap_trie.num_7_children", nums[7]);
st.update("heap_trie.num_8_children", nums[8]);
st.update("heap_trie.num_9_children", nums[9]);
st.update("heap_trie.num_10_children", nums[10]);
st.update("heap_trie.num_11_children", nums[11]);
st.update("heap_trie.num_12_children", nums[12]);
st.update("heap_trie.num_13_children", nums[13]);
st.update("heap_trie.num_14_children", nums[14]);
st.update("heap_trie.num_15_children", nums[15]);
unsigned sz = 0;
for (unsigned i = 16; i < nums.size(); ++i) {
sz += nums[i];
}
st.update("heap_trie.num_16+_children", sz);
} }
void display(std::ostream& out) { void display(std::ostream& out) const {
m_root->display(out, 0); m_root->display(out, 0);
out << "\n"; out << "\n";
} }
@ -301,23 +340,37 @@ private:
return m_num_keys; return m_num_keys;
} }
void insert(node* n, unsigned num_keys, Key const* keys, Value const& val) { bool find_le(node* n, unsigned index, Key const* keys, check_value& check) {
// assumption: key is not in table. if (index == num_keys()) {
SASSERT(n->ref_count() > 0);
while (true) { return check(to_leaf(n)->get_value());
n->inc_ref();
if (num_keys == 0) {
to_leaf(n)->set_value(val);
SASSERT(n->ref_count() == 1);
break;
} }
else { else {
n = insert_key(to_trie(n), (num_keys == 1), keys[0]); Key key = keys[index];
--num_keys; children_t const& nodes = to_trie(n)->nodes();
++keys; for (unsigned i = 0; i < nodes.size(); ++i) {
++m_stats.m_num_find_le_nodes;
if (KeyLE::le(nodes[i].first, key)) {
node* m = nodes[i].second;
if (m->ref_count() > 0 && find_le(m, index+1, keys, check)) {
return true;
} }
} }
} }
return false;
}
}
void insert(node* n, unsigned num_keys, Key const* keys, Value const& val) {
// assumption: key is not in table.
for (unsigned i = 0; i < num_keys; ++i) {
n->inc_ref();
n = insert_key(to_trie(n), (i + 1 == num_keys), keys[i]);
}
n->inc_ref();
to_leaf(n)->set_value(val);
SASSERT(n->ref_count() == 1);
}
node* insert_key(trie* n, bool is_leaf, Key const& key) { node* insert_key(trie* n, bool is_leaf, Key const& key) {
node* m1 = is_leaf?m_spare_leaf:m_spare_trie; node* m1 = is_leaf?m_spare_leaf:m_spare_trie;
@ -334,19 +387,40 @@ private:
} }
leaf* mk_leaf() { leaf* mk_leaf() {
return alloc(leaf); void* mem = m_alloc.allocate(sizeof(leaf));
return new (mem) leaf();
} }
trie* mk_trie() { trie* mk_trie() {
return alloc(trie); void* mem = m_alloc.allocate(sizeof(trie));
return new (mem) trie();
} }
trie* to_trie(node* n) { void del_node(node* n) {
if (!n) {
return;
}
if (n->type() == trie_t) {
trie* t = to_trie(n);
for (unsigned i = 0; i < t->nodes().size(); ++i) {
del_node(t->nodes()[i].second);
}
t->~trie();
m_alloc.deallocate(sizeof(trie), t);
}
else {
leaf* l = to_leaf(n);
l->~leaf();
m_alloc.deallocate(sizeof(leaf), l);
}
}
trie* to_trie(node* n) const {
SASSERT(n->type() == trie_t); SASSERT(n->type() == trie_t);
return static_cast<trie*>(n); return static_cast<trie*>(n);
} }
leaf* to_leaf(node* n) { leaf* to_leaf(node* n) const {
SASSERT(n->type() == leaf_t); SASSERT(n->type() == leaf_t);
return static_cast<leaf*>(n); return static_cast<leaf*>(n);
} }

View file

@ -87,7 +87,39 @@ public:
unsigned size() const { unsigned size() const {
return m_table.size(); return m_table.size();
} }
void display(std::ostream& out) const {
int_table::iterator it = m_table.begin(), end = m_table.end();
for (; it != end; ++it) {
offset_t offs(*it);
hb.display(out, offs);
}
display_profile(out);
}
private: private:
typedef hashtable<numeral, numeral::hash_proc, numeral::eq_proc> numeral_set;
void display_profile(std::ostream& out) const {
vector<numeral_set> weights;
weights.resize(hb.get_num_vars()+1);
int_table::iterator it = m_table.begin(), end = m_table.end();
for (; it != end; ++it) {
offset_t offs(*it);
values const& ws = hb.vec(offs);
weights[0].insert(ws.weight());
for (unsigned i = 0; i < hb.get_num_vars(); ++i) {
weights[i+1].insert(ws[i]);
}
}
out << "profile: ";
for (unsigned i = 0; i < weights.size(); ++i) {
out << weights[i].size() << " ";
}
out << "\n";
}
void display_profile(offset_t idx, std::ostream& out) { void display_profile(offset_t idx, std::ostream& out) {
unsigned_vector leq; unsigned_vector leq;
unsigned nv = hb.get_num_vars(); unsigned nv = hb.get_num_vars();
@ -130,14 +162,19 @@ private:
}; };
class hilbert_basis::value_index2 { class hilbert_basis::value_index2 {
struct checker : public heap_trie<numeral, unsigned>::check_value { struct key_le {
static bool le(numeral const& n1, numeral const& n2) {
return hilbert_basis::is_abs_geq(n2, n1);
}
};
struct checker : public heap_trie<numeral, key_le, unsigned>::check_value {
hilbert_basis* hb; hilbert_basis* hb;
offset_t m_value; offset_t m_value;
offset_t m_found; offset_t* m_found;
checker(): hb(0) {} checker(): hb(0), m_found(0) {}
virtual bool operator()(unsigned const& v) { virtual bool operator()(unsigned const& v) {
if (m_value.m_offset != v && hb->is_subsumed(m_value, offset_t(v))) { if (m_value.m_offset != v && hb->is_subsumed(m_value, offset_t(v))) {
m_found = offset_t(v); *m_found = offset_t(v);
return true; return true;
} }
else { else {
@ -146,11 +183,25 @@ class hilbert_basis::value_index2 {
} }
}; };
hilbert_basis& hb; hilbert_basis& hb;
heap_trie<numeral, unsigned> m_trie; heap_trie<numeral, key_le, unsigned> m_trie;
vector<unsigned> m_found; vector<unsigned> m_found;
bool m_init; bool m_init;
checker m_checker; checker m_checker;
vector<numeral> m_keys;
#if 1
numeral const* get_keys(values const& vs) {
return vs()-1;
}
#else
numeral const* get_keys(values const& vs) {
unsigned sz = m_keys.size();
for (unsigned i = 0; i < sz; ++i) {
m_keys[sz-i-1] = vs()[i-1];
}
return m_keys.c_ptr();
}
#endif
public: public:
value_index2(hilbert_basis& hb): hb(hb), m_init(false) { value_index2(hilbert_basis& hb): hb(hb), m_init(false) {
@ -159,50 +210,23 @@ public:
void insert(offset_t idx, values const& vs) { void insert(offset_t idx, values const& vs) {
init(); init();
m_trie.insert(vs()-1, idx.m_offset); m_trie.insert(get_keys(vs), idx.m_offset);
} }
void remove(offset_t idx, values const& vs) { void remove(offset_t idx, values const& vs) {
m_trie.remove(vs()-1); m_trie.remove(get_keys(vs));
} }
void reset() { void reset() {
m_trie.reset(hb.get_num_vars()); m_trie.reset(hb.get_num_vars()+1);
m_keys.resize(hb.get_num_vars()+1);
} }
bool find(offset_t idx, values const& vs, offset_t& found_idx) { bool find(offset_t idx, values const& vs, offset_t& found_idx) {
init(); init();
m_found.reset();
m_checker.m_value = idx; m_checker.m_value = idx;
if (!m_trie.find_le(vs()-1, m_checker)) { m_checker.m_found = &found_idx;
return false; return m_trie.find_le(get_keys(vs), m_checker);
}
else {
found_idx = m_checker.m_found;
return true;
}
}
bool find_old(offset_t idx, values const& vs, offset_t& found_idx) {
init();
m_found.reset();
m_trie.find_le(vs()-1, m_found);
std::cout << m_found.size() << " - ";
for (unsigned i = 0; i < m_found.size(); ++i) {
found_idx = offset_t(m_found[i]);
std::cout << i << " ";
if (m_found[i] != idx.m_offset && hb.is_subsumed(idx, found_idx)) {
TRACE("hilbert_basis",
hb.display(tout << "found:" , idx);
hb.display(tout << "-> ", found_idx);
m_trie.display(tout););
std::cout << "\n";
return true;
}
}
std::cout << "\n";
TRACE("hilbert_basis", tout << "not found: "; hb.display(tout, idx); );
return false;
} }
void collect_statistics(statistics& st) const { void collect_statistics(statistics& st) const {
@ -217,6 +241,10 @@ public:
return m_trie.size(); return m_trie.size();
} }
void display(std::ostream& out) const {
// m_trie.display(out);
}
private: private:
void init() { void init() {
if (!m_init) { if (!m_init) {
@ -232,8 +260,8 @@ class hilbert_basis::index {
// for each non-positive weight a separate index. // for each non-positive weight a separate index.
// for positive weights a shared value index. // for positive weights a shared value index.
typedef value_index1 value_index; // typedef value_index1 value_index;
// typedef value_index2 value_index; typedef value_index2 value_index;
struct stats { struct stats {
unsigned m_num_find; unsigned m_num_find;
@ -329,6 +357,15 @@ public:
} }
} }
void display(std::ostream& out) const {
m_pos.display(out);
m_zero.display(out);
value_map::iterator it = m_neg.begin(), end = m_neg.end();
for (; it != end; ++it) {
it->m_value->display(out);
}
}
private: private:
unsigned size() const { unsigned size() const {
unsigned sz = m_pos.size(); unsigned sz = m_pos.size();
@ -347,15 +384,16 @@ private:
class hilbert_basis::passive { class hilbert_basis::passive {
struct lt { struct lt {
passive& p; passive** p;
lt(passive& p): p(p) {} lt(passive** p): p(p) {}
bool operator()(int v1, int v2) const { bool operator()(int v1, int v2) const {
return p(v1, v2); return (**p)(v1, v2);
} }
}; };
hilbert_basis& hb; hilbert_basis& hb;
svector<offset_t> m_passive; svector<offset_t> m_passive;
unsigned_vector m_free_list; unsigned_vector m_free_list;
passive* m_this;
lt m_lt; lt m_lt;
heap<lt> m_heap; // binary heap over weights heap<lt> m_heap; // binary heap over weights
@ -372,9 +410,10 @@ public:
passive(hilbert_basis& hb): passive(hilbert_basis& hb):
hb(hb), hb(hb),
m_lt(*this), m_lt(&m_this),
m_heap(10, m_lt) m_heap(10, m_lt)
{ {
m_this = this;
} }
void reset() { void reset() {
@ -529,7 +568,7 @@ void hilbert_basis::add_eq(num_vector const& v) {
void hilbert_basis::set_is_int(unsigned var_index) { void hilbert_basis::set_is_int(unsigned var_index) {
// //
// The 0't index is reserved for the constant // The 0'th index is reserved for the constant
// coefficient. Shift indices by 1. // coefficient. Shift indices by 1.
// //
m_ints.push_back(var_index+1); m_ints.push_back(var_index+1);
@ -550,7 +589,7 @@ unsigned hilbert_basis::get_num_vars() const {
} }
hilbert_basis::values hilbert_basis::vec(offset_t offs) const { hilbert_basis::values hilbert_basis::vec(offset_t offs) const {
return values(m_store.c_ptr() + offs.m_offset); return values(m_store.c_ptr() + (get_num_vars() + 1)*offs.m_offset);
} }
void hilbert_basis::init_basis() { void hilbert_basis::init_basis() {
@ -680,7 +719,7 @@ void hilbert_basis::select_inequality() {
for (unsigned j = best+1; prod != 0 && j < m_ineqs.size(); ++j) { for (unsigned j = best+1; prod != 0 && j < m_ineqs.size(); ++j) {
unsigned non_zeros2 = get_num_nonzeros(m_ineqs[j]); unsigned non_zeros2 = get_num_nonzeros(m_ineqs[j]);
unsigned prod2 = get_ineq_product(m_ineqs[j]); unsigned prod2 = get_ineq_product(m_ineqs[j]);
if (prod2 < prod || (prod2 == prod && non_zeros2 < non_zeros)) { if (non_zeros2 < non_zeros || (non_zeros2 == non_zeros && prod2 < prod)) {
prod = prod2; prod = prod2;
non_zeros = non_zeros2; non_zeros = non_zeros2;
best = j; best = j;
@ -733,7 +772,6 @@ 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.weight() = v.weight() + w.weight(); u.weight() = v.weight() + w.weight();
// std::cout << "resolve: " << v.weight() << " + " << w.weight() << " = " << u.weight() << "\n";
TRACE("hilbert_basis_verbose", TRACE("hilbert_basis_verbose",
display(tout, i); display(tout, i);
display(tout, j); display(tout, j);
@ -747,7 +785,7 @@ hilbert_basis::offset_t hilbert_basis::alloc_vector() {
unsigned num_vars = get_num_vars(); unsigned num_vars = get_num_vars();
unsigned idx = m_store.size(); unsigned idx = m_store.size();
m_store.resize(idx + 1 + num_vars); m_store.resize(idx + 1 + num_vars);
return offset_t(idx); return offset_t(idx/(1+num_vars));
} }
else { else {
offset_t result = m_free_list.back(); offset_t result = m_free_list.back();
@ -757,6 +795,7 @@ hilbert_basis::offset_t hilbert_basis::alloc_vector() {
} }
void hilbert_basis::add_goal(offset_t idx) { void hilbert_basis::add_goal(offset_t idx) {
TRACE("hilbert_basis", display(tout, idx););
values v = vec(idx); values v = vec(idx);
if (is_subsumed(idx)) { if (is_subsumed(idx)) {
return; return;
@ -852,6 +891,9 @@ void hilbert_basis::display(std::ostream& out) const {
display(out, m_zero[i]); display(out, m_zero[i]);
} }
} }
if (m_index) {
m_index->display(out);
}
} }
void hilbert_basis::display(std::ostream& out, offset_t o) const { void hilbert_basis::display(std::ostream& out, offset_t o) const {
@ -954,7 +996,7 @@ bool hilbert_basis::is_geq(values const& v, values const& w) const {
return true; return true;
} }
bool hilbert_basis::is_abs_geq(numeral const& v, numeral const& w) const { bool hilbert_basis::is_abs_geq(numeral const& v, numeral const& w) {
if (w.is_neg()) { if (w.is_neg()) {
return v <= w; return v <= w;
} }

View file

@ -100,7 +100,7 @@ private:
unsigned get_num_vars() const; unsigned get_num_vars() const;
numeral get_weight(values const & val, num_vector const& ineq) const; numeral get_weight(values const & val, num_vector const& ineq) const;
bool is_geq(values const& v, values const& w) const; bool is_geq(values const& v, values const& w) const;
bool is_abs_geq(numeral const& v, numeral const& w) const; static bool is_abs_geq(numeral const& v, numeral const& w);
bool is_subsumed(offset_t idx); bool is_subsumed(offset_t idx);
bool is_subsumed(offset_t i, offset_t j) const; bool is_subsumed(offset_t i, offset_t j) const;
void recycle(offset_t idx); void recycle(offset_t idx);

View file

@ -1,12 +1,15 @@
#include "heap_trie.h" #include "heap_trie.h"
struct unsigned_le {
static bool le(unsigned i, unsigned j) { return i <= j; }
};
typedef heap_trie<unsigned, unsigned > heap_trie_t; typedef heap_trie<unsigned, unsigned_le, unsigned > heap_trie_t;
static void find_le(heap_trie_t& ht, unsigned num_keys, unsigned const* keys) { static void find_le(heap_trie_t& ht, unsigned num_keys, unsigned const* keys) {
statistics st; statistics st;
vector<unsigned> vals; vector<unsigned> vals;
ht.find_le(keys, vals); ht.find_all_le(keys, vals);
std::cout << "find_le: "; std::cout << "find_le: ";
for (unsigned i = 0; i < num_keys; ++i) { for (unsigned i = 0; i < num_keys; ++i) {
std::cout << keys[i] << " "; std::cout << keys[i] << " ";

View file

@ -510,7 +510,7 @@ void tst_hilbert_basis() {
tst1(); tst1();
tst2(); tst2();
tst3(); tst3();
// tst4(); tst4();
tst5(); tst5();
tst6(); tst6();
tst7(); tst7();
@ -530,6 +530,5 @@ void tst_hilbert_basis() {
} }
else { else {
gorrila_test(0, 10, 7, 20, 11); gorrila_test(0, 10, 7, 20, 11);
tst4();
} }
} }