Create a Reduced Ordered Binary Decision Diagram from boolean expression in Haskell

323 views Asked by At

Assuming the following definitions:

type Index = Int

data BExp = Prim Bool | IdRef Index | Not BExp | And BExp BExp | Or BExp BExp
           deriving (Eq, Ord, Show)

type NodeId = Int

type BDDNode =  (NodeId, (Index, NodeId, NodeId))

type BDD = (NodeId, [BDDNode])

I want to build a ROBDD from a boolean expression. So far, I've been able to construct a BDD that doesn't satisfy the no-redundancy or sharing properties.

buildBDD :: BExp -> [Index] -> BDD
buildBDD e idxs
 = buildBDD' e 2 idxs

buildBDD' :: BExp -> NodeId -> [Index] -> BDD
buildBDD' (Prim bool) _ []
  | bool       = (1, [])
  | otherwise  = (0, [])
buildBDD' e nodeId (idx : idxs)
 = (nodeId, [newNode] ++ tl ++ tr)
 where
   newNode = (nodeId, (idx, il, ir))
   (il, tl) = buildBDD' (restrict e idx False) (2 * nodeId) idxs
   (ir, tr) = buildBDD' (restrict e idx True) (2 * nodeId + 1) idxs

The naming and style may not be the best, as this is still work in progress.

The nodes are internally represented by a unique id. It starts from 2. The root node of the left subtree will be labelled 2n and the root node of the right subtree will be labelled 2n + 1.

The function will take as input the boolean expression and a list of indices for the variables that appear in the expression.

For example, for the following expression:

And (IdRef 7) (Or (IdRef 2) (Not (IdRef 3)))

The call buildBDD bexp [2,3,7] will return

(2,[(2,(2,4,5)),(4,(3,8,9)),(8,(7,0,1)),(9,(7,0,0)),(5,(3,10,11)),(10,(7,0,1)),
(11,(7,0,1))])

I've made the following changes to account for the no-redundancy property (this has not been tested thoroughly, but appears to be working)

checkEqual (_, l, r)
  | l == r    = True
  | otherwise = False

getElemFromTuple (_, _, e)
  = e

getTuple = snd . head

buildROBDD' e nodeId (idx : idxs)
     = (nodeId, [newNode] ++ left ++ right)
 where
   newNode   = (nodeId, (idx, lId, rId))
   (il, tl)  = buildROBDD' (restrict e idx False) (2 * nodeId) idxs
   (ir, tr)  = buildROBDD' (restrict e idx True) (2 * nodeId + 1) idxs
   lId       = if (not . null) tl && (checkEqual . getTuple) tl then (getElemFromTuple . getTuple) tl else il
   rId       = if (not . null) tr && (checkEqual . getTuple) tr then (getElemFromTuple . getTuple) tr else ir
   left      = if (not . null) tl && (checkEqual . getTuple) tl then [] else tl
   right     = if (not . null) tr && (checkEqual . getTuple) tr then [] else tr

(excuse the clumsy expressions above)

However, I don't know how to approach the sharing property, especially because the shared node might be anywhere in the graph and I am not storing the current tree. The formula for the unique node ids can be changed if needed.

Note: this is meant as an exercise, so the types and style involved might not be optimal. I am also not supposed to change them (I am free to change the function though).

0

There are 0 answers