00001
00002
00003
00004
00005
00006
00007
00204 #ifndef __LAVABDD_H__
00205 #define __LAVABDD_H__
00206
00211 #define USING_DENSE_HASH_MAP
00212
00217 #define INITIAL_REFCOUNT 0
00218
00219 #include <list>
00220 #include <stdexcept>
00221 #include <iomanip>
00222 #include <iostream>
00223 #include <fstream>
00224 #include <map>
00225 #include <set>
00226 #include <vector>
00227
00228 #ifdef USING_DENSE_HASH_MAP
00229 #include <google/dense_hash_map>
00230 using google::dense_hash_map;
00231 #else
00232 #include <google/sparse_hash_map>
00233 using google::sparse_hash_map;
00234 #endif
00235
00236 using namespace std;
00237
00241 namespace lava {
00242
00246 const int UNF = 0;
00247
00252 const int SNF_MEET = 1;
00253
00258 const int SNF_JOIN = 2;
00259
00260
00261
00266 inline int hash_int(int key) {
00267 key = ~key + (key << 15);
00268 key = key ^ (key >> 12);
00269 key = key + (key << 2);
00270 key = key ^ (key >> 4);
00271 key = key * 2057;
00272 key = key ^ (key >> 16);
00273 return key;
00274 }
00275
00276
00277
00281 template<typename V>
00282 class Lattice {
00283
00284 public:
00285
00286 typedef V ValueType;
00287
00292 static bool less(const V& x, const V& y) {
00293 throw logic_error("Lattice::less not implemented.");
00294 }
00295
00299 static bool equal(const V& x, const V& y) {
00300 throw logic_error("Lattice::equal not implemented.");
00301 }
00302
00306 static void join(const V& x, const V& y, V& z) {
00307 throw logic_error("Lattice::join not implemented.");
00308 }
00309
00313 static void meet(const V& x, const V& y, V& z) {
00314 throw logic_error("Lattice::meet not implemented.");
00315 }
00316
00321 static void rpc(const V& x, const V& y, V& z) {
00322 throw logic_error("Lattice::rpc not implemented.");
00323 }
00324
00329 static void drpc(const V& x, const V& y, V& z) {
00330 throw logic_error("Lattice::drpc not implemented.");
00331 }
00332
00336 static void top(V& x) {
00337 throw logic_error("Lattice::top not implemented.");
00338 }
00339
00343 static void bot(V& x) {
00344 throw logic_error("Lattice::bot not implemented.");
00345 }
00346
00355 static size_t hash(const V& x) {
00356 throw logic_error("Lattice::hash not implemented.");
00357 }
00358
00362 static void print(const V& x, ostream& out) {
00363 throw logic_error("Lattice::print not implemented.");
00364 }
00365
00371 static int size(const V& x) {
00372 throw logic_error("Lattice::size not implemented.");
00373 }
00374
00381 static int list_size(const list<V>& l) {
00382 throw logic_error("Lattice::list_size not implemented.");
00383 }
00384
00385 };
00386
00387
00388
00389 template<class L, int F> class Node;
00390
00397 template<class L, int F> class NodePtr {
00398
00399 private:
00400
00401 typedef typename L::ValueType V;
00402 typedef Node<L, F> Node;
00403
00404 Node* _node;
00405
00406 public:
00407
00408 NodePtr() {
00409 _node = NULL;
00410 }
00411
00416 NodePtr(Node* node) {
00417 _node = node;
00418 if (_node)
00419 _node->_ref();
00420 }
00421
00425 ~NodePtr() {
00426 if (_node)
00427 _node->_unref();
00428 }
00429
00433 NodePtr(const NodePtr& other) {
00434 _node = other._node;
00435 if (_node)
00436 _node->_ref();
00437 }
00438
00442 NodePtr& operator=(const NodePtr& other) {
00443 if (this != &other) {
00444 if (_node)
00445 _node->_unref();
00446 _node = other._node;
00447 if (_node)
00448 _node->_ref();
00449 }
00450 return *this;
00451 }
00452
00456 Node& operator*() const {
00457 if (_node == NULL)
00458 throw logic_error("NodePtr : NULL pointer access");
00459 return *_node;
00460 }
00461
00465 Node* operator->() const {
00466 if (_node == NULL)
00467 throw logic_error("NodePtr : NULL pointer access");
00468 return _node;
00469 }
00470
00476 Node* get_ptr() const {
00477 return _node;
00478 }
00479
00483 bool operator==(const NodePtr& other) const {
00484 return _node == other._node;
00485 }
00486
00490 bool operator!=(const NodePtr& other) const {
00491 return _node != other._node;
00492 }
00493
00497 bool operator<(const NodePtr& other) const {
00498 return _node < other._node;
00499 }
00500
00504 operator bool() const {
00505 return _node ? true : false;
00506 }
00507
00511 void nullify() {
00512 if (_node)
00513 _node->_unref();
00514 _node = NULL;
00515 }
00516
00520 void grab(Node *node) {
00521 if (_node)
00522 _node->_unref();
00523 _node = node;
00524 if (_node)
00525 _node->_ref();
00526 }
00527
00528 };
00529
00530 template<class L, int F> class LVBDD;
00531
00538 template<class L, int F> class Node {
00539
00540 private:
00541
00542 typedef typename L::ValueType V;
00543
00544 friend class NodePtr<L, F> ;
00545 typedef NodePtr<L, F> NodePtr;
00546 typedef LVBDD<L, F> LVBDD;
00547
00548 mutable int _refcount;
00549 int _index;
00550 V _value;
00551 size_t _hash;
00552
00553 NodePtr _lo;
00554 NodePtr _hi;
00555
00556 void _unref() {
00557 if (_refcount <= 0) {
00558 throw runtime_error("unref on orphan Node");
00559 }
00560 _refcount--;
00561 if (_refcount == 0) {
00562 LVBDD::_add_orphan(this);
00563 _lo.nullify();
00564 _hi.nullify();
00565 _index = -1;
00566 }
00567 }
00568
00569 void _ref() {
00570 _refcount++;
00571 }
00572
00573 public:
00574
00575
00576
00577
00578 Node() {
00579 }
00580
00593 Node(int index, const V& val, const NodePtr& lo, const NodePtr& hi) :
00594 _refcount(INITIAL_REFCOUNT), _index(index), _value(val), _lo(lo), _hi(hi) {
00595 _hash = L::hash(_value) ^ hash_int(_index);
00596 if (lo)
00597 _hash ^= hash_int(((size_t) lo.get_ptr()) * 17);
00598 if (hi)
00599 _hash ^= hash_int(((size_t) hi.get_ptr()));
00600 }
00601
00606 int index() const {
00607 return _index;
00608 }
00609
00614 size_t hash() const {
00615 return _hash;
00616 }
00617
00621 int refcount() const {
00622 return _refcount;
00623 }
00624
00628 const V& value() const {
00629 return _value;
00630 }
00631
00635 void value(V& value) const {
00636 value = _value;
00637 }
00638
00642 NodePtr lo() const {
00643 return _lo;
00644 }
00645
00649 NodePtr hi() const {
00650 return _hi;
00651 }
00652
00657 bool operator==(const Node& other) const {
00658 return _hash == other._hash && _index == other._index && _lo == other._lo && _hi
00659 == other._hi && L::equal(_value, other._value);
00660 }
00661
00665 bool operator!=(const Node& other) const {
00666 return not (*this == other);
00667 }
00668
00669
00670
00671
00672 void set_refcount(int refcount) {
00673 _refcount = refcount;
00674 }
00675
00676
00677
00678
00679 static Node deleted_key() {
00680 Node key;
00681 key._refcount = -1;
00682 key._index = -1;
00683 key._hash = -1;
00684 return key;
00685 }
00686
00687
00688
00689
00690 static Node empty_key() {
00691 Node key;
00692 key._refcount = -2;
00693 key._index = -2;
00694 key._hash = -2;
00695 return key;
00696 }
00697
00704 static void print_graphviz(ostream& out = cout, NodePtr root = NULL) {
00705 set<Node*> my_nodes;
00706 if (not root) {
00707 typename LVBDD::HashMap::const_iterator it;
00708 for (it = LVBDD::_hash_map.begin(); it != LVBDD::_hash_map.end(); it++) {
00709 my_nodes.insert(it->second);
00710 }
00711 }
00712 else {
00713 root->_descendants(my_nodes);
00714 }
00715 typename set<Node*>::iterator it;
00716 out << "digraph G {" << endl;
00717 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
00718 if ((*it)->index() == 0) {
00719 out << "\"" << *it << "\" [label=\"";
00720 L::print((*it)->value(), out);
00721 if (*it == root.get_ptr())
00722 out << " (" << (*it)->refcount() - 1 << ")";
00723 else
00724 out << " (" << (*it)->refcount() << ")";
00725 out << "\", shape=box];" << endl;
00726 }
00727 else {
00728 out << "\"" << *it << "\" [label=\"" << (*it)->index() << " : ";
00729 L::print((*it)->value(), out);
00730 if (*it == root.get_ptr())
00731 out << " (" << (*it)->refcount() - 1 << ")";
00732 else
00733 out << " (" << (*it)->refcount() << ")";
00734 out << "\"];" << endl;
00735 }
00736 }
00737 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
00738 if ((*it)->lo()) {
00739 out << "\"" << *it << "\" -> " << "\"" << ((*it)->lo().get_ptr());
00740 out << "\" [style=dotted, arrowhead=none];" << endl;
00741 }
00742 if ((*it)->lo()) {
00743 out << "\"" << *it << "\" -> " << "\"" << ((*it)->hi().get_ptr());
00744 out << "\" [arrowhead=none];" << endl;
00745 }
00746 }
00747 out << "}" << endl;
00748 }
00749
00750 void _descendants(set<Node*>& nodes) {
00751 nodes.clear();
00752 set<Node*> to_visit;
00753 typename set<Node*>::iterator it;
00754 to_visit.insert(this);
00755 Node* n;
00756 while (to_visit.size() > 0) {
00757 it = to_visit.begin();
00758 n = *it;
00759 to_visit.erase(it);
00760 if (nodes.find(n) == nodes.end()) {
00761 nodes.insert(n);
00762 if (n->index() > 0) {
00763 to_visit.insert(n->lo().get_ptr());
00764 to_visit.insert(n->hi().get_ptr());
00765 }
00766 }
00767 }
00768 }
00769
00770 };
00771
00772
00773
00779 template<class L, int F>
00780 class LVBDD {
00781
00782 private:
00783
00784 typedef typename L::ValueType V;
00785
00786
00787
00788 struct NodeHashFunction {
00789 size_t operator()(Node<L, F>* const & n) const {
00790 return n->hash();
00791 }
00792 };
00793
00794 struct NodeEqualFunction {
00795 bool operator()(Node<L, F>* const & n1, Node<L, F>* const & n2) const {
00796 return (*n1) == (*n2);
00797 }
00798 };
00799
00800
00801
00802 struct Quadruple {
00803 NodePtr<L, F> n1, n2;
00804 V d1, d2;
00805 };
00806
00807 struct QuadrupleLT {
00808 bool operator()(const Quadruple& a, const Quadruple& b) const {
00809 if (a.n1->hash() != b.n1->hash())
00810 return a.n1->hash() < b.n1->hash();
00811 if (a.n2->hash() != b.n2->hash())
00812 return a.n2->hash() < b.n2->hash();
00813 if (L::hash(a.d1) != L::hash(b.d1))
00814 return L::hash(a.d1) < L::hash(b.d1);
00815 if (L::hash(a.d2) != L::hash(b.d2))
00816 return L::hash(a.d2) < L::hash(b.d2);
00817 return false;
00818 }
00819 };
00820
00821
00822
00823 class QuadrupleMemoizer {
00824
00825 typedef Node<L, F> Node;
00826 typedef NodePtr<L, F> NodePtr;
00827
00828 typedef map<const Quadruple, NodePtr, QuadrupleLT> MAP;
00829 MAP _map;
00830
00831 public:
00832
00833 NodePtr get(const NodePtr& n1, const NodePtr& n2, const V& d1, const V& d2) const {
00834 Quadruple q1, q2;
00835 q1.n1 = n1;
00836 q2.n1 = n2;
00837 q1.n2 = n2;
00838 q2.n2 = n1;
00839 q1.d1 = d1;
00840 q2.d1 = d2;
00841 q1.d2 = d2;
00842 q2.d2 = d1;
00843 typename MAP::const_iterator it;
00844 it = _map.find(q1);
00845 if (it != _map.end())
00846 return it->second;
00847 it = _map.find(q2);
00848 if (it != _map.end())
00849 return it->second;
00850 return NULL;
00851 }
00852
00853 void set(const NodePtr& n1, const NodePtr& n2, const V& d1, const V& d2,
00854 const NodePtr& memo) {
00855 Quadruple q;
00856 q.n1 = n1;
00857 q.n2 = n2;
00858 q.d1 = d1;
00859 q.d2 = d2;
00860 _map[q] = memo;
00861 }
00862
00863 void clear() {
00864 _map.clear();
00865 }
00866
00867 };
00868
00869
00870
00871 class NodeNodeMemoizer {
00872
00873 typedef Node<L, F> Node;
00874 typedef NodePtr<L, F> NodePtr;
00875
00876 map<pair<NodePtr, NodePtr> , NodePtr> _map;
00877
00878 public:
00879
00880 NodePtr get(const NodePtr& n1, const NodePtr& n2) const {
00881 pair<NodePtr, NodePtr> p1(n1, n2);
00882 pair<NodePtr, NodePtr> p2(n2, n1);
00883 typename map<pair<NodePtr, NodePtr> , NodePtr>::const_iterator it;
00884 NodePtr result;
00885 it = _map.find(p1);
00886 if (it != _map.end()) {
00887 result = it->second;
00888 }
00889 else {
00890 it = _map.find(p2);
00891 if (it != _map.end())
00892 result = it->second;
00893 else
00894 result = NULL;
00895 }
00896 return result;
00897 }
00898
00899 void set(const NodePtr& n1, const NodePtr& n2, const NodePtr& memo) {
00900 pair<NodePtr, NodePtr> p(n1, n2);
00901 _map[p] = memo;
00902 }
00903
00904 void clear() {
00905 _map.clear();
00906 }
00907
00908 };
00909
00910
00911
00912 struct NodeValueLT {
00913 typedef Node<L, F> Node;
00914 typedef NodePtr<L, F> NodePtr;
00915
00916 bool operator()(const pair<NodePtr, V>& a, const pair<NodePtr, V>& b) const {
00917 if (a.first == b.first)
00918 return L::hash(a.second) < L::hash(b.second);
00919 else
00920 return a.first.get_ptr() < b.first.get_ptr();
00921 }
00922 };
00923
00924
00925
00926 class NodeValueMemoizer {
00927
00928 typedef Node<L, F> Node;
00929 typedef NodePtr<L, F> NodePtr;
00930 map<pair<NodePtr, V> , NodePtr, NodeValueLT> _map;
00931
00932 public:
00933
00934 NodePtr get(const NodePtr& n, const V& value) const {
00935 pair<NodePtr, V> p(n, value);
00936 typename map<pair<NodePtr, V> , NodePtr, NodeValueLT>::const_iterator it;
00937 it = _map.find(p);
00938 if (it != _map.end())
00939 return it->second;
00940 else
00941 return NULL;
00942 }
00943
00944 void set(const NodePtr& n, const V& value, const NodePtr& memo) {
00945 pair<NodePtr, V> p(n, value);
00946 _map[p] = memo;
00947 }
00948
00949 void clear() {
00950 _map.clear();
00951 }
00952
00953 };
00954
00955 friend class Node<L, F> ;
00956
00957 typedef Node<L, F> Node;
00958 typedef NodeHashFunction HashNode;
00959 typedef NodeEqualFunction EqualNode;
00960 typedef NodePtr<L, F> NodePtr;
00961
00962 #ifdef USING_DENSE_HASH_MAP
00963 typedef dense_hash_map<Node*, Node*, HashNode, EqualNode> HashMap;
00964 #else
00965 typedef sparse_hash_map<Node*, Node*, HashNode, EqualNode> HashMap;
00966 #endif
00967
00968 NodePtr _root;
00969
00970 static HashMap _hash_map;
00971 static list<Node*> _orphans;
00972
00973 static int _mk_call_count;
00974 static int _orphan_fetches;
00975 static int _node_allocations;
00976
00977 static NodeNodeMemoizer _memo_nn;
00978 static NodeValueMemoizer _memo_nv;
00979 static QuadrupleMemoizer _memo_quad;
00980
00981 static NodePtr _unf_apply_rec(const NodePtr& n1, const NodePtr& n2, bool meet) {
00982 if (not n1 or not n2)
00983 abort();
00984 NodePtr result = _memo_nn.get(n1, n2);
00985 V value;
00986 L::top(value);
00987 if (not result) {
00988 if (n1->index() == 0 and n2->index() == 0) {
00989 V value = n1->value();
00990 if (meet)
00991 L::meet(value, n2->value(), value);
00992 else
00993 L::join(value, n2->value(), value);
00994 result = _mk(0, value, NULL, NULL);
00995 }
00996 else if (n1->index() == n2->index()) {
00997 NodePtr lo = _unf_apply_rec(n1->lo(), n2->lo(), meet);
00998 NodePtr hi = _unf_apply_rec(n1->hi(), n2->hi(), meet);
00999 if (lo == hi) {
01000 result = lo;
01001 }
01002 else {
01003 result = _mk(n1->index(), value, lo, hi);
01004 }
01005 }
01006 else {
01007 const NodePtr *new_n1 = &n1, *new_n2 = &n2;
01008 if (n1->index() < n2->index()) {
01009 new_n1 = &n2;
01010 new_n2 = &n1;
01011 }
01012 NodePtr lo = _unf_apply_rec((*new_n1)->lo(), *new_n2, meet);
01013 NodePtr hi = _unf_apply_rec((*new_n1)->hi(), *new_n2, meet);
01014 if (lo == hi) {
01015 result = lo;
01016 }
01017 else {
01018 result = _mk((*new_n1)->index(), value, lo, hi);
01019 }
01020 }
01021 _memo_nn.set(n1, n2, result);
01022 }
01023 return result;
01024 }
01025
01026 static NodePtr _snf_rpc(const NodePtr& n, const V& d) {
01027 V value = n->value();
01028 if (F == SNF_MEET) {
01029 L::rpc(d, value, value);
01030 }
01031 else {
01032 L::drpc(d, value, value);
01033 }
01034 if (n->index() == 0)
01035 return _mk(0, value, NULL, NULL);
01036 V x = n->lo()->value();
01037 if (F == SNF_MEET) {
01038 L::join(x, n->hi()->value(), x);
01039 L::meet(value, x, value);
01040 }
01041 else {
01042 L::meet(x, n->hi()->value(), x);
01043 L::join(value, x, value);
01044 }
01045 return _mk(n->index(), value, n->lo(), n->hi());
01046 }
01047
01048 static NodePtr _snf_easy_cst(const NodePtr& n, const V& value) {
01049 NodePtr result = _memo_nv.get(n, value);
01050 if (result) {
01051 return result;
01052 }
01053 if ((F == SNF_MEET and L::less(n->value(), value)) or (F == SNF_JOIN and L::less(value,
01054 n->value()))) {
01055 result = n;
01056 }
01057 else {
01058 V new_value = value;
01059 if (F == SNF_MEET)
01060 L::meet(new_value, n->value(), new_value);
01061 else
01062 L::join(new_value, n->value(), new_value);
01063 if (n->index() == 0) {
01064 result = _mk(0, new_value, NULL, NULL);
01065 }
01066 else {
01067 NodePtr lo, hi, new_lo, new_hi;
01068 lo = _snf_easy_cst(n->lo(), value);
01069 hi = _snf_easy_cst(n->hi(), value);
01070 if (lo == hi) {
01071 V label = lo->value();
01072 if (F == SNF_MEET)
01073 L::meet(label, value, label);
01074 else
01075 L::join(label, value, label);
01076 result = _mk(lo->index(), label, lo->lo(), lo->hi());
01077 }
01078 else {
01079 new_lo = _snf_rpc(lo, value);
01080 new_hi = _snf_rpc(hi, value);
01081 if (new_lo == new_hi)
01082 abort();
01083 result = _mk(n->index(), new_value, new_lo, new_hi);
01084 }
01085 }
01086 }
01087 _memo_nv.set(n, value, result);
01088 return result;
01089 }
01090
01091 static NodePtr _snf_easy_rec(const NodePtr& n1, const NodePtr& n2) {
01092 if (not n1 or not n2)
01093 abort();
01094 NodePtr result = _memo_nn.get(n1, n2);
01095 if (result) {
01096 return result;
01097 }
01098 if (n1->index() == 0)
01099 result = _snf_easy_cst(n2, n1->value());
01100 else if (n2->index() == 0)
01101 result = _snf_easy_cst(n1, n2->value());
01102 else if (n1->index() == n2->index()) {
01103 NodePtr lo = _snf_easy_rec(n1->lo(), n2->lo());
01104 NodePtr hi = _snf_easy_rec(n1->hi(), n2->hi());
01105 V cst_value = n1->value();
01106 if (F == SNF_MEET)
01107 L::meet(cst_value, n2->value(), cst_value);
01108 else
01109 L::join(cst_value, n2->value(), cst_value);
01110 NodePtr new_lo = _snf_easy_cst(lo, cst_value);
01111 NodePtr new_hi = _snf_easy_cst(hi, cst_value);
01112 if (new_lo == new_hi) {
01113 result = new_lo;
01114 }
01115 else {
01116 cst_value = new_lo->value();
01117 if (F == SNF_MEET) {
01118 L::join(cst_value, new_hi->value(), cst_value);
01119 }
01120 else {
01121 L::meet(cst_value, new_hi->value(), cst_value);
01122 }
01123 lo = _snf_rpc(new_lo, cst_value);
01124 hi = _snf_rpc(new_hi, cst_value);
01125 if (lo == hi) {
01126 result = lo;
01127 }
01128 else {
01129 result = _mk(n1->index(), cst_value, lo, hi);
01130 }
01131 }
01132 }
01133 else {
01134 const NodePtr *new_n1 = &n1, *new_n2 = &n2;
01135 if (n1->index() < n2->index()) {
01136 new_n1 = &n2;
01137 new_n2 = &n1;
01138 }
01139 NodePtr lo = _snf_easy_rec((*new_n1)->lo(), *new_n2);
01140 NodePtr hi = _snf_easy_rec((*new_n1)->hi(), *new_n2);
01141 V cst_value = (*new_n1)->value();
01142 NodePtr new_lo = _snf_easy_cst(lo, cst_value);
01143 NodePtr new_hi = _snf_easy_cst(hi, cst_value);
01144 if (new_lo == new_hi) {
01145 result = new_lo;
01146 }
01147 else {
01148 cst_value = new_lo->value();
01149 if (F == SNF_MEET) {
01150 L::join(cst_value, new_hi->value(), cst_value);
01151 }
01152 else {
01153 L::meet(cst_value, new_hi->value(), cst_value);
01154 }
01155 lo = _snf_rpc(new_lo, cst_value);
01156 hi = _snf_rpc(new_hi, cst_value);
01157 if (lo == hi) {
01158 result = lo;
01159 }
01160 else {
01161 result = _mk((*new_n1)->index(), cst_value, lo, hi);
01162 }
01163 }
01164 }
01165 _memo_nn.set(n1, n2, result);
01166 return result;
01167 }
01168
01169 static NodePtr _snf_hard_rec(const NodePtr& n1, const NodePtr& n2, const V& d1, const V& d2) {
01170 NodePtr result = _memo_quad.get(n1, n2, d1, d2);
01171 if (result) {
01172 return result;
01173 }
01174 V new_d1 = d1, new_d2 = d2;
01175 if (F == SNF_MEET) {
01176 L::meet(new_d1, n1->value(), new_d1);
01177 L::meet(new_d2, n2->value(), new_d2);
01178 }
01179 else {
01180 L::join(new_d1, n1->value(), new_d1);
01181 L::join(new_d2, n2->value(), new_d2);
01182 }
01183 if (n1->index() == 0 and n2->index() == 0) {
01184 V value = new_d1;
01185 if (F == SNF_MEET)
01186 L::join(value, new_d2, value);
01187 else
01188 L::meet(value, new_d2, value);
01189 result = _mk(0, value, NULL, NULL);
01190 _memo_quad.set(n1, n2, d1, d2, result);
01191 return result;
01192 }
01193 else if (n1->index() == n2->index()) {
01194 NodePtr lo = _snf_hard_rec(n1->lo(), n2->lo(), new_d1, new_d2);
01195 NodePtr hi = _snf_hard_rec(n1->hi(), n2->hi(), new_d1, new_d2);
01196 if (lo == hi) {
01197 result = lo;
01198 }
01199 else {
01200 V value = lo->value();
01201 if (F == SNF_MEET) {
01202 L::join(value, hi->value(), value);
01203 }
01204 else {
01205 L::meet(value, hi->value(), value);
01206 }
01207 NodePtr new_lo = _snf_rpc(lo, value);
01208 NodePtr new_hi = _snf_rpc(hi, value);
01209 result = _mk(n1->index(), value, new_lo, new_hi);
01210 }
01211 _memo_quad.set(n1, n2, d1, d2, result);
01212 return result;
01213 }
01214 else {
01215 const NodePtr *new_n1 = &n1, *new_n2 = &n2;
01216 bool swapped = false;
01217 if (n1->index() < n2->index()) {
01218 new_n1 = &n2;
01219 new_n2 = &n1;
01220 swapped = true;
01221 swap(new_d1, new_d2);
01222 }
01223 NodePtr lo = _snf_hard_rec((*new_n1)->lo(), *new_n2, new_d1, new_d2);
01224 NodePtr hi = _snf_hard_rec((*new_n1)->hi(), *new_n2, new_d1, new_d2);
01225 if (lo == hi) {
01226 result = lo;
01227 }
01228 else {
01229 V value = lo->value();
01230 if (F == SNF_MEET) {
01231 L::join(value, hi->value(), value);
01232 }
01233 else {
01234 L::meet(value, hi->value(), value);
01235 }
01236 NodePtr new_lo = _snf_rpc(lo, value);
01237 NodePtr new_hi = _snf_rpc(hi, value);
01238 result = _mk((*new_n1)->index(), value, new_lo, new_hi);
01239 }
01240 if (swapped)
01241 _memo_quad.set(n2, n1, d1, d2, result);
01242 else
01243 _memo_quad.set(n1, n2, d1, d2, result);
01244 return result;
01245 }
01246 }
01247
01248 static NodePtr _fetch_orphan() {
01249 Node* result;
01250 typename list<Node*>::iterator it;
01251 for (it = _orphans.begin(); it != _orphans.end();) {
01252 if ((*it)->refcount() == 0)
01253 break;
01254 it = _orphans.erase(it);
01255 }
01256 if (it == _orphans.end()) {
01257 result = NULL;
01258 }
01259 else {
01260 Node* n = *it;
01261 _orphans.erase(it);
01262 _hash_map.erase(n);
01263 result = n;
01264 }
01265 return NodePtr(result);
01266 }
01267
01268 static NodePtr _mkbot() {
01269 V v;
01270 L::bot(v);
01271 return _mk(0, v, NULL, NULL);
01272 }
01273
01274 static NodePtr _mktop() {
01275 V v;
01276 L::top(v);
01277 return _mk(0, v, NULL, NULL);
01278 }
01279
01280 static void _add_orphan(Node* n) {
01281 if (n == NULL or n->refcount() != 0)
01282 throw runtime_error("invalid orphan node");
01283 _hash_map.erase(n);
01284 _orphans.push_back(n);
01285 }
01286
01287 static NodePtr _mk(int index, const V& value, const NodePtr& lo, const NodePtr& hi) {
01288
01289 typename HashMap::const_iterator it;
01290
01291 _mk_call_count++;
01292
01293 NodePtr result;
01294 if (lo == hi and lo) {
01295 abort();
01296 }
01297 else {
01298 Node key(index, value, lo, hi);
01299 it = _hash_map.find(&key);
01300 if (it == _hash_map.end()) {
01301 result = _fetch_orphan();
01302 if (not result) {
01303 _node_allocations++;
01304 result.grab(new Node(index, value, lo, hi));
01305 }
01306 else {
01307 if (result->refcount() != 1)
01308 abort();
01309 _orphan_fetches++;
01310 *result = key;
01311 result->set_refcount(1);
01312 }
01313 _hash_map[result.get_ptr()] = result.get_ptr();
01314 }
01315 else {
01316 result.grab(it->second);
01317 }
01318 }
01319
01320 return result;
01321 }
01322
01323 void _quantify_rec(const NodePtr& n, map<NodePtr, V>& memo, V& result, bool exists) const {
01324 typename map<NodePtr, V>::iterator it;
01325 it = memo.find(n);
01326 if (it != memo.end())
01327 result = it->second;
01328 else if (n->index() == 0) {
01329 result = n->value();
01330 memo[n] = result;
01331 }
01332 else {
01333 V tmp;
01334 _quantify_rec(n->lo(), memo, tmp, exists);
01335 _quantify_rec(n->hi(), memo, result, exists);
01336 if (exists) {
01337 L::join(result, tmp, result);
01338 }
01339 else {
01340 L::meet(result, tmp, result);
01341 }
01342 if (F == SNF_MEET) {
01343 L::meet(result, n->value(), result);
01344 }
01345 else {
01346 L::join(result, n->value(), result);
01347 }
01348 memo[n] = result;
01349 }
01350 }
01351
01352 static void _eval_rec(const vector<bool>& valuation, const NodePtr& node, V& result) {
01353 if (node->index() == 0) {
01354 node->value(result);
01355 return;
01356 }
01357 if (node->index() > (int) valuation.size()) {
01358 throw logic_error("eval : bad valuation");
01359 }
01360 NodePtr next = valuation[node->index() - 1] ? node->hi() : node->lo();
01361 if (F == SNF_JOIN) {
01362 V tmp;
01363 _eval_rec(valuation, next, tmp);
01364 L::join(tmp, node->value(), result);
01365 }
01366 else {
01367 V tmp;
01368 _eval_rec(valuation, next, tmp);
01369 L::meet(tmp, node->value(), result);
01370 }
01371 }
01372
01373 public:
01374
01378 LVBDD() {
01379 _root = _mkbot();
01380 }
01381
01385 ~LVBDD() {
01386
01387 }
01388
01392 LVBDD(const LVBDD& other) {
01393 _root = other._root;
01394 }
01395
01399 LVBDD& operator=(const LVBDD& other) {
01400 if (this != &other) {
01401 _root = other._root;
01402 }
01403 return *this;
01404 }
01405
01410 bool operator==(const LVBDD& other) const {
01411 return _root == other._root;
01412 }
01413
01417 bool operator!=(const LVBDD& other) const {
01418 return _root != other._root;
01419 }
01420
01424 static LVBDD terminal(const V& value) {
01425 LVBDD res;
01426 res._root = _mk(0, value, NULL, NULL);
01427 return res;
01428 }
01429
01435 static LVBDD literal(int index, bool positive) {
01436 if (index <= 0)
01437 throw invalid_argument("bad index");
01438 LVBDD res;
01439 NodePtr lo = positive ? _mkbot() : _mktop();
01440 NodePtr hi = positive ? _mktop() : _mkbot();
01441 V value;
01442 if (F == SNF_JOIN)
01443 L::bot(value);
01444 else
01445 L::top(value);
01446 res._root = _mk(index, value, lo, hi);
01447 return res;
01448 }
01449
01453 static LVBDD top() {
01454 LVBDD result;
01455 V value;
01456 L::top(value);
01457 result._root = _mk(0, value, NULL, NULL);
01458 return result;
01459 }
01460
01464 static LVBDD bot() {
01465 LVBDD result;
01466 V value;
01467 L::bot(value);
01468 result._root = _mk(0, value, NULL, NULL);
01469 return result;
01470 }
01471
01482 static LVBDD _mk_unsafe(int index, V value, LVBDD lo, LVBDD hi) {
01483 if (index < 1)
01484 throw logic_error("bad index");
01485 if (lo == hi)
01486 throw logic_error("lo and hi are the same");
01487 LVBDD result;
01488 result._root = _mk(index, value, lo._root, hi._root);
01489 return result;
01490 }
01491
01495 static int orphan_count() {
01496 int count = 0;
01497 for (typename list<Node*>::iterator it = _orphans.begin(); it != _orphans.end(); it++) {
01498 if ((*it)->refcount() == 0)
01499 count++;
01500 }
01501 return count;
01502 }
01503
01507 static void print_hashmap_debug(ostream& out = cout) {
01508 out << endl;
01509 typename HashMap::iterator it;
01510 for (it = _hash_map.begin(); it != _hash_map.end(); it++) {
01511 Node* n = (*it).second;
01512 out << "@" << n << " index=" << n->index();
01513 out << " lo@" << setw(10) << n->lo();
01514 out << " hi@" << setw(10) << n->hi();
01515 out << " rc=" << n->refcount();
01516 out << " value=" << n->value();
01517 out << " hash=" << n->hash();
01518 out << endl;
01519 }
01520 print_hashmap_stats();
01521 out << endl;
01522 }
01523
01527 static void print_hashmap_stats(ostream& out = cout) {
01528 set<size_t, less<size_t> > hashes;
01529 map<int, int, less<int> > hash_count;
01530 for (typename HashMap::iterator it = _hash_map.begin(); it != _hash_map.end(); it++) {
01531 hashes.insert(it->second->hash());
01532 if (hash_count.find(it->second->hash()) == hash_count.end()) {
01533 hash_count[it->second->hash()] = 1;
01534 }
01535 else {
01536 hash_count[it->second->hash()] += 1;
01537 }
01538 }
01539 int max = -1;
01540 int max_hash = -1;
01541 map<int, int, less<int> >::const_iterator itt;
01542 for (itt = hash_count.begin(); itt != hash_count.end(); itt++) {
01543 if (itt->second > max) {
01544 max = itt->second;
01545 max_hash = itt->first;
01546 }
01547 }
01548 float lf = float(_hash_map.size()) / _hash_map.bucket_count();
01549 out << "HashMap size = " << _hash_map.size() << endl;
01550 out << "HashMap load factor = " << lf << endl;
01551 out << "HashMap bucket count = " << _hash_map.bucket_count() << endl;
01552 out << "# of different hashes = " << hashes.size() << endl;
01553 out << "Most usage of hash key = " << max << " (" << max_hash << ")";
01554 out << endl;
01555 out << "# of calls to MK = " << _mk_call_count << endl;
01556 float pct = 100.0 - ((100.0 * (_orphan_fetches + _node_allocations)) / _mk_call_count);
01557 out << "# of MK cache hits = " << _mk_call_count - _orphan_fetches - _node_allocations;
01558 out << " (" << pct << "%)" << endl;
01559 pct = (100.0 * _orphan_fetches) / _mk_call_count;
01560 out << "# of orphans reused = " << _orphan_fetches << " (";
01561 out << pct << "%)" << endl;
01562 pct = (100.0 * _node_allocations) / _mk_call_count;
01563 out << "# of node allocations = " << _node_allocations << " (";
01564 out << pct << "%)" << endl;
01565 out << "# of orphan nodes = " << orphan_count() << endl;
01566 }
01567
01571 static void free_orphaned_nodes() {
01572 typename list<Node*>::iterator it;
01573 Node* n;
01574 for (it = _orphans.begin(); it != _orphans.end(); it++) {
01575 if ((*it)->refcount())
01576 continue;
01577 n = *it;
01578 delete n;
01579 }
01580 _orphans.clear();
01581 }
01582
01586 static void clear_memoization_tables() {
01587 _memo_quad.clear();
01588 _memo_nn.clear();
01589 _memo_nv.clear();
01590 }
01591
01595 static int memoization_tables_size() {
01596 return _memo_quad.size() + _memo_nn.size() + _memo_nv.size();
01597 }
01598
01603 static size_t total_node_count() {
01604 return _hash_map.size();
01605 }
01606
01610 static size_t node_count() {
01611 return total_node_count() - orphan_count();
01612 }
01613
01618 static void init() {
01619 Node *dk = new Node();
01620 *dk = Node::deleted_key();
01621 _hash_map.set_deleted_key(dk);
01622 #ifdef USING_DENSE_HASH_MAP
01623 Node *ek = new Node();
01624 *ek = Node::empty_key();
01625 _hash_map.set_empty_key(ek);
01626 #endif
01627 }
01628
01633 LVBDD join(const LVBDD& other) const {
01634 LVBDD result;
01635 if (F == SNF_MEET) {
01636 V value;
01637 L::top(value);
01638 result._root = _snf_hard_rec(_root, other._root, value, value);
01639 }
01640 else if (F == SNF_JOIN) {
01641 result._root = _snf_easy_rec(_root, other._root);
01642 }
01643 else {
01644 result._root = _unf_apply_rec(_root, other._root, false);
01645 }
01646 return result;
01647 }
01648
01652 LVBDD operator|(const LVBDD& other) const {
01653 return join(other);
01654 }
01655
01660 LVBDD meet(const LVBDD& other) const {
01661 LVBDD result;
01662 if (F == SNF_JOIN) {
01663 V value;
01664 L::bot(value);
01665 result._root = _snf_hard_rec(_root, other._root, value, value);
01666 }
01667 else if (F == SNF_MEET) {
01668 result._root = _snf_easy_rec(_root, other._root);
01669 }
01670 else {
01671 result._root = _unf_apply_rec(_root, other._root, true);
01672 }
01673 return result;
01674 }
01675
01679 LVBDD operator&(const LVBDD& other) const {
01680 return meet(other);
01681 }
01682
01686 int size() const {
01687 set<Node*> my_nodes;
01688 _root->_descendants(my_nodes);
01689 return my_nodes.size();
01690 }
01691
01695 int nonterminal_size() const {
01696 set<Node*> my_nodes;
01697 _root->_descendants(my_nodes);
01698 typename set<Node*>::iterator it;
01699 int count = 0;
01700 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
01701 if ((*it)->index() != 0) {
01702 count++;
01703 }
01704 }
01705 return count;
01706 }
01707
01711 int terminal_size() const {
01712 set<Node*> my_nodes;
01713 _root->_descendants(my_nodes);
01714 typename set<Node*>::iterator it;
01715 int count = 0;
01716 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
01717 if ((*it)->index() == 0) {
01718 count++;
01719 }
01720 }
01721 return count;
01722 }
01723
01728 int values_size() const {
01729 set<Node*> my_nodes;
01730 _root->_descendants(my_nodes);
01731 list<V> l;
01732 typename set<Node*>::iterator it;
01733 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
01734 V val = (*it)->value();
01735 l.push_back(val);
01736 }
01737 return L::list_size(l);
01738 }
01739
01743 void print_graphviz(ostream& out = cout) const {
01744 Node::print_graphviz(out, _root);
01745 }
01746
01750 static void print_graphviz_debug(ostream& out = cout) {
01751 Node::print_graphviz(out, NULL);
01752 }
01753
01757 void exists(V& result) const {
01758 if (F == SNF_MEET) {
01759 result = _root->value();
01760 }
01761 else {
01762 map<NodePtr, V> memo;
01763 _quantify_rec(_root, memo, result, true);
01764 }
01765 }
01766
01770 V exists() const {
01771 V result;
01772 exists(result);
01773 return result;
01774 }
01775
01779 void forall(V& result) const {
01780 if (F == SNF_JOIN) {
01781 result = _root->value();
01782 }
01783 else {
01784 map<NodePtr, V> memo;
01785 _quantify_rec(_root, memo, result, false);
01786 }
01787 }
01788
01792 V forall() const {
01793 V result;
01794 forall(result);
01795 return result;
01796 }
01797
01802 LVBDD lo() const {
01803 if (_root->index() == 0)
01804 throw logic_error("called lo() on terminal LVBDD");
01805 LVBDD result;
01806 result._root = _root->lo();
01807 return result;
01808 }
01809
01814 LVBDD hi() const {
01815 if (_root->index() == 0)
01816 throw logic_error("called hi() on terminal LVBDD");
01817 LVBDD result;
01818 result._root = _root->hi();
01819 return result;
01820 }
01821
01826 int index() const {
01827 return _root->index();
01828 }
01829
01833 void root_value(V& result) const {
01834 _root->value(result);
01835 }
01836
01840 V root_value() const {
01841 return _root->value();
01842 }
01843
01850 void evaluate(const vector<bool>& valuation, V& result) const {
01851 result = _eval_rec(valuation, _root, result);
01852 }
01853
01860 V evaluate(const vector<bool>& valuation) const {
01861 V result;
01862 _eval_rec(valuation, _root, result);
01863 return result;
01864 }
01865
01869 friend ostream& operator<<(ostream& out, const LVBDD& dd) {
01870 out << dd._root.get_ptr();
01871 return out;
01872 }
01873
01874 };
01875
01876 template<class L, int F>
01877 typename LVBDD<L, F>::HashMap LVBDD<L, F>::_hash_map;
01878
01879 template<class L, int F>
01880 list<Node<L, F>*> LVBDD<L, F>::_orphans;
01881
01882 template<class L, int F>
01883 int LVBDD<L, F>::_mk_call_count;
01884
01885 template<class L, int F>
01886 int LVBDD<L, F>::_orphan_fetches;
01887
01888 template<class L, int F>
01889 int LVBDD<L, F>::_node_allocations;
01890
01891 template<class L, int F>
01892 typename LVBDD<L, F>::NodeNodeMemoizer LVBDD<L, F>::_memo_nn;
01893
01894 template<class L, int F>
01895 typename LVBDD<L, F>::NodeValueMemoizer LVBDD<L, F>::_memo_nv;
01896
01897 template<class L, int F>
01898 typename LVBDD<L, F>::QuadrupleMemoizer LVBDD<L, F>::_memo_quad;
01899
01900 }
01901
01902
01903 #endif