00001
00002
00003
00004
00005
00006
00007
00195 #ifndef __LAVABDD_H__
00196 #define __LAVABDD_H__
00197
00202 #define USING_DENSE_HASH_MAP
00203
00208 #define INITIAL_REFCOUNT 0
00209
00210 #include <list>
00211 #include <stdexcept>
00212 #include <iomanip>
00213 #include <iostream>
00214 #include <fstream>
00215 #include <map>
00216 #include <set>
00217 #include <vector>
00218
00219 #ifdef USING_DENSE_HASH_MAP
00220 #include <google/dense_hash_map>
00221 using google::dense_hash_map;
00222 #else
00223 #include <google/sparse_hash_map>
00224 using google::sparse_hash_map;
00225 #endif
00226
00227 using namespace std;
00228
00232 namespace lava {
00233
00237 const int UNF = 0;
00238
00243 const int SNF_MEET = 1;
00244
00249 const int SNF_JOIN = 2;
00250
00251
00252
00257 inline int hash_int(int key) {
00258 key = ~key + (key << 15);
00259 key = key ^ (key >> 12);
00260 key = key + (key << 2);
00261 key = key ^ (key >> 4);
00262 key = key * 2057;
00263 key = key ^ (key >> 16);
00264 return key;
00265 }
00266
00267
00268
00272 template<typename V>
00273 class Lattice {
00274
00275 public:
00276
00277 typedef V __V__;
00278
00283 static bool less(const V& x, const V& y) {
00284 throw logic_error("Lattice::less not implemented.");
00285 }
00286
00290 static bool equal(const V& x, const V& y) {
00291 throw logic_error("Lattice::equal not implemented.");
00292 }
00293
00297 static void join(const V& x, const V& y, V& z) {
00298 throw logic_error("Lattice::join not implemented.");
00299 }
00300
00304 static void meet(const V& x, const V& y, V& z) {
00305 throw logic_error("Lattice::meet not implemented.");
00306 }
00307
00312 static void rpc(const V& x, const V& y, V& z) {
00313 throw logic_error("Lattice::rpc not implemented.");
00314 }
00315
00320 static void drpc(const V& x, const V& y, V& z) {
00321 throw logic_error("Lattice::drpc not implemented.");
00322 }
00323
00327 static void top(V& x) {
00328 throw logic_error("Lattice::top not implemented.");
00329 }
00330
00334 static void bot(V& x) {
00335 throw logic_error("Lattice::bot not implemented.");
00336 }
00337
00346 static size_t hash(const V& x) {
00347 throw logic_error("Lattice::hash not implemented.");
00348 }
00349
00353 static void print(const V& x, ostream& out) {
00354 throw logic_error("Lattice::print not implemented.");
00355 }
00356
00362 static int size(const V& x) {
00363 throw logic_error("Lattice::size not implemented.");
00364 }
00365
00372 static int list_size(const list<V>& l) {
00373 throw logic_error("Lattice::list_size not implemented.");
00374 }
00375
00376 };
00377
00378
00379
00380 template<class L, int F> class Node;
00381
00388 template<class L, int F> class NodePtr {
00389
00390 private:
00391
00392 typedef typename L::__V__ V;
00393 typedef Node<L, F> Node;
00394
00395 Node* _node;
00396
00397 public:
00398
00399 NodePtr() {
00400 _node = NULL;
00401 }
00402
00407 NodePtr(Node* node) {
00408 _node = node;
00409 if (_node)
00410 _node->_ref();
00411 }
00412
00416 ~NodePtr() {
00417 if (_node)
00418 _node->_unref();
00419 }
00420
00424 NodePtr(const NodePtr& other) {
00425 _node = other._node;
00426 if (_node)
00427 _node->_ref();
00428 }
00429
00433 NodePtr& operator=(const NodePtr& other) {
00434 if (this != &other) {
00435 if (_node)
00436 _node->_unref();
00437 _node = other._node;
00438 if (_node)
00439 _node->_ref();
00440 }
00441 return *this;
00442 }
00443
00447 Node& operator*() const {
00448 if (_node == NULL)
00449 throw logic_error("NodePtr : NULL pointer access");
00450 return *_node;
00451 }
00452
00456 Node* operator->() const {
00457 if (_node == NULL)
00458 throw logic_error("NodePtr : NULL pointer access");
00459 return _node;
00460 }
00461
00467 Node* get_ptr() const {
00468 return _node;
00469 }
00470
00474 bool operator==(const NodePtr& other) const {
00475 return _node == other._node;
00476 }
00477
00481 bool operator!=(const NodePtr& other) const {
00482 return _node != other._node;
00483 }
00484
00488 bool operator<(const NodePtr& other) const {
00489 return _node < other._node;
00490 }
00491
00495 operator bool() const {
00496 return _node ? true : false;
00497 }
00498
00502 void nullify() {
00503 if (_node)
00504 _node->_unref();
00505 _node = NULL;
00506 }
00507
00511 void grab(Node *node) {
00512 if (_node)
00513 _node->_unref();
00514 _node = node;
00515 if (_node)
00516 _node->_ref();
00517 }
00518
00519 };
00520
00521 template<class L, int F> class LVBDD;
00522
00529 template<class L, int F> class Node {
00530
00531 private:
00532
00533 typedef typename L::__V__ V;
00534
00535 friend class NodePtr<L, F> ;
00536 typedef NodePtr<L, F> NodePtr;
00537 typedef LVBDD<L, F> LVBDD;
00538
00539 int _refcount;
00540 int _index;
00541 V _value;
00542 size_t _hash;
00543
00544 NodePtr _lo;
00545 NodePtr _hi;
00546
00547 void _unref() {
00548 if (_refcount <= 0) {
00549 throw runtime_error("unref on orphan Node");
00550 }
00551 _refcount--;
00552 if (_refcount == 0) {
00553 LVBDD::_add_orphan(this);
00554 _lo.nullify();
00555 _hi.nullify();
00556 _index = -1;
00557 }
00558 }
00559
00560 void _ref() {
00561 _refcount++;
00562 }
00563
00564 public:
00565
00566
00567
00568
00569 Node() {
00570 }
00571
00584 Node(int index, const V& val, NodePtr lo, NodePtr hi) :
00585 _refcount(INITIAL_REFCOUNT), _index(index), _value(val), _lo(lo), _hi(hi) {
00586 _hash = L::hash(_value) ^ hash_int(_index);
00587 if (lo)
00588 _hash ^= hash_int(((size_t) lo.get_ptr()) * 17);
00589 if (hi)
00590 _hash ^= hash_int(((size_t) hi.get_ptr()));
00591 }
00592
00597 int index() const {
00598 return _index;
00599 }
00600
00605 size_t hash() const {
00606 return _hash;
00607 }
00608
00612 int refcount() const {
00613 return _refcount;
00614 }
00615
00619 const V& value() const {
00620 return _value;
00621 }
00622
00626 NodePtr lo() const {
00627 return _lo;
00628 }
00629
00633 NodePtr hi() const {
00634 return _hi;
00635 }
00636
00637
00638
00639
00640 NodePtr _lo_const_bypass() const {
00641 return _lo;
00642 }
00643
00644
00645
00646
00647 NodePtr _hi_const_bypass() const {
00648 return _hi;
00649 }
00650
00655 bool operator==(const Node& other) const {
00656 return _hash == other._hash && _index == other._index && _lo == other._lo
00657 && _hi == other._hi && L::equal(_value, other._value);
00658 }
00659
00663 bool operator!=(const Node& other) const {
00664 return not (*this == other);
00665 }
00666
00667
00668
00669
00670 void _new_refcount() {
00671 _refcount = 1;
00672 }
00673
00674
00675
00676
00677 static Node deleted_key() {
00678 Node key;
00679 key._refcount = -1;
00680 key._index = -1;
00681 key._hash = -1;
00682 return key;
00683 }
00684
00685
00686
00687
00688 static Node empty_key() {
00689 Node key;
00690 key._refcount = -2;
00691 key._index = -2;
00692 key._hash = -2;
00693 return key;
00694 }
00695
00702 static void print_graphviz(ostream& out = cout, NodePtr root = NULL) {
00703 set<Node*> my_nodes;
00704 if (not root) {
00705 typename LVBDD::HashMap::const_iterator it;
00706 for (it = LVBDD::_hash_map.begin(); it != LVBDD::_hash_map.end(); it++) {
00707 my_nodes.insert(it->second);
00708 }
00709 }
00710 else {
00711 root->_descendants(my_nodes);
00712 }
00713 typename set<Node*>::iterator it;
00714 out << "digraph G {" << endl;
00715 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
00716 if ((*it)->index() == 0) {
00717 out << "\"" << *it << "\" [label=\"";
00718 L::print((*it)->value(), out);
00719 if (*it == root.get_ptr())
00720 out << " (" << (*it)->refcount() - 1 << ")";
00721 else
00722 out << " (" << (*it)->refcount() << ")";
00723 out << "\", shape=box];" << endl;
00724 }
00725 else {
00726 out << "\"" << *it << "\" [label=\"" << (*it)->index() << " : ";
00727 L::print((*it)->value(), out);
00728 if (*it == root.get_ptr())
00729 out << " (" << (*it)->refcount() - 1 << ")";
00730 else
00731 out << " (" << (*it)->refcount() << ")";
00732 out << "\"];" << endl;
00733 }
00734 }
00735 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
00736 if ((*it)->lo()) {
00737 out << "\"" << *it << "\" -> " << "\"" << ((*it)->lo().get_ptr());
00738 out << "\" [style=dotted, arrowhead=none];" << endl;
00739 }
00740 if ((*it)->lo()) {
00741 out << "\"" << *it << "\" -> " << "\"" << ((*it)->hi().get_ptr());
00742 out << "\" [arrowhead=none];" << endl;
00743 }
00744 }
00745 out << "}" << endl;
00746 }
00747
00748 void _descendants(set<Node*>& nodes) {
00749 nodes.clear();
00750 set<Node*> to_visit;
00751 typename set<Node*>::iterator it;
00752 to_visit.insert(this);
00753 Node* n;
00754 while (to_visit.size() > 0) {
00755 it = to_visit.begin();
00756 n = *it;
00757 to_visit.erase(it);
00758 if (nodes.find(n) == nodes.end()) {
00759 nodes.insert(n);
00760 if (n->index() > 0) {
00761 to_visit.insert(n->lo().get_ptr());
00762 to_visit.insert(n->hi().get_ptr());
00763 }
00764 }
00765 }
00766 }
00767
00768 };
00769
00770
00771
00778 template<class L, int F>
00779 class LVBDD {
00780
00781 private:
00782
00783 typedef typename L::__V__ V;
00784
00785
00786
00787 struct NodeHashFunction {
00788 size_t operator()(Node<L, F>* const & n) const {
00789 return n->hash();
00790 }
00791 };
00792
00793 struct NodeEqualFunction {
00794 bool operator()(Node<L, F>* const & n1, Node<L, F>* const & n2) const {
00795 return (*n1) == (*n2);
00796 }
00797 };
00798
00799
00800
00801 struct Quadruple {
00802 NodePtr<L, F> n1, n2;
00803 V d1, d2;
00804 };
00805
00806 struct QuadrupleLT {
00807 bool operator()(const Quadruple& a, const Quadruple& b) const {
00808 if (a.n1->hash() != b.n1->hash())
00809 return a.n1->hash() < b.n1->hash();
00810 if (a.n2->hash() != b.n2->hash())
00811 return a.n2->hash() < b.n2->hash();
00812 if (L::hash(a.d1) != L::hash(b.d1))
00813 return L::hash(a.d1) < L::hash(b.d1);
00814 if (L::hash(a.d2) != L::hash(b.d2))
00815 return L::hash(a.d2) < L::hash(b.d2);
00816 return false;
00817 }
00818 };
00819
00820
00821
00822 class QuadrupleMemoizer {
00823
00824 typedef Node<L, F> Node;
00825 typedef NodePtr<L, F> NodePtr;
00826
00827 typedef map<const Quadruple, NodePtr, QuadrupleLT> MAP;
00828 MAP _map;
00829
00830 public:
00831
00832 NodePtr get(NodePtr n1, NodePtr n2, const V& d1, const V& d2) const {
00833 Quadruple q1, q2;
00834 q1.n1 = n1;
00835 q2.n1 = n2;
00836 q1.n2 = n2;
00837 q2.n2 = n1;
00838 q1.d1 = d1;
00839 q2.d1 = d2;
00840 q1.d2 = d2;
00841 q2.d2 = d1;
00842 typename MAP::const_iterator it;
00843 it = _map.find(q1);
00844 if (it != _map.end())
00845 return it->second;
00846 it = _map.find(q2);
00847 if (it != _map.end())
00848 return it->second;
00849 return NULL;
00850 }
00851
00852 void set(NodePtr n1, NodePtr n2, const V& d1, const V& d2, NodePtr memo) {
00853 Quadruple q;
00854 q.n1 = n1;
00855 q.n2 = n2;
00856 q.d1 = d1;
00857 q.d2 = d2;
00858 _map[q] = memo;
00859 }
00860
00861 void clear() {
00862 typename MAP::iterator it;
00863 for (it = _map.begin(); it != _map.end(); it++) {
00864 it->second.nullify();
00865 }
00866 _map.clear();
00867 }
00868
00869 };
00870
00871
00872
00873 class NodeNodeMemoizer {
00874
00875 typedef Node<L, F> Node;
00876 typedef NodePtr<L, F> NodePtr;
00877
00878 map<pair<NodePtr, NodePtr> , NodePtr> _map;
00879
00880 public:
00881
00882 NodePtr get(NodePtr n1, NodePtr n2) const {
00883 pair<NodePtr, NodePtr> p1(n1, n2);
00884 pair<NodePtr, NodePtr> p2(n2, n1);
00885 typename map<pair<NodePtr, NodePtr> , NodePtr>::const_iterator it;
00886 NodePtr result;
00887 it = _map.find(p1);
00888 if (it != _map.end()) {
00889 result = it->second;
00890 }
00891 else {
00892 it = _map.find(p2);
00893 if (it != _map.end())
00894 result = it->second;
00895 else
00896 result = NULL;
00897 }
00898 return result;
00899 }
00900
00901 void set(NodePtr n1, NodePtr n2, NodePtr memo) {
00902 pair<NodePtr, NodePtr> p(n1, n2);
00903 _map[p] = memo;
00904 }
00905
00906 void clear() {
00907 typename map<pair<NodePtr, NodePtr> , NodePtr>::iterator it;
00908 for (it = _map.begin(); it != _map.end(); it++) {
00909 it->second.nullify();
00910 }
00911 _map.clear();
00912 }
00913
00914 };
00915
00916
00917
00918 struct NodeValueLT {
00919 typedef Node<L, F> Node;
00920 typedef NodePtr<L, F> NodePtr;
00921
00922 bool operator()(const pair<NodePtr, V>& a, const pair<NodePtr, V>& b) const {
00923 if (a.first == b.first)
00924 return L::hash(a.second) < L::hash(b.second);
00925 else
00926 return a.first.get_ptr() < b.first.get_ptr();
00927 }
00928 };
00929
00930
00931
00932 class NodeValueMemoizer {
00933
00934 typedef Node<L, F> Node;
00935 typedef NodePtr<L, F> NodePtr;
00936 map<pair<NodePtr, V> , NodePtr, NodeValueLT> _map;
00937
00938 public:
00939
00940 NodePtr get(NodePtr n, const V& value) const {
00941 pair<NodePtr, V> p(n, value);
00942 typename map<pair<NodePtr, V> , NodePtr, NodeValueLT>::const_iterator
00943 it;
00944 it = _map.find(p);
00945 if (it != _map.end())
00946 return it->second;
00947 else
00948 return NULL;
00949 }
00950
00951 void set(NodePtr n, const V& value, NodePtr memo) {
00952 pair<NodePtr, V> p(n, value);
00953 _map[p] = memo;
00954 }
00955
00956 void clear() {
00957 typename map<pair<NodePtr, V> , NodePtr, NodeValueLT>::iterator it;
00958 for (it = _map.begin(); it != _map.end(); it++) {
00959 it->second.nullify();
00960 }
00961 _map.clear();
00962 }
00963
00964 };
00965
00966 friend class Node<L, F> ;
00967
00968 typedef Node<L, F> Node;
00969 typedef NodeHashFunction HashNode;
00970 typedef NodeEqualFunction EqualNode;
00971 typedef NodePtr<L, F> NodePtr;
00972
00973 #ifdef USING_DENSE_HASH_MAP
00974 typedef dense_hash_map<Node*, Node*, HashNode, EqualNode> HashMap;
00975 #else
00976 typedef sparse_hash_map<Node*, Node*, HashNode, EqualNode> HashMap;
00977 #endif
00978
00979 NodePtr _root;
00980
00981 static HashMap _hash_map;
00982 static list<Node*> _orphans;
00983
00984 static int _mk_call_count;
00985 static int _orphan_fetches;
00986 static int _node_allocations;
00987
00988 static NodeNodeMemoizer _memo_nn;
00989 static NodeValueMemoizer _memo_nv;
00990 static QuadrupleMemoizer _memo_quad;
00991
00992 static NodePtr _unf_apply_rec(NodePtr n1, NodePtr n2, bool meet) {
00993 if (not n1 or not n2)
00994 abort();
00995 NodePtr result = _memo_nn.get(n1, n2);
00996 V value;
00997 L::top(value);
00998 if (not result) {
00999 if (n1->index() == 0 and n2->index() == 0) {
01000 V value = n1->value();
01001 if (meet)
01002 L::meet(value, n2->value(), value);
01003 else
01004 L::join(value, n2->value(), value);
01005 result = _mk(0, value, NULL, NULL);
01006 }
01007 else if (n1->index() == n2->index()) {
01008 NodePtr lo = _unf_apply_rec(n1->lo(), n2->lo(), meet);
01009 NodePtr hi = _unf_apply_rec(n1->hi(), n2->hi(), meet);
01010 if (lo == hi) {
01011 result = lo;
01012 }
01013 else {
01014 result = _mk(n1->index(), value, lo, hi);
01015 }
01016 }
01017 else {
01018 if (n1->index() < n2->index())
01019 swap(n1, n2);
01020 NodePtr lo = _unf_apply_rec(n1->lo(), n2, meet);
01021 NodePtr hi = _unf_apply_rec(n1->hi(), n2, meet);
01022 if (lo == hi) {
01023 result = lo;
01024 }
01025 else {
01026 result = _mk(n1->index(), value, lo, hi);
01027 }
01028 }
01029 _memo_nn.set(n1, n2, result);
01030 }
01031 return result;
01032 }
01033
01034 static NodePtr _snf_rpc(NodePtr n, const V& d) {
01035 V value = n->value();
01036 if (F == SNF_MEET) {
01037 if (not L::less(value, d))
01038 throw logic_error("rpc order mismatch");
01039 L::rpc(d, value, value);
01040 }
01041 else {
01042 if (not L::less(d, value))
01043 throw logic_error("drpc order mismatch");
01044 L::drpc(d, value, value);
01045 }
01046 if (n->index() == 0)
01047 return _mk(0, value, NULL, NULL);
01048 V x = n->lo()->value();
01049 if (F == SNF_MEET) {
01050 L::join(x, n->hi()->value(), x);
01051 L::meet(value, x, value);
01052 }
01053 else {
01054 L::meet(x, n->hi()->value(), x);
01055 L::join(value, x, value);
01056 }
01057 return _mk(n->index(), value, n->_lo_const_bypass(), n->_hi_const_bypass());
01058 }
01059
01060 static NodePtr _snf_easy_cst(NodePtr n, const V& value) {
01061 NodePtr result = _memo_nv.get(n, value);
01062 if (result) {
01063 return result;
01064 }
01065 if ((F == SNF_MEET and L::less(n->value(), value)) or (F == SNF_JOIN
01066 and L::less(value, n->value()))) {
01067 result = n;
01068 }
01069 else {
01070 V new_value = value;
01071 if (F == SNF_MEET)
01072 L::meet(new_value, n->value(), new_value);
01073 else
01074 L::join(new_value, n->value(), new_value);
01075 if (n->index() == 0) {
01076 result = _mk(0, new_value, NULL, NULL);
01077 }
01078 else {
01079 NodePtr lo, hi, new_lo, new_hi;
01080 lo = _snf_easy_cst(n->lo(), value);
01081 hi = _snf_easy_cst(n->hi(), value);
01082 if (lo == hi) {
01083 V label = lo->value();
01084 if (F == SNF_MEET)
01085 L::meet(label, value, label);
01086 else
01087 L::join(label, value, label);
01088 result = _mk(lo->index(), label, lo->_lo_const_bypass(),
01089 lo->_hi_const_bypass());
01090 }
01091 else {
01092 new_lo = _snf_rpc(lo, value);
01093 new_hi = _snf_rpc(hi, value);
01094 if (new_lo == new_hi)
01095 abort();
01096 result = _mk(n->index(), new_value, new_lo, new_hi);
01097 }
01098 }
01099 }
01100 _memo_nv.set(n, value, result);
01101 return result;
01102 }
01103
01104 static NodePtr _snf_easy_rec(NodePtr n1, NodePtr n2) {
01105 if (not n1 or not n2)
01106 abort();
01107 NodePtr result = _memo_nn.get(n1, n2);
01108 if (result) {
01109 return result;
01110 }
01111 if (n1->index() == 0)
01112 result = _snf_easy_cst(n2, n1->value());
01113 else if (n2->index() == 0)
01114 result = _snf_easy_cst(n1, n2->value());
01115 else if (n1->index() == n2->index()) {
01116 NodePtr lo = _snf_easy_rec(n1->lo(), n2->lo());
01117 NodePtr hi = _snf_easy_rec(n1->hi(), n2->hi());
01118 V cst_value = n1->value();
01119 if (F == SNF_MEET)
01120 L::meet(cst_value, n2->value(), cst_value);
01121 else
01122 L::join(cst_value, n2->value(), cst_value);
01123 NodePtr new_lo = _snf_easy_cst(lo, cst_value);
01124 NodePtr new_hi = _snf_easy_cst(hi, cst_value);
01125 if (new_lo == new_hi) {
01126 result = new_lo;
01127 }
01128 else {
01129 cst_value = new_lo->value();
01130 if (F == SNF_MEET) {
01131 L::join(cst_value, new_hi->value(), cst_value);
01132 }
01133 else {
01134 L::meet(cst_value, new_hi->value(), cst_value);
01135 }
01136 lo = _snf_rpc(new_lo, cst_value);
01137 hi = _snf_rpc(new_hi, cst_value);
01138 if (lo == hi) {
01139 result = lo;
01140 }
01141 else {
01142 result = _mk(n1->index(), cst_value, lo, hi);
01143 }
01144 }
01145 }
01146 else {
01147 if (n1->index() < n2->index())
01148 swap(n1, n2);
01149 NodePtr lo = _snf_easy_rec(n1->lo(), n2);
01150 NodePtr hi = _snf_easy_rec(n1->hi(), n2);
01151 V cst_value = n1->value();
01152 NodePtr new_lo = _snf_easy_cst(lo, cst_value);
01153 NodePtr new_hi = _snf_easy_cst(hi, cst_value);
01154 if (new_lo == new_hi) {
01155 result = new_lo;
01156 }
01157 else {
01158 cst_value = new_lo->value();
01159 if (F == SNF_MEET) {
01160 L::join(cst_value, new_hi->value(), cst_value);
01161 }
01162 else {
01163 L::meet(cst_value, new_hi->value(), cst_value);
01164 }
01165 lo = _snf_rpc(new_lo, cst_value);
01166 hi = _snf_rpc(new_hi, cst_value);
01167 if (lo == hi) {
01168 result = lo;
01169 }
01170 else {
01171 result = _mk(n1->index(), cst_value, lo, hi);
01172 }
01173 }
01174 }
01175 _memo_nn.set(n1, n2, result);
01176 return result;
01177 }
01178
01179 static NodePtr _snf_hard_rec(NodePtr n1, NodePtr n2, const V& d1, const V& d2) {
01180 NodePtr result = _memo_quad.get(n1, n2, d1, d2);
01181 bool swapped = false;
01182 if (result) {
01183 return result;
01184 }
01185 V new_d1 = d1, new_d2 = d2;
01186 if (F == SNF_MEET) {
01187 L::meet(new_d1, n1->value(), new_d1);
01188 L::meet(new_d2, n2->value(), new_d2);
01189 }
01190 else {
01191 L::join(new_d1, n1->value(), new_d1);
01192 L::join(new_d2, n2->value(), new_d2);
01193 }
01194 if (n1->index() == 0 and n2->index() == 0) {
01195 V value = new_d1;
01196 if (F == SNF_MEET)
01197 L::join(value, new_d2, value);
01198 else
01199 L::meet(value, new_d2, value);
01200 result = _mk(0, value, NULL, NULL);
01201 }
01202 else if (n1->index() == n2->index()) {
01203 NodePtr lo = _snf_hard_rec(n1->_lo_const_bypass(),
01204 n2->_lo_const_bypass(), new_d1, new_d2);
01205 NodePtr hi = _snf_hard_rec(n1->_hi_const_bypass(),
01206 n2->_hi_const_bypass(), new_d1, new_d2);
01207 if (lo == hi) {
01208 result = lo;
01209 }
01210 else {
01211 V value = lo->value();
01212 if (F == SNF_MEET) {
01213 L::join(value, hi->value(), value);
01214 }
01215 else {
01216 L::meet(value, hi->value(), value);
01217 }
01218 NodePtr new_lo = _snf_rpc(lo, value);
01219 NodePtr new_hi = _snf_rpc(hi, value);
01220 result = _mk(n1->index(), value, new_lo, new_hi);
01221 }
01222 }
01223 else {
01224 if (n1->index() < n2->index()) {
01225 swap(n1, n2);
01226 swapped = true;
01227 swap(new_d1, new_d2);
01228 }
01229 NodePtr lo = _snf_hard_rec(n1->_lo_const_bypass(), n2, new_d1, new_d2);
01230 NodePtr hi = _snf_hard_rec(n1->_hi_const_bypass(), n2, new_d1, new_d2);
01231 if (lo == hi) {
01232 result = lo;
01233 }
01234 else {
01235 V value = lo->value();
01236 if (F == SNF_MEET) {
01237 L::join(value, hi->value(), value);
01238 }
01239 else {
01240 L::meet(value, hi->value(), value);
01241 }
01242 NodePtr new_lo = _snf_rpc(lo, value);
01243 NodePtr new_hi = _snf_rpc(hi, value);
01244 result = _mk(n1->index(), value, new_lo, new_hi);
01245 }
01246 }
01247 if (swapped)
01248 _memo_quad.set(n2, n1, d1, d2, result);
01249 else
01250 _memo_quad.set(n1, n2, d1, d2, result);
01251 return result;
01252 }
01253
01254 static NodePtr _fetch_orphan() {
01255 Node* result;
01256 typename list<Node*>::iterator it;
01257 for (it = _orphans.begin(); it != _orphans.end();) {
01258 if ((*it)->refcount() == 0)
01259 break;
01260 it = _orphans.erase(it);
01261 }
01262 if (it == _orphans.end()) {
01263 result = NULL;
01264 }
01265 else {
01266 Node* n = *it;
01267 _orphans.erase(it);
01268 _hash_map.erase(n);
01269 result = n;
01270 }
01271 return NodePtr(result);
01272 }
01273
01274 static NodePtr _mkbot() {
01275 V v;
01276 L::bot(v);
01277 return _mk(0, v, NULL, NULL);
01278 }
01279
01280 static NodePtr _mktop() {
01281 V v;
01282 L::top(v);
01283 return _mk(0, v, NULL, NULL);
01284 }
01285
01286 static void _add_orphan(Node* n) {
01287 if (n == NULL or n->refcount() != 0)
01288 throw runtime_error("invalid orphan node");
01289 _orphans.push_back(n);
01290 }
01291
01292 static NodePtr _mk(int index, const V& value, NodePtr lo, NodePtr hi) {
01293
01294 typename HashMap::const_iterator it;
01295
01296 _mk_call_count++;
01297
01298 NodePtr result;
01299 if (lo == hi and lo) {
01300 abort();
01301 }
01302 else {
01303 Node key(index, value, lo, hi);
01304 it = _hash_map.find(&key);
01305 if (it == _hash_map.end()) {
01306 result = _fetch_orphan();
01307 if (not result) {
01308 _node_allocations++;
01309 result.grab(new Node(index, value, lo, hi));
01310 }
01311 else {
01312 if (result->refcount() != 1)
01313 abort();
01314 _orphan_fetches++;
01315 *result = key;
01316 result->_new_refcount();
01317 }
01318 _hash_map[result.get_ptr()] = result.get_ptr();
01319 }
01320 else {
01321 result.grab(it->second);
01322 }
01323 }
01324
01325 return result;
01326 }
01327
01328 void _quantify_rec(NodePtr n, map<NodePtr, V>& memo, V& result, bool exists) const {
01329 typename map<NodePtr, V>::iterator it;
01330 it = memo.find(n);
01331 if (it != memo.end())
01332 result = it->second;
01333 else if (n->index() == 0) {
01334 result = n->value();
01335 memo[n] = result;
01336 }
01337 else {
01338 V tmp;
01339 _quantify_rec(n->lo(), memo, tmp, exists);
01340 _quantify_rec(n->hi(), memo, result, exists);
01341 if (exists) {
01342 L::join(result, tmp, result);
01343 }
01344 else {
01345 L::meet(result, tmp, result);
01346 }
01347 if (F == SNF_MEET) {
01348 L::meet(result, n->value(), result);
01349 }
01350 else {
01351 L::join(result, n->value(), result);
01352 }
01353 memo[n] = result;
01354 }
01355 }
01356
01357 static V _eval_rec(const vector<bool>& valuation, NodePtr node) {
01358 if (node->index() == 0) {
01359 return node->value();
01360 }
01361 if (node->index() > (int) valuation.size()) {
01362 throw logic_error("eval : bad valuation");
01363 }
01364 NodePtr next = valuation[node->index() - 1] ? node->hi() : node->lo();
01365 V result = node->value();
01366 if (F == SNF_JOIN) {
01367 L::join(result, _eval_rec(valuation, next), result);
01368 }
01369 else {
01370 L::meet(result, _eval_rec(valuation, next), result);
01371 }
01372 return result;
01373 }
01374
01375 public:
01376
01380 LVBDD() {
01381 _root = _mkbot();
01382 }
01383
01387 ~LVBDD() {
01388
01389 }
01390
01394 LVBDD(const LVBDD& other) {
01395 _root = other._root;
01396 }
01397
01401 LVBDD& operator=(const LVBDD& other) {
01402 if (this != &other) {
01403 _root = other._root;
01404 }
01405 return *this;
01406 }
01407
01412 bool operator==(const LVBDD& other) const {
01413 return _root == other._root;
01414 }
01415
01419 bool operator!=(const LVBDD& other) const {
01420 return _root != other._root;
01421 }
01422
01426 static LVBDD terminal(const V& value) {
01427 LVBDD res;
01428 res._root = _mk(0, value, NULL, NULL);
01429 return res;
01430 }
01431
01437 static LVBDD literal(int index, bool positive) {
01438 if (index <= 0)
01439 throw invalid_argument("bad index");
01440 LVBDD res;
01441 NodePtr lo = positive ? _mkbot() : _mktop();
01442 NodePtr hi = positive ? _mktop() : _mkbot();
01443 V value;
01444 if (F == SNF_JOIN)
01445 L::bot(value);
01446 else
01447 L::top(value);
01448 res._root = _mk(index, value, lo, hi);
01449 return res;
01450 }
01451
01455 static LVBDD top() {
01456 LVBDD result;
01457 V value;
01458 L::top(value);
01459 result._root = _mk(0, value, NULL, NULL);
01460 return result;
01461 }
01462
01466 static LVBDD bot() {
01467 LVBDD result;
01468 V value;
01469 L::bot(value);
01470 result._root = _mk(0, value, NULL, NULL);
01471 return result;
01472 }
01473
01484 static LVBDD _mk_unsafe(int index, V value, LVBDD lo, LVBDD hi) {
01485 if (index < 1)
01486 throw logic_error("bad index");
01487 if (lo == hi)
01488 throw logic_error("lo and hi are the same");
01489 LVBDD result;
01490 result._root = _mk(index, value, lo._root, hi._root);
01491 return result;
01492 }
01493
01497 static int orphan_count() {
01498 int count = 0;
01499 for (typename list<Node*>::iterator it = _orphans.begin(); it
01500 != _orphans.end(); it++) {
01501 if ((*it)->refcount() == 0)
01502 count++;
01503 }
01504 return count;
01505 }
01506
01510 static void print_hashmap_debug(ostream& out = cout) {
01511 out << endl;
01512 typename HashMap::iterator it;
01513 for (it = _hash_map.begin(); it != _hash_map.end(); it++) {
01514 Node* n = (*it).second;
01515 out << "@" << n << " index=" << n->index();
01516 out << " lo@" << setw(10) << n->lo();
01517 out << " hi@" << setw(10) << n->hi();
01518 out << " rc=" << n->refcount();
01519 out << " value=" << n->value();
01520 out << " hash=" << n->hash();
01521 out << endl;
01522 }
01523 print_hashmap_stats();
01524 out << endl;
01525 }
01526
01530 static void print_hashmap_stats(ostream& out = cout) {
01531 set<size_t, less<size_t> > hashes;
01532 map<int, int, less<int> > hash_count;
01533 for (typename HashMap::iterator it = _hash_map.begin(); it
01534 != _hash_map.end(); it++) {
01535 hashes.insert(it->second->hash());
01536 if (hash_count.find(it->second->hash()) == hash_count.end()) {
01537 hash_count[it->second->hash()] = 1;
01538 }
01539 else {
01540 hash_count[it->second->hash()] += 1;
01541 }
01542 }
01543 int max = -1;
01544 int max_hash = -1;
01545 map<int, int, less<int> >::const_iterator itt;
01546 for (itt = hash_count.begin(); itt != hash_count.end(); itt++) {
01547 if (itt->second > max) {
01548 max = itt->second;
01549 max_hash = itt->first;
01550 }
01551 }
01552 float lf = float(_hash_map.size()) / _hash_map.bucket_count();
01553 out << "HashMap size = " << _hash_map.size() << endl;
01554 out << "HashMap load factor = " << lf << endl;
01555 out << "HashMap bucket count = " << _hash_map.bucket_count() << endl;
01556 out << "# of different hashes = " << hashes.size() << endl;
01557 out << "Most usage of hash key = " << max << " (" << max_hash << ")";
01558 out << endl;
01559 out << "# of calls to MK = " << _mk_call_count << endl;
01560 float pct = (100.0 * _orphan_fetches) / _mk_call_count;
01561 out << "# of orphans reused = " << _orphan_fetches << " (";
01562 out << pct << "%)" << endl;
01563 pct = (100.0 * _node_allocations) / _mk_call_count;
01564 out << "# of node allocations = " << _node_allocations << " (";
01565 out << pct << "%)" << endl;
01566 out << "# of orphan nodes = " << orphan_count() << endl;
01567 }
01568
01572 static void free_orphaned_nodes() {
01573 typename list<NodePtr>::iterator it;
01574 NodePtr n;
01575 for (it = _orphans.begin(); it != _orphans.end(); it++) {
01576 if ((*it)->refcount())
01577 continue;
01578 n = *it;
01579 _hash_map.erase(*n);
01580 delete n;
01581 }
01582 _orphans.clear();
01583 }
01584
01589 static size_t total_node_count() {
01590 return _hash_map.size();
01591 }
01592
01596 static size_t node_count() {
01597 return total_node_count() - orphan_count();
01598 }
01599
01604 static void init() {
01605 Node *dk = new Node();
01606 *dk = Node::deleted_key();
01607 _hash_map.set_deleted_key(dk);
01608 #ifdef USING_DENSE_HASH_MAP
01609 Node *ek = new Node();
01610 *ek = Node::empty_key();
01611 _hash_map.set_empty_key(ek);
01612 #endif
01613 }
01614
01619 LVBDD join(const LVBDD& other) const {
01620 LVBDD result;
01621 if (F == SNF_MEET) {
01622 V value;
01623 L::top(value);
01624 result._root = _snf_hard_rec(_root, other._root, value, value);
01625 _memo_quad.clear();
01626 }
01627 else if (F == SNF_JOIN) {
01628 result._root = _snf_easy_rec(_root, other._root);
01629 _memo_nv.clear();
01630 _memo_nn.clear();
01631 }
01632 else {
01633 result._root = _unf_apply_rec(_root, other._root, false);
01634 _memo_nn.clear();
01635 }
01636 return result;
01637 }
01638
01642 LVBDD operator|(const LVBDD& other) const {
01643 return join(other);
01644 }
01645
01650 LVBDD meet(const LVBDD& other) const {
01651 LVBDD result;
01652 if (F == SNF_JOIN) {
01653 V value;
01654 L::bot(value);
01655 result._root = _snf_hard_rec(_root, other._root, value, value);
01656 _memo_quad.clear();
01657 }
01658 else if (F == SNF_MEET) {
01659 result._root = _snf_easy_rec(_root, other._root);
01660 _memo_nv.clear();
01661 _memo_nn.clear();
01662 }
01663 else {
01664 result._root = _unf_apply_rec(_root, other._root, true);
01665 _memo_nn.clear();
01666 }
01667 return result;
01668 }
01669
01673 LVBDD operator&(const LVBDD& other) const {
01674 return meet(other);
01675 }
01676
01680 int size() const {
01681 set<Node*> my_nodes;
01682 _root->_descendants(my_nodes);
01683 return my_nodes.size();
01684 }
01685
01689 int nonterminal_size() const {
01690 set<Node*> my_nodes;
01691 _root->_descendants(my_nodes);
01692 typename set<Node*>::iterator it;
01693 int count = 0;
01694 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
01695 if ((*it)->index() != 0) {
01696 count++;
01697 }
01698 }
01699 return count;
01700 }
01701
01705 int terminal_size() const {
01706 set<Node*> my_nodes;
01707 _root->_descendants(my_nodes);
01708 typename set<Node*>::iterator it;
01709 int count = 0;
01710 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
01711 if ((*it)->index() == 0) {
01712 count++;
01713 }
01714 }
01715 return count;
01716 }
01717
01722 int values_size() const {
01723 set<Node*> my_nodes;
01724 _root->_descendants(my_nodes);
01725 list<V> l;
01726 typename set<Node*>::iterator it;
01727 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
01728 V val = (*it)->value();
01729 l.push_back(val);
01730 }
01731 return L::list_size(l);
01732 }
01733
01737 void print_graphviz(ostream& out = cout) const {
01738 Node::print_graphviz(out, _root);
01739 }
01740
01744 static void print_graphviz_debug(ostream& out = cout) {
01745 Node::print_graphviz(out, NULL);
01746 }
01747
01751 void exists(V& result) const {
01752 if (F == SNF_MEET) {
01753 result = _root->value();
01754 }
01755 else {
01756 map<NodePtr, V> memo;
01757 _quantify_rec(_root, memo, result, true);
01758 }
01759 }
01760
01764 V exists() const {
01765 V result;
01766 exists(result);
01767 return result;
01768 }
01769
01773 void forall(V& result) const {
01774 if (F == SNF_JOIN) {
01775 result = _root->value();
01776 }
01777 else {
01778 map<NodePtr, V> memo;
01779 _quantify_rec(_root, memo, result, false);
01780 }
01781 }
01782
01786 V forall() const {
01787 V result;
01788 forall(result);
01789 return result;
01790 }
01791
01796 LVBDD lo() const {
01797 if (_root->index() == 0)
01798 throw logic_error("called lo() on terminal LVBDD");
01799 LVBDD result;
01800 result._root = _root->_lo_const_bypass();
01801 return result;
01802 }
01803
01808 LVBDD hi() const {
01809 if (_root->index() == 0)
01810 throw logic_error("called hi() on terminal LVBDD");
01811 LVBDD result;
01812 result._root = _root->_hi_const_bypass();
01813 return result;
01814 }
01815
01820 int index() const {
01821 return _root->index();
01822 }
01823
01827 void root_value(V& result) const {
01828 result = _root->value();
01829 }
01830
01834 V root_value() const {
01835 return _root->value();
01836 }
01837
01844 void evaluate(const vector<bool>& valuation, V& result) const {
01845 result = _eval_rec(valuation, _root);
01846 }
01847
01854 V evaluate(const vector<bool>& valuation) const {
01855 return _eval_rec(valuation, _root);
01856 }
01857
01861 friend ostream& operator<<(ostream& out, const LVBDD& dd) {
01862 out << dd._root.get_ptr();
01863 return out;
01864 }
01865
01866 };
01867
01868 template<class L, int F>
01869 typename LVBDD<L, F>::HashMap LVBDD<L, F>::_hash_map;
01870
01871 template<class L, int F>
01872 list<Node<L, F>*> LVBDD<L, F>::_orphans;
01873
01874 template<class L, int F>
01875 int LVBDD<L, F>::_mk_call_count;
01876
01877 template<class L, int F>
01878 int LVBDD<L, F>::_orphan_fetches;
01879
01880 template<class L, int F>
01881 int LVBDD<L, F>::_node_allocations;
01882
01883 template<class L, int F>
01884 typename LVBDD<L, F>::NodeNodeMemoizer LVBDD<L, F>::_memo_nn;
01885
01886 template<class L, int F>
01887 typename LVBDD<L, F>::NodeValueMemoizer LVBDD<L, F>::_memo_nv;
01888
01889 template<class L, int F>
01890 typename LVBDD<L, F>::QuadrupleMemoizer LVBDD<L, F>::_memo_quad;
01891
01892 }
01893
01894
01895 #endif