在SML中递归二进制决策图

时间:2016-02-02 21:59:49

标签: recursion binary-tree sml smlnj

在我的大学课程中,我们正在通过SML / NJ学习函数式编程。

我获得了一项任务,要求我们对二进制决策图执行许多操作。 (连接,分离,不是等)

基于此真值表

table

我定义了以下功能

fun IfThenElse(p,q,r) = 
  if p then q else r;

然后,我们将BDD(ROBDD)数据类型声明为

datatype ROBDD = true
               | false
               | IfThenElse of string * ROBDD * ROBDD;

到目前为止,这一切都相当简单。我在实际操作BDD时迷路了,例如,创建一个代表两个ROBDD的连接的ROBDD。

到目前为止,我的函数声明如下所示

infix bddAnd;
fun op bddAnd(first:ROBDD,second:ROBDD) = 
   ...

它会被两个ROBDD调用,就像这样

val conjunction = IfThenElse("p", true, false) bddAnd IfThenElse("q", true, false);

从这里开始,我不确定从哪里开始。我的教授给了我们这个提示:

  

当然,True bddAnd anyROBDD只是anyROBDD。要获得排序:如果要求您进行计算   (IfThenElse(p, ϕ, ψ) bddAnd IfThenElse(q, χ, θ))   在得到的ROBDD的根处的命题字母将是p或q - 以较小者为准。所以你需要   3个案例:p < qp = qp > q。确定了根后,你可以递归分支

第一部分是有道理的,但我有两个问题。

1。如何确定任何ROBDD的根?

如果它只是truefalse,它没有一个,对吧?所以应该有一个特殊情况,只是给一个布尔值?如果给我们一个更加充实的ROBDD,比如IfThenElse("p", true, false),我如何在ROBDD结构中获得对p的访问权限?请注意,IfThenElse的第一个参数将始终为字母。

2。我如何通过ROBDD进行递归?

我理解SML中递归函数的基础知识,但是我很困惑如何在ROBDD结构中执行它,比如列表。我猜我需要构建一些在ROBDD中对每个参数进行操作的curried函数,但我真的不确定如何构造它。

为冗长的问题道歉,但我真的很难理解如何操作ROBDD结构。任何解释都会非常有用,谢谢!

编辑:

经过一些语法和重命名后,我的bddAnd函数现在看起来像这样

infix bddAnd;
fun op bddAnd (true, second) = second
  | op bddAnd (first, true) = first
  | op bddAnd (false, _) = false
  | op bddAnd (_, false) = false
  | op bddAnd ((left as (IfThenElse (prop1, true1, else1))), (right as (IfThenElse (prop2, true2, else2)))) = 
        if prop1 < prop2 then 
          IfThenElse (prop1, true1 bddAnd right, else1 bddAnd right)
        else if prop1 > prop2 then
          IfThenElse (prop2, true2 bddAnd left, else2 bddAnd left)
        else
          IfThenElse (prop1, true1 bddAnd right, else1 bddAnd left);

1 个答案:

答案 0 :(得分:4)

模式匹配通常是一个很好的起点。

涉及TrueFalse的案件很简单:

fun op bddAnd (True, second) = second
     | bddAnd (first, True) = first
     | bddAnd (False, _) = False
     | bddAnd (_, False) = False

最后一个更有趣:

 | bddAnd (IfThenElse (v1, t1, e1)) (IfThenElse (v2, t2, e2)) = ... what? ...

正如您的教授暗示的那样,您需要考虑v1v2的三个案例:

if v1 < v2 then ...
else if v1 > v2 then ...
else ...

查看第一个v1 < v2,我们应该选择v1作为“根”。

说服自己并不是很难

(IfThenElse p T1 E1) bddAnd (IfThenElse q T2 E2)

相当于

IfThenElse p (T1 bddAnd (IfThenElse q T2 E2)) (E1 bddAnd (IfThenElse q T2 E2))

也就是说,你通过递归到你选择的IfThenElse的两个分支中来创建一个“树”,将另一个树带到一起。
递归将终止,因为bddAnd应用于越来越小的参数,只要输入被排序(我假设我们可以假设),结果就会被排序。

匹配上面的代码,

 | bddAnd (left as (IfThenElse (v1, t1, e1))) (right as (IfThenElse (v2, t2, e2))) = 
        if v1 < v2 then IfThenElse (v1, t1 bddAnd right, e1 bddAnd right)
        else ...

(使用as - 模式可以更容易地将参数称为整体。)

剩下的两个案例作为练习。