从Haskell中的布尔表达式创建降阶二元决策图

从Haskell中的布尔表达式创建降阶二元决策图,haskell,recursion,directed-acyclic-graphs,binary-decision-diagram,Haskell,Recursion,Directed Acyclic Graphs,Binary Decision Diagram,假设以下定义: 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]) 我想从布尔表达

假设以下定义:

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])
我想从布尔表达式构建一个ROBDD。到目前为止,我已经能够构造一个不满足无冗余或共享属性的BDD

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
命名和样式可能不是最好的,因为这仍在进行中

节点在内部由唯一id表示。它从2开始。左子树的根节点将标记为2n,右子树的根节点将标记为2n+1

该函数将布尔表达式和表达式中出现的变量的索引列表作为输入

例如,对于以下表达式:

And (IdRef 7) (Or (IdRef 2) (Not (IdRef 3)))
调用
buildBDD bexp[2,3,7]
将返回

(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))])
我已经对no-redundancy属性做了以下更改(这还没有经过彻底的测试,但似乎可以正常工作)

(请原谅上面的笨拙表情)

但是,我不知道如何处理共享属性,特别是因为共享节点可能位于图中的任何位置,并且我没有存储当前树。如果需要,可以更改唯一节点ID的公式


注意:这是一个练习,因此所涉及的类型和样式可能不是最佳的。我也不应该更改它们(尽管我可以自由更改功能)。

共享属性是什么,它与无冗余有什么区别?更多信息,包括图表,请访问
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