Re: [討論] BddNode and BddNodeInt

看板EE_DSnP作者 (dryman)時間14年前 (2010/01/11 21:07), 編輯推噓1(101)
留言2則, 2人參與, 最新討論串4/6 (看更多)
雖然老師上課有講過及示範,不過當時似懂非懂:p 爬文挖到寶,幫大家手動置底一下 (謎之音:其實是自己需要看,又不想每次都爬到那麼前面XD) 這真是refCount的寶典啊~~ ※ 引述《ric2k1 (Ric)》之銘言: (剛剛好像看到這個問題曇花一現???) Anyway... 避免有些人不敢問這些很重要的基本問題, 我還是稍微說一下好了... 1. A graph is connected by links of nodes. The links of nodes are best implemented as node pointers (why? (*)). 2. So a simple binary decision diagram can be implemented as: class BddNodeInt { BddNodeInt* _left; BddNodeInt* _right; }; 3. However, we also like to keep some information on the node, such as "level", "reference count", "visited flag", etc. So we use 4 Bytes to store them as: class BddNodeInt { BddNodeInt* _left; BddNodeInt* _right; unsigned _level : 16; unsigned _refCount : 15; unsigned _visited : 1; }; 4. Please note that the definition of reference count is --- Let this node be 'n'. Whoever pointing to this node (e.g. "k->_left = _n", k is some BddNodeInt*), or any variable associated to this node (e.g. _bddMap("a", n), will increase the reference count of 'n'. 5. But how do you maintain the correctness of the reference count? Whenver there is a BddNodeInt* assignment, or whenever there is a _bddMap insertion, you need to increase the count. And when to decrease the count? 6. Yes, it is quite complicated to "manually" maintain the reference count. This is the case as in CUDD, which is a very error prone feature. 7. Overload the operator or member functions to take care of the count? Look again on the assignment, "k->_left = n". Since both sides are "pointers", there is no way we can overload the pointer assignment. 8. That's the motivation of using an object variable to "wrap" the pointer class --- class BddNode { BddNodeInt* _node; }; 9. All the operations on BddNodeInt* need to go through BddNode --- * In the BddNode constructor, we increase the reference count of the BddNode::_node. So if a BddNode variable is declared, the reference count of its associated BddNodeInt* will be incremented by 1. * In the BddNode descructor, we decrease the reference count of the BddNode::_node. So if the program goes out of the scope of a certain BddNode variable, the reference count of its BddNodeInt* will be decremented by 1. * In the BddNode assignment '=' operator, for example, f = g, we first decrease the reference count of "f._node", and then increase the reference count of "g._node". Of course, we will asssign "f._node = g._node" 10. That's all the place we need to worry about the reference count. As all the operations are on BddNodes, the reference counts can be maintained automatically. 11. That's why we change the BddNodeInt as --- class BddNodeInt { BddNode _left; BddNode _right; unsigned _level : 16; unsigned _refCount : 15; unsigned _visited : 1; }; In other words, when there is a link between BddNodeInt, it is wrapped by a BddNode and therefore the reference count will be incremented by 1. 12. Then how about the "complement edge"? Try --- class BddNodeInt { BddNode _left; BddNode _right; unsigned _level : 15; unsigned _refCount : 14; unsigned _visited : 1; unsigned _leftPhase : 1; unsigned _rightPhase : 1; }; How to represent ~F, where the complement flag is on the node itself but not on its children? 13. So we will take the advanatage of the fact that the pointer addresses are multiplier of 4, and we can use the lowest two bits to record the edge information. We use the lowest 1 bit to record the INVERSION. 14. To use the lower bits of a pointer variable, we need to conver it to a size_t variable, such as: v = size_t(n); and then the edge information can be added to it by v = v + 1. 15. Combining the above, we redefine the classes BddNode and BddNodeInt as... class BddNode { size_t _nodeV; // to hold BddNodeInt* and 1-bit edge info }; class BddNodeInt { BddNode _left; BddNode _right; unsigned _level : 16; unsigned _refCount : 15; unsigned _visited : 1; }; 16. We also define functions like "BddNode::operator () const { return _nodeV; }", "bool isNegEdge() const { return (_nodeV & BDD_NEG_EDGE); }"... etc. (*) The reason of using "pointers" for the links of nodes are "to share the nodes pointed by different edges. (Remember the reason for using pointers is to "share"). ---- 不小心還是寫了一堆英文, 希望大家看得懂... -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.121.129.139

01/06 15:41,
所以BddNode裡面的_nodeV的type是size_t !? 不是BddNodeInt*?
01/06 15:41

01/06 15:42,
謝謝老師><""寫得好詳細Q____Q
01/06 15:42

01/06 16:19,
謝老師><""寫得好詳細Q____Q(不過曇花一現不是我造成的啊)
01/06 16:19

01/06 16:55,
現在最後幾篇文章已經亂了 @@
01/06 16:55

01/06 17:24,
D 掉 393 試試看
01/06 17:24

01/06 17:25,
好像 OK 了...
01/06 17:25

01/06 17:26,
To nagy: yes, please see the reference code.
01/06 17:26
※ 編輯: ric2k1 來自: 59.121.129.139 (01/06 17:28)

01/08 16:41,
謝謝老師!!
01/08 16:41
-- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.45.170.8

01/11 21:35, , 1F
哇哇! 三年前的文章耶~~~ 應該要有精華區的...
01/11 21:35, 1F

01/11 21:46, , 2F
XD
01/11 21:46, 2F
文章代碼(AID): #1BIoAfFg (EE_DSnP)
文章代碼(AID): #1BIoAfFg (EE_DSnP)