00001
00002
00003
00004
00005
00006
00007
00213 #ifndef __LAVABDD_H__
00214 #define __LAVABDD_H__
00215
00220 #define USING_DENSE_HASH_MAP
00221
00226 #define INITIAL_REFCOUNT 0
00227
00228 #include <list>
00229 #include <stdexcept>
00230 #include <iomanip>
00231 #include <iostream>
00232 #include <fstream>
00233 #include <map>
00234 #include <set>
00235 #include <vector>
00236
00237 #ifdef USING_DENSE_HASH_MAP
00238 #include <google/dense_hash_map>
00239 using google::dense_hash_map;
00240 #else
00241 #include <google/sparse_hash_map>
00242 using google::sparse_hash_map;
00243 #endif
00244
00245 using namespace std;
00246
00250 namespace lava {
00251
00255 const int UNF = 0;
00256
00261 const int SNF_MEET = 1;
00262
00267 const int SNF_JOIN = 2;
00268
00269
00270
00275 inline int hash_int(int key) {
00276 key = ~key + (key << 15);
00277 key = key ^ (key >> 12);
00278 key = key + (key << 2);
00279 key = key ^ (key >> 4);
00280 key = key * 2057;
00281 key = key ^ (key >> 16);
00282 return key;
00283 }
00284
00285
00286
00290 template<typename V>
00291 class Lattice {
00292
00293 public:
00294
00295 typedef V ValueType;
00296
00301 static bool less(const V& x, const V& y) {
00302 throw logic_error("Lattice::less not implemented.");
00303 }
00304
00308 static bool equal(const V& x, const V& y) {
00309 throw logic_error("Lattice::equal not implemented.");
00310 }
00311
00315 static void join(const V& x, const V& y, V& z) {
00316 throw logic_error("Lattice::join not implemented.");
00317 }
00318
00322 static void meet(const V& x, const V& y, V& z) {
00323 throw logic_error("Lattice::meet not implemented.");
00324 }
00325
00330 static void rpc(const V& x, const V& y, V& z) {
00331 throw logic_error("Lattice::rpc not implemented.");
00332 }
00333
00338 static void drpc(const V& x, const V& y, V& z) {
00339 throw logic_error("Lattice::drpc not implemented.");
00340 }
00341
00345 static void top(V& x) {
00346 throw logic_error("Lattice::top not implemented.");
00347 }
00348
00352 static void bot(V& x) {
00353 throw logic_error("Lattice::bot not implemented.");
00354 }
00355
00364 static size_t hash(const V& x) {
00365 throw logic_error("Lattice::hash not implemented.");
00366 }
00367
00371 static void print(const V& x, ostream& out) {
00372 throw logic_error("Lattice::print not implemented.");
00373 }
00374
00380 static int size(const V& x) {
00381 throw logic_error("Lattice::size not implemented.");
00382 }
00383
00390 static int list_size(const list<V>& l) {
00391 throw logic_error("Lattice::list_size not implemented.");
00392 }
00393
00394 };
00395
00396
00397
00398 template<class L, int F> class LVBDD;
00399
00400 namespace {
00401
00402 template<class L, int F> class Node;
00403
00410 template<class L, int F> class NodePtr {
00411
00412 private:
00413
00414 typedef typename L::ValueType V;
00415 typedef lava::Node<L, F> Node;
00416
00417 Node* _node;
00418
00419 public:
00420
00421 NodePtr() {
00422 _node = NULL;
00423 }
00424
00429 NodePtr(Node* node) {
00430 _node = node;
00431 if (_node)
00432 _node->_ref();
00433 }
00434
00438 ~NodePtr() {
00439 if (_node)
00440 _node->_unref();
00441 }
00442
00446 NodePtr(const NodePtr& other) {
00447 _node = other._node;
00448 if (_node)
00449 _node->_ref();
00450 }
00451
00455 NodePtr& operator=(const NodePtr& other) {
00456 if (this != &other) {
00457 if (_node)
00458 _node->_unref();
00459 _node = other._node;
00460 if (_node)
00461 _node->_ref();
00462 }
00463 return *this;
00464 }
00465
00469 Node& operator*() const {
00470 if (_node == NULL)
00471 throw logic_error("NodePtr : NULL pointer access");
00472 return *_node;
00473 }
00474
00478 Node* operator->() const {
00479 if (_node == NULL)
00480 throw logic_error("NodePtr : NULL pointer access");
00481 return _node;
00482 }
00483
00489 Node* get_ptr() const {
00490 return _node;
00491 }
00492
00496 bool operator==(const NodePtr& other) const {
00497 return _node == other._node;
00498 }
00499
00503 bool operator!=(const NodePtr& other) const {
00504 return _node != other._node;
00505 }
00506
00510 bool operator<(const NodePtr& other) const {
00511 return _node < other._node;
00512 }
00513
00517 operator bool() const {
00518 return _node ? true : false;
00519 }
00520
00524 void nullify() {
00525 if (_node)
00526 _node->_unref();
00527 _node = NULL;
00528 }
00529
00533 void grab(Node *node) {
00534 if (_node)
00535 _node->_unref();
00536 _node = node;
00537 if (_node)
00538 _node->_ref();
00539 }
00540
00541 };
00542
00549 template<class L, int F> class Node {
00550
00551 private:
00552
00553 typedef typename L::ValueType V;
00554
00555 friend class NodePtr<L, F> ;
00556 typedef lava::NodePtr<L, F> NodePtr;
00557 typedef lava::LVBDD<L, F> LVBDD;
00558
00559 mutable int _refcount;
00560 int _index;
00561 V _value;
00562 size_t _hash;
00563
00564 NodePtr _lo;
00565 NodePtr _hi;
00566
00567 void _unref() {
00568 if (_refcount <= 0) {
00569 throw runtime_error("unref on orphan Node");
00570 }
00571 _refcount--;
00572 if (_refcount == 0) {
00573 LVBDD::_add_orphan(this);
00574 _lo.nullify();
00575 _hi.nullify();
00576 _index = -1;
00577 }
00578 }
00579
00580 void _ref() {
00581 _refcount++;
00582 }
00583
00584 public:
00585
00586
00587
00588
00589 Node() {
00590 }
00591
00604 Node(int index, const V& val, const NodePtr& lo, const NodePtr& hi) :
00605 _refcount(INITIAL_REFCOUNT), _index(index), _value(val), _lo(lo), _hi(hi) {
00606 _hash = L::hash(_value) ^ hash_int(_index);
00607 if (lo)
00608 _hash ^= hash_int(((size_t) lo.get_ptr()) * 17);
00609 if (hi)
00610 _hash ^= hash_int(((size_t) hi.get_ptr()));
00611 }
00612
00617 int index() const {
00618 return _index;
00619 }
00620
00625 size_t hash() const {
00626 return _hash;
00627 }
00628
00632 int refcount() const {
00633 return _refcount;
00634 }
00635
00639 const V& value() const {
00640 return _value;
00641 }
00642
00646 void value(V& value) const {
00647 value = _value;
00648 }
00649
00653 NodePtr lo() const {
00654 return _lo;
00655 }
00656
00660 NodePtr hi() const {
00661 return _hi;
00662 }
00663
00668 bool operator==(const Node& other) const {
00669 return _hash == other._hash && _index == other._index && _lo == other._lo && _hi
00670 == other._hi && L::equal(_value, other._value);
00671 }
00672
00676 bool operator!=(const Node& other) const {
00677 return not (*this == other);
00678 }
00679
00680
00681
00682
00683 void set_refcount(int refcount) {
00684 _refcount = refcount;
00685 }
00686
00687
00688
00689
00690 static Node deleted_key() {
00691 Node key;
00692 key._refcount = -1;
00693 key._index = -1;
00694 key._hash = -1;
00695 return key;
00696 }
00697
00698
00699
00700
00701 static Node empty_key() {
00702 Node key;
00703 key._refcount = -2;
00704 key._index = -2;
00705 key._hash = -2;
00706 return key;
00707 }
00708
00715 static void print_graphviz(ostream& out = cout, NodePtr root = NULL) {
00716 set<Node*> my_nodes;
00717 if (not root) {
00718 typename LVBDD::HashMap::const_iterator it;
00719 for (it = LVBDD::_hash_map.begin(); it != LVBDD::_hash_map.end(); it++) {
00720 my_nodes.insert(it->second);
00721 }
00722 }
00723 else {
00724 root->_descendants(my_nodes);
00725 }
00726 typename set<Node*>::iterator it;
00727 out << "digraph G {" << endl;
00728 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
00729 if ((*it)->index() == 0) {
00730 out << "\"" << *it << "\" [label=\"";
00731 L::print((*it)->value(), out);
00732 if (*it == root.get_ptr())
00733 out << " (" << (*it)->refcount() - 1 << ")";
00734 else
00735 out << " (" << (*it)->refcount() << ")";
00736 out << "\", shape=box];" << endl;
00737 }
00738 else {
00739 out << "\"" << *it << "\" [label=\"" << (*it)->index() << " : ";
00740 L::print((*it)->value(), out);
00741 if (*it == root.get_ptr())
00742 out << " (" << (*it)->refcount() - 1 << ")";
00743 else
00744 out << " (" << (*it)->refcount() << ")";
00745 out << "\"];" << endl;
00746 }
00747 }
00748 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
00749 if ((*it)->lo()) {
00750 out << "\"" << *it << "\" -> " << "\"" << ((*it)->lo().get_ptr());
00751 out << "\" [style=dotted, arrowhead=none];" << endl;
00752 }
00753 if ((*it)->lo()) {
00754 out << "\"" << *it << "\" -> " << "\"" << ((*it)->hi().get_ptr());
00755 out << "\" [arrowhead=none];" << endl;
00756 }
00757 }
00758 out << "}" << endl;
00759 }
00760
00761 void _descendants(set<Node*>& nodes) {
00762 nodes.clear();
00763 set<Node*> to_visit;
00764 typename set<Node*>::iterator it;
00765 to_visit.insert(this);
00766 Node* n;
00767 while (to_visit.size() > 0) {
00768 it = to_visit.begin();
00769 n = *it;
00770 to_visit.erase(it);
00771 if (nodes.find(n) == nodes.end()) {
00772 nodes.insert(n);
00773 if (n->index() > 0) {
00774 to_visit.insert(n->lo().get_ptr());
00775 to_visit.insert(n->hi().get_ptr());
00776 }
00777 }
00778 }
00779 }
00780
00781 };
00782
00783 }
00784
00785
00786
00792 template<class L, int F>
00793 class LVBDD {
00794
00795 private:
00796
00797 typedef typename L::ValueType V;
00798
00799
00800
00801 struct NodeHashFunction {
00802 size_t operator()(Node<L, F>* const & n) const {
00803 return n->hash();
00804 }
00805 };
00806
00807 struct NodeEqualFunction {
00808 bool operator()(Node<L, F>* const & n1, Node<L, F>* const & n2) const {
00809 return (*n1) == (*n2);
00810 }
00811 };
00812
00813
00814
00815 struct Quadruple {
00816 NodePtr<L, F> n1, n2;
00817 V d1, d2;
00818 };
00819
00820 struct QuadrupleLT {
00821 bool operator()(const Quadruple& a, const Quadruple& b) const {
00822 if (a.n1->hash() != b.n1->hash())
00823 return a.n1->hash() < b.n1->hash();
00824 if (a.n2->hash() != b.n2->hash())
00825 return a.n2->hash() < b.n2->hash();
00826 if (L::hash(a.d1) != L::hash(b.d1))
00827 return L::hash(a.d1) < L::hash(b.d1);
00828 if (L::hash(a.d2) != L::hash(b.d2))
00829 return L::hash(a.d2) < L::hash(b.d2);
00830 return false;
00831 }
00832 };
00833
00834
00835
00836 class QuadrupleMemoizer {
00837
00838 typedef lava::Node<L, F> Node;
00839 typedef lava::NodePtr<L, F> NodePtr;
00840
00841 typedef map<const Quadruple, NodePtr, QuadrupleLT> MAP;
00842 MAP _map;
00843
00844 public:
00845
00846 NodePtr get(const NodePtr& n1, const NodePtr& n2, const V& d1, const V& d2) const {
00847 Quadruple q1, q2;
00848 q1.n1 = n1;
00849 q2.n1 = n2;
00850 q1.n2 = n2;
00851 q2.n2 = n1;
00852 q1.d1 = d1;
00853 q2.d1 = d2;
00854 q1.d2 = d2;
00855 q2.d2 = d1;
00856 typename MAP::const_iterator it;
00857 it = _map.find(q1);
00858 if (it != _map.end())
00859 return it->second;
00860 it = _map.find(q2);
00861 if (it != _map.end())
00862 return it->second;
00863 return NULL;
00864 }
00865
00866 void set(const NodePtr& n1, const NodePtr& n2, const V& d1, const V& d2,
00867 const NodePtr& memo) {
00868 Quadruple q;
00869 q.n1 = n1;
00870 q.n2 = n2;
00871 q.d1 = d1;
00872 q.d2 = d2;
00873 _map[q] = memo;
00874 }
00875
00876 void clear() {
00877 _map.clear();
00878 }
00879
00880 };
00881
00882
00883
00884 class NodeNodeMemoizer {
00885
00886 typedef lava::Node<L, F> Node;
00887 typedef lava::NodePtr<L, F> NodePtr;
00888
00889 map<pair<NodePtr, NodePtr> , NodePtr> _map;
00890
00891 public:
00892
00893 NodePtr get(const NodePtr& n1, const NodePtr& n2) const {
00894 pair<NodePtr, NodePtr> p1(n1, n2);
00895 pair<NodePtr, NodePtr> p2(n2, n1);
00896 typename map<pair<NodePtr, NodePtr> , NodePtr>::const_iterator it;
00897 NodePtr result;
00898 it = _map.find(p1);
00899 if (it != _map.end()) {
00900 result = it->second;
00901 }
00902 else {
00903 it = _map.find(p2);
00904 if (it != _map.end())
00905 result = it->second;
00906 else
00907 result = NULL;
00908 }
00909 return result;
00910 }
00911
00912 void set(const NodePtr& n1, const NodePtr& n2, const NodePtr& memo) {
00913 pair<NodePtr, NodePtr> p(n1, n2);
00914 _map[p] = memo;
00915 }
00916
00917 void clear() {
00918 _map.clear();
00919 }
00920
00921 };
00922
00923
00924
00925 struct NodeValueLT {
00926 typedef lava::Node<L, F> Node;
00927 typedef lava::NodePtr<L, F> NodePtr;
00928
00929 bool operator()(const pair<NodePtr, V>& a, const pair<NodePtr, V>& b) const {
00930 if (a.first == b.first)
00931 return L::hash(a.second) < L::hash(b.second);
00932 else
00933 return a.first.get_ptr() < b.first.get_ptr();
00934 }
00935 };
00936
00937
00938
00939 class NodeValueMemoizer {
00940
00941 typedef lava::Node<L, F> Node;
00942 typedef lava::NodePtr<L, F> NodePtr;
00943 map<pair<NodePtr, V> , NodePtr, NodeValueLT> _map;
00944
00945 public:
00946
00947 NodePtr get(const NodePtr& n, const V& value) const {
00948 pair<NodePtr, V> p(n, value);
00949 typename map<pair<NodePtr, V> , NodePtr, NodeValueLT>::const_iterator it;
00950 it = _map.find(p);
00951 if (it != _map.end())
00952 return it->second;
00953 else
00954 return NULL;
00955 }
00956
00957 void set(const NodePtr& n, const V& value, const NodePtr& memo) {
00958 pair<NodePtr, V> p(n, value);
00959 _map[p] = memo;
00960 }
00961
00962 void clear() {
00963 _map.clear();
00964 }
00965
00966 };
00967
00968 friend class Node<L, F> ;
00969
00970 typedef lava::Node<L, F> Node;
00971 typedef NodeHashFunction HashNode;
00972 typedef NodeEqualFunction EqualNode;
00973 typedef lava::NodePtr<L, F> NodePtr;
00974
00975 #ifdef USING_DENSE_HASH_MAP
00976 typedef dense_hash_map<Node*, Node*, HashNode, EqualNode> HashMap;
00977 #else
00978 typedef sparse_hash_map<Node*, Node*, HashNode, EqualNode> HashMap;
00979 #endif
00980
00981 NodePtr _root;
00982
00983 static HashMap _hash_map;
00984 static list<Node*> _orphans;
00985
00986 static int _mk_call_count;
00987 static int _orphan_fetches;
00988 static int _node_allocations;
00989
00990 static NodeNodeMemoizer _memo_nn;
00991 static NodeValueMemoizer _memo_nv;
00992 static QuadrupleMemoizer _memo_quad;
00993
00994 static NodePtr _unf_apply_rec(const NodePtr& n1, const NodePtr& n2, bool meet) {
00995 if (not n1 or not n2)
00996 abort();
00997 NodePtr result = _memo_nn.get(n1, n2);
00998 V value;
00999 L::top(value);
01000 if (not result) {
01001 if (n1->index() == 0 and n2->index() == 0) {
01002 V value = n1->value();
01003 if (meet)
01004 L::meet(value, n2->value(), value);
01005 else
01006 L::join(value, n2->value(), value);
01007 result = _mk(0, value, NULL, NULL);
01008 }
01009 else if (n1->index() == n2->index()) {
01010 NodePtr lo = _unf_apply_rec(n1->lo(), n2->lo(), meet);
01011 NodePtr hi = _unf_apply_rec(n1->hi(), n2->hi(), meet);
01012 if (lo == hi) {
01013 result = lo;
01014 }
01015 else {
01016 result = _mk(n1->index(), value, lo, hi);
01017 }
01018 }
01019 else {
01020 const NodePtr *new_n1 = &n1, *new_n2 = &n2;
01021 if (n1->index() < n2->index()) {
01022 new_n1 = &n2;
01023 new_n2 = &n1;
01024 }
01025 NodePtr lo = _unf_apply_rec((*new_n1)->lo(), *new_n2, meet);
01026 NodePtr hi = _unf_apply_rec((*new_n1)->hi(), *new_n2, meet);
01027 if (lo == hi) {
01028 result = lo;
01029 }
01030 else {
01031 result = _mk((*new_n1)->index(), value, lo, hi);
01032 }
01033 }
01034 _memo_nn.set(n1, n2, result);
01035 }
01036 return result;
01037 }
01038
01039 static NodePtr _snf_rpc(const NodePtr& n, const V& d) {
01040 V value = n->value();
01041 if (F == SNF_MEET) {
01042 L::rpc(d, value, value);
01043 }
01044 else {
01045 L::drpc(d, value, value);
01046 }
01047 if (n->index() == 0)
01048 return _mk(0, value, NULL, NULL);
01049 V x = n->lo()->value();
01050 if (F == SNF_MEET) {
01051 L::join(x, n->hi()->value(), x);
01052 L::meet(value, x, value);
01053 }
01054 else {
01055 L::meet(x, n->hi()->value(), x);
01056 L::join(value, x, value);
01057 }
01058 return _mk(n->index(), value, n->lo(), n->hi());
01059 }
01060
01061 static NodePtr _snf_easy_cst(const NodePtr& n, const V& value) {
01062 NodePtr result = _memo_nv.get(n, value);
01063 if (result) {
01064 return result;
01065 }
01066 if ((F == SNF_MEET and L::less(n->value(), value)) or (F == SNF_JOIN and L::less(value,
01067 n->value()))) {
01068 result = n;
01069 }
01070 else {
01071 V new_value = value;
01072 if (F == SNF_MEET)
01073 L::meet(new_value, n->value(), new_value);
01074 else
01075 L::join(new_value, n->value(), new_value);
01076 if (n->index() == 0) {
01077 result = _mk(0, new_value, NULL, NULL);
01078 }
01079 else {
01080 NodePtr lo, hi, new_lo, new_hi;
01081 lo = _snf_easy_cst(n->lo(), value);
01082 hi = _snf_easy_cst(n->hi(), value);
01083 if (lo == hi) {
01084 V label = lo->value();
01085 if (F == SNF_MEET)
01086 L::meet(label, n->value(), label);
01087 else
01088 L::join(label, n->value(), label);
01089 result = _mk(lo->index(), label, lo->lo(), lo->hi());
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(const NodePtr& n1, const 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 const NodePtr *new_n1 = &n1, *new_n2 = &n2;
01148 if (n1->index() < n2->index()) {
01149 new_n1 = &n2;
01150 new_n2 = &n1;
01151 }
01152 NodePtr lo = _snf_easy_rec((*new_n1)->lo(), *new_n2);
01153 NodePtr hi = _snf_easy_rec((*new_n1)->hi(), *new_n2);
01154 V cst_value = (*new_n1)->value();
01155 NodePtr new_lo = _snf_easy_cst(lo, cst_value);
01156 NodePtr new_hi = _snf_easy_cst(hi, cst_value);
01157 if (new_lo == new_hi) {
01158 result = new_lo;
01159 }
01160 else {
01161 cst_value = new_lo->value();
01162 if (F == SNF_MEET) {
01163 L::join(cst_value, new_hi->value(), cst_value);
01164 }
01165 else {
01166 L::meet(cst_value, new_hi->value(), cst_value);
01167 }
01168 lo = _snf_rpc(new_lo, cst_value);
01169 hi = _snf_rpc(new_hi, cst_value);
01170 if (lo == hi) {
01171 result = lo;
01172 }
01173 else {
01174 result = _mk((*new_n1)->index(), cst_value, lo, hi);
01175 }
01176 }
01177 }
01178 _memo_nn.set(n1, n2, result);
01179 return result;
01180 }
01181
01182 static NodePtr _snf_hard_rec(const NodePtr& n1, const NodePtr& n2, const V& d1, const V& d2) {
01183 NodePtr result = _memo_quad.get(n1, n2, d1, d2);
01184 if (result) {
01185 return result;
01186 }
01187 V new_d1 = d1, new_d2 = d2;
01188 if (F == SNF_MEET) {
01189 L::meet(new_d1, n1->value(), new_d1);
01190 L::meet(new_d2, n2->value(), new_d2);
01191 }
01192 else {
01193 L::join(new_d1, n1->value(), new_d1);
01194 L::join(new_d2, n2->value(), new_d2);
01195 }
01196 if (n1->index() == 0 and n2->index() == 0) {
01197 V value = new_d1;
01198 if (F == SNF_MEET)
01199 L::join(value, new_d2, value);
01200 else
01201 L::meet(value, new_d2, value);
01202 result = _mk(0, value, NULL, NULL);
01203 _memo_quad.set(n1, n2, d1, d2, result);
01204 return result;
01205 }
01206 else if (n1->index() == n2->index()) {
01207 NodePtr lo = _snf_hard_rec(n1->lo(), n2->lo(), new_d1, new_d2);
01208 NodePtr hi = _snf_hard_rec(n1->hi(), n2->hi(), new_d1, new_d2);
01209 if (lo == hi) {
01210 result = lo;
01211 }
01212 else {
01213 V value = lo->value();
01214 if (F == SNF_MEET) {
01215 L::join(value, hi->value(), value);
01216 }
01217 else {
01218 L::meet(value, hi->value(), value);
01219 }
01220 NodePtr new_lo = _snf_rpc(lo, value);
01221 NodePtr new_hi = _snf_rpc(hi, value);
01222 result = _mk(n1->index(), value, new_lo, new_hi);
01223 }
01224 _memo_quad.set(n1, n2, d1, d2, result);
01225 return result;
01226 }
01227 else {
01228 const NodePtr *new_n1 = &n1, *new_n2 = &n2;
01229 bool swapped = false;
01230 if (n1->index() < n2->index()) {
01231 new_n1 = &n2;
01232 new_n2 = &n1;
01233 swapped = true;
01234 swap(new_d1, new_d2);
01235 }
01236 NodePtr lo = _snf_hard_rec((*new_n1)->lo(), *new_n2, new_d1, new_d2);
01237 NodePtr hi = _snf_hard_rec((*new_n1)->hi(), *new_n2, new_d1, new_d2);
01238 if (lo == hi) {
01239 result = lo;
01240 }
01241 else {
01242 V value = lo->value();
01243 if (F == SNF_MEET) {
01244 L::join(value, hi->value(), value);
01245 }
01246 else {
01247 L::meet(value, hi->value(), value);
01248 }
01249 NodePtr new_lo = _snf_rpc(lo, value);
01250 NodePtr new_hi = _snf_rpc(hi, value);
01251 result = _mk((*new_n1)->index(), value, new_lo, new_hi);
01252 }
01253 if (swapped)
01254 _memo_quad.set(n2, n1, d1, d2, result);
01255 else
01256 _memo_quad.set(n1, n2, d1, d2, result);
01257 return result;
01258 }
01259 }
01260
01261 static NodePtr _fetch_orphan() {
01262 Node* result;
01263 typename list<Node*>::iterator it;
01264 for (it = _orphans.begin(); it != _orphans.end();) {
01265 if ((*it)->refcount() == 0)
01266 break;
01267 it = _orphans.erase(it);
01268 }
01269 if (it == _orphans.end()) {
01270 result = NULL;
01271 }
01272 else {
01273 Node* n = *it;
01274 _orphans.erase(it);
01275 _hash_map.erase(n);
01276 result = n;
01277 }
01278 return NodePtr(result);
01279 }
01280
01281 static NodePtr _mkbot() {
01282 V v;
01283 L::bot(v);
01284 return _mk(0, v, NULL, NULL);
01285 }
01286
01287 static NodePtr _mktop() {
01288 V v;
01289 L::top(v);
01290 return _mk(0, v, NULL, NULL);
01291 }
01292
01293 static void _add_orphan(Node* n) {
01294 if (n == NULL or n->refcount() != 0)
01295 throw runtime_error("invalid orphan node");
01296 _hash_map.erase(n);
01297 _orphans.push_back(n);
01298 }
01299
01300 static NodePtr _mk(int index, const V& value, const NodePtr& lo, const NodePtr& hi) {
01301
01302 typename HashMap::const_iterator it;
01303
01304 _mk_call_count++;
01305
01306 NodePtr result;
01307 Node key(index, value, lo, hi);
01308 it = _hash_map.find(&key);
01309 if (it == _hash_map.end()) {
01310 result = _fetch_orphan();
01311 if (not result) {
01312 _node_allocations++;
01313 result.grab(new Node(index, value, lo, hi));
01314 }
01315 else {
01316 if (result->refcount() != 1)
01317 abort();
01318 _orphan_fetches++;
01319 *result = key;
01320 result->set_refcount(1);
01321 }
01322 _hash_map[result.get_ptr()] = result.get_ptr();
01323 }
01324 else {
01325 result.grab(it->second);
01326 }
01327
01328 return result;
01329 }
01330
01331 void _quantify_rec(const NodePtr& n, map<NodePtr, V>& memo, V& result, bool exists) const {
01332 typename map<NodePtr, V>::iterator it;
01333 it = memo.find(n);
01334 if (it != memo.end())
01335 result = it->second;
01336 else if (n->index() == 0) {
01337 result = n->value();
01338 memo[n] = result;
01339 }
01340 else {
01341 V tmp;
01342 _quantify_rec(n->lo(), memo, tmp, exists);
01343 _quantify_rec(n->hi(), memo, result, exists);
01344 if (exists) {
01345 L::join(result, tmp, result);
01346 }
01347 else {
01348 L::meet(result, tmp, result);
01349 }
01350 if (F == SNF_MEET) {
01351 L::meet(result, n->value(), result);
01352 }
01353 else {
01354 L::join(result, n->value(), result);
01355 }
01356 memo[n] = result;
01357 }
01358 }
01359
01360 static void _eval_rec(const vector<bool>& valuation, const NodePtr& node, V& result) {
01361 if (node->index() == 0) {
01362 node->value(result);
01363 return;
01364 }
01365 if (node->index() > (int) valuation.size()) {
01366 throw logic_error("eval : bad valuation");
01367 }
01368 NodePtr next = valuation[node->index() - 1] ? node->hi() : node->lo();
01369 if (F == SNF_JOIN) {
01370 V tmp;
01371 _eval_rec(valuation, next, tmp);
01372 L::join(tmp, node->value(), result);
01373 }
01374 else {
01375 V tmp;
01376 _eval_rec(valuation, next, tmp);
01377 L::meet(tmp, node->value(), result);
01378 }
01379 }
01380
01381 public:
01382
01386 LVBDD() {
01387 _root = _mkbot();
01388 }
01389
01393 ~LVBDD() {
01394
01395 }
01396
01400 LVBDD(const LVBDD& other) {
01401 _root = other._root;
01402 }
01403
01407 LVBDD& operator=(const LVBDD& other) {
01408 if (this != &other) {
01409 _root = other._root;
01410 }
01411 return *this;
01412 }
01413
01418 bool operator==(const LVBDD& other) const {
01419 return _root == other._root;
01420 }
01421
01425 bool operator!=(const LVBDD& other) const {
01426 return _root != other._root;
01427 }
01428
01432 static LVBDD terminal(const V& value) {
01433 LVBDD res;
01434 res._root = _mk(0, value, NULL, NULL);
01435 return res;
01436 }
01437
01443 static LVBDD literal(int index, bool positive) {
01444 if (index <= 0)
01445 throw invalid_argument("LVBDD::literal : bad index");
01446 LVBDD res;
01447 NodePtr lo = positive ? _mkbot() : _mktop();
01448 NodePtr hi = positive ? _mktop() : _mkbot();
01449 V value;
01450 if (F == SNF_JOIN)
01451 L::bot(value);
01452 else
01453 L::top(value);
01454 res._root = _mk(index, value, lo, hi);
01455 return res;
01456 }
01457
01461 static LVBDD top() {
01462 LVBDD result;
01463 V value;
01464 L::top(value);
01465 result._root = _mk(0, value, NULL, NULL);
01466 return result;
01467 }
01468
01472 static LVBDD bot() {
01473 LVBDD result;
01474 V value;
01475 L::bot(value);
01476 result._root = _mk(0, value, NULL, NULL);
01477 return result;
01478 }
01479
01490 static LVBDD _mk_unsafe(int index, V value, LVBDD lo, LVBDD hi) {
01491 if (index < 1)
01492 throw logic_error("LVBDD::_mk_unsafe : bad index");
01493 if (lo == hi)
01494 throw logic_error("lo and hi are the same");
01495 LVBDD result;
01496 result._root = _mk(index, value, lo._root, hi._root);
01497 return result;
01498 }
01499
01503 static int orphan_count() {
01504 int count = 0;
01505 for (typename list<Node*>::iterator it = _orphans.begin(); it != _orphans.end(); it++) {
01506 if ((*it)->refcount() == 0)
01507 count++;
01508 }
01509 return count;
01510 }
01511
01515 static void print_hashmap_debug(ostream& out = cout) {
01516 out << endl;
01517 typename HashMap::iterator it;
01518 for (it = _hash_map.begin(); it != _hash_map.end(); it++) {
01519 Node* n = (*it).second;
01520 out << "@" << n << " index=" << n->index();
01521 out << " lo@" << setw(10) << n->lo();
01522 out << " hi@" << setw(10) << n->hi();
01523 out << " rc=" << n->refcount();
01524 out << " value=" << n->value();
01525 out << " hash=" << n->hash();
01526 out << endl;
01527 }
01528 print_hashmap_stats();
01529 out << endl;
01530 }
01531
01535 static void print_hashmap_stats(ostream& out = cout) {
01536 set<size_t, less<size_t> > hashes;
01537 map<int, int, less<int> > hash_count;
01538 for (typename HashMap::iterator it = _hash_map.begin(); it != _hash_map.end(); it++) {
01539 hashes.insert(it->second->hash());
01540 if (hash_count.find(it->second->hash()) == hash_count.end()) {
01541 hash_count[it->second->hash()] = 1;
01542 }
01543 else {
01544 hash_count[it->second->hash()] += 1;
01545 }
01546 }
01547 int max = -1;
01548 int max_hash = -1;
01549 map<int, int, less<int> >::const_iterator itt;
01550 for (itt = hash_count.begin(); itt != hash_count.end(); itt++) {
01551 if (itt->second > max) {
01552 max = itt->second;
01553 max_hash = itt->first;
01554 }
01555 }
01556 float lf = float(_hash_map.size()) / _hash_map.bucket_count();
01557 out << "HashMap size = " << _hash_map.size() << endl;
01558 out << "HashMap load factor = " << lf << endl;
01559 out << "HashMap bucket count = " << _hash_map.bucket_count() << endl;
01560 out << "# of different hashes = " << hashes.size() << endl;
01561 out << "Most usage of hash key = " << max << " (" << max_hash << ")";
01562 out << endl;
01563 out << "# of calls to MK = " << _mk_call_count << endl;
01564 float pct = 100.0 - ((100.0 * (_orphan_fetches + _node_allocations)) / _mk_call_count);
01565 out << "# of MK cache hits = " << _mk_call_count - _orphan_fetches - _node_allocations;
01566 out << " (" << pct << "%)" << endl;
01567 pct = (100.0 * _orphan_fetches) / _mk_call_count;
01568 out << "# of orphans reused = " << _orphan_fetches << " (";
01569 out << pct << "%)" << endl;
01570 pct = (100.0 * _node_allocations) / _mk_call_count;
01571 out << "# of node allocations = " << _node_allocations << " (";
01572 out << pct << "%)" << endl;
01573 out << "# of orphan nodes = " << orphan_count() << endl;
01574 }
01575
01579 static void free_orphaned_nodes() {
01580 typename list<Node*>::iterator it;
01581 Node* n;
01582 for (it = _orphans.begin(); it != _orphans.end(); it++) {
01583 if ((*it)->refcount())
01584 continue;
01585 n = *it;
01586 delete n;
01587 }
01588 _orphans.clear();
01589 }
01590
01594 static void clear_memoization_tables() {
01595 _memo_quad.clear();
01596 _memo_nn.clear();
01597 _memo_nv.clear();
01598 }
01599
01603 static int memoization_tables_size() {
01604 return _memo_quad.size() + _memo_nn.size() + _memo_nv.size();
01605 }
01606
01611 static size_t total_node_count() {
01612 return _hash_map.size();
01613 }
01614
01618 static size_t node_count() {
01619 return total_node_count() - orphan_count();
01620 }
01621
01626 static void init() {
01627 Node *dk = new Node();
01628 *dk = Node::deleted_key();
01629 _hash_map.set_deleted_key(dk);
01630 #ifdef USING_DENSE_HASH_MAP
01631 Node *ek = new Node();
01632 *ek = Node::empty_key();
01633 _hash_map.set_empty_key(ek);
01634 #endif
01635 }
01636
01641 LVBDD join(const LVBDD& other) const {
01642 LVBDD result;
01643 if (F == SNF_MEET) {
01644 V value;
01645 L::top(value);
01646 result._root = _snf_hard_rec(_root, other._root, value, value);
01647 }
01648 else if (F == SNF_JOIN) {
01649 result._root = _snf_easy_rec(_root, other._root);
01650 }
01651 else {
01652 result._root = _unf_apply_rec(_root, other._root, false);
01653 }
01654 return result;
01655 }
01656
01660 LVBDD operator|(const LVBDD& other) const {
01661 return join(other);
01662 }
01663
01668 LVBDD meet(const LVBDD& other) const {
01669 LVBDD result;
01670 if (F == SNF_JOIN) {
01671 V value;
01672 L::bot(value);
01673 result._root = _snf_hard_rec(_root, other._root, value, value);
01674 }
01675 else if (F == SNF_MEET) {
01676 result._root = _snf_easy_rec(_root, other._root);
01677 }
01678 else {
01679 result._root = _unf_apply_rec(_root, other._root, true);
01680 }
01681 return result;
01682 }
01683
01687 LVBDD operator&(const LVBDD& other) const {
01688 return meet(other);
01689 }
01690
01694 int size() const {
01695 set<Node*> my_nodes;
01696 _root->_descendants(my_nodes);
01697 return my_nodes.size();
01698 }
01699
01703 int nonterminal_size() const {
01704 set<Node*> my_nodes;
01705 _root->_descendants(my_nodes);
01706 typename set<Node*>::iterator it;
01707 int count = 0;
01708 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
01709 if ((*it)->index() != 0) {
01710 count++;
01711 }
01712 }
01713 return count;
01714 }
01715
01719 int terminal_size() const {
01720 set<Node*> my_nodes;
01721 _root->_descendants(my_nodes);
01722 typename set<Node*>::iterator it;
01723 int count = 0;
01724 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
01725 if ((*it)->index() == 0) {
01726 count++;
01727 }
01728 }
01729 return count;
01730 }
01731
01736 int values_size() const {
01737 set<Node*> my_nodes;
01738 _root->_descendants(my_nodes);
01739 list<V> l;
01740 typename set<Node*>::iterator it;
01741 for (it = my_nodes.begin(); it != my_nodes.end(); it++) {
01742 V val = (*it)->value();
01743 l.push_back(val);
01744 }
01745 return L::list_size(l);
01746 }
01747
01751 void print_graphviz(ostream& out = cout) const {
01752 Node::print_graphviz(out, _root);
01753 }
01754
01758 static void print_graphviz_debug(ostream& out = cout) {
01759 Node::print_graphviz(out, NULL);
01760 }
01761
01765 void exists(V& result) const {
01766 if (F == SNF_MEET) {
01767 result = _root->value();
01768 }
01769 else {
01770 map<NodePtr, V> memo;
01771 _quantify_rec(_root, memo, result, true);
01772 }
01773 }
01774
01778 V exists() const {
01779 V result;
01780 exists(result);
01781 return result;
01782 }
01783
01787 void forall(V& result) const {
01788 if (F == SNF_JOIN) {
01789 result = _root->value();
01790 }
01791 else {
01792 map<NodePtr, V> memo;
01793 _quantify_rec(_root, memo, result, false);
01794 }
01795 }
01796
01800 V forall() const {
01801 V result;
01802 forall(result);
01803 return result;
01804 }
01805
01810 LVBDD lo() const {
01811 if (_root->index() == 0)
01812 throw logic_error("called lo() on terminal LVBDD");
01813 LVBDD result;
01814 result._root = _root->lo();
01815 return result;
01816 }
01817
01822 LVBDD hi() const {
01823 if (_root->index() == 0)
01824 throw logic_error("called hi() on terminal LVBDD");
01825 LVBDD result;
01826 result._root = _root->hi();
01827 return result;
01828 }
01829
01834 int index() const {
01835 return _root->index();
01836 }
01837
01841 void root_value(V& result) const {
01842 _root->value(result);
01843 }
01844
01848 V root_value() const {
01849 return _root->value();
01850 }
01851
01858 void evaluate(const vector<bool>& valuation, V& result) const {
01859 result = _eval_rec(valuation, _root, result);
01860 }
01861
01868 V evaluate(const vector<bool>& valuation) const {
01869 V result;
01870 _eval_rec(valuation, _root, result);
01871 return result;
01872 }
01873
01877 friend ostream& operator<<(ostream& out, const LVBDD& dd) {
01878 out << dd._root.get_ptr();
01879 return out;
01880 }
01881
01882 };
01883
01884 template<class L, int F>
01885 typename LVBDD<L, F>::HashMap LVBDD<L, F>::_hash_map;
01886
01887 template<class L, int F>
01888 list<Node<L, F>*> LVBDD<L, F>::_orphans;
01889
01890 template<class L, int F>
01891 int LVBDD<L, F>::_mk_call_count;
01892
01893 template<class L, int F>
01894 int LVBDD<L, F>::_orphan_fetches;
01895
01896 template<class L, int F>
01897 int LVBDD<L, F>::_node_allocations;
01898
01899 template<class L, int F>
01900 typename LVBDD<L, F>::NodeNodeMemoizer LVBDD<L, F>::_memo_nn;
01901
01902 template<class L, int F>
01903 typename LVBDD<L, F>::NodeValueMemoizer LVBDD<L, F>::_memo_nv;
01904
01905 template<class L, int F>
01906 typename LVBDD<L, F>::QuadrupleMemoizer LVBDD<L, F>::_memo_quad;
01907
01908 }
01909
01910
01911 #endif