Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This happens when constructing oBDDs. The Idea is: put the tree into a canonical form, and construct a hashtable with an entry for every node. Hash function is a function of the node + the hash functions for the left/right child nodes. Complexity is O(N), but only if one can rely on the hashvalues being unique. The final compare (e.g. for Resolving collisions) will still cost o(N*N) for the recursive subtree &lt;--> subtree compare. <a href="http://en.wikipedia.org/wiki/Binary_decision_diagram" rel="nofollow">More on BDDs</a> or <a href="http://www.cs.cmu.edu/~bryant/pubdir/ieeetc86.pdf" rel="nofollow">the original Bryant paper</a></p> <p>The hashfunction I currently use:</p> <pre><code>#define SHUFFLE(x,n) (((x) &lt;&lt; (n))|((x) &gt;&gt;(32-(n)))) /* a node's hashvalue is based on its value * and (recursively) on it's children's hashvalues. */ #define NODE_HASH2(l,r) ((SHUFFLE((l),5)^SHUFFLE((r),9))) #define NODE_HASH3(v,l,r) ((0x54321u*(v) ^ NODE_HASH2((l),(r)))) </code></pre> <p>Typical usage:</p> <pre><code>void node_sethash(NodeNum num) { if (NODE_IS_NULL(num)) return; if (NODE_IS_TERMINAL(num)) switch (nodes[num].var) { case 0: nodes[num].hash.hash= HASH_FALSE; break; case 1: nodes[num].hash.hash= HASH_TRUE; break; case 2: nodes[num].hash.hash= HASH_FALSE^HASH_TRUE; break; } else if (NODE_IS_NAMED(num)) { NodeNum f,t; f = nodes[num].negative; t = nodes[num].positive; nodes[num].hash.hash = NODE_HASH3 (nodes[num].var, nodes[f].hash.hash, nodes[t].hash.hash); } return ; } </code></pre> <p>Searching the hash table:</p> <pre><code>NodeNum *hash_hnd(NodeNum num, int want_exact) { unsigned slot; NodeNum *ptr, this; if (NODE_IS_NULL(num)) return NULL; slot = nodes[num].hash.hash % COUNTOF(hash_nodes); for (ptr = &amp;hash_nodes[slot]; !NODE_IS_NULL(this= *ptr); ptr = &amp;nodes[this].hash.link) { if (this == num) break; if (want_exact) continue; if (nodes[this].hash.hash != nodes[num].hash.hash) continue; if (nodes[this].var != nodes[num].var) continue; if (node_compare( nodes[this].negative , nodes[num].negative)) continue; if (node_compare( nodes[this].positive , nodes[num].positive)) continue; /* duplicate node := same var+same children */ break; } return ptr; } </code></pre> <p>The recursive compare function:</p> <pre><code>int node_compare(NodeNum one, NodeNum two) { int rc; if (one == two) return 0; if (NODE_IS_NULL(one) &amp;&amp; NODE_IS_NULL(two)) return 0; if (NODE_IS_NULL(one) &amp;&amp; !NODE_IS_NULL(two)) return -1; if (!NODE_IS_NULL(one) &amp;&amp; NODE_IS_NULL(two)) return 1; if (NODE_IS_TERMINAL(one) &amp;&amp; !NODE_IS_TERMINAL(two)) return -1; if (!NODE_IS_TERMINAL(one) &amp;&amp; NODE_IS_TERMINAL(two)) return 1; if (VAR_RANK(nodes[one].var) &lt; VAR_RANK(nodes[two].var) ) return -1; if (VAR_RANK(nodes[one].var) &gt; VAR_RANK(nodes[two].var) ) return 1; rc = node_compare(nodes[one].negative,nodes[two].negative); if (rc) return rc; rc = node_compare(nodes[one].positive,nodes[two].positive); if (rc) return rc; return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload