Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何将布尔函数转换为二进制决策图_Algorithm_Data Structures_Logic_Graph Theory_Binary Decision Diagram - Fatal编程技术网

Algorithm 如何将布尔函数转换为二进制决策图

Algorithm 如何将布尔函数转换为二进制决策图,algorithm,data-structures,logic,graph-theory,binary-decision-diagram,Algorithm,Data Structures,Logic,Graph Theory,Binary Decision Diagram,假设我有以下布尔函数: or(x, y) := x || y and(x, y) := x && y not(x) := !x foo(x, y, z) := and(x, or(y, z)) bar(x, y, z, a) := or(foo(x, y, z), not(a)) baz(x, y) := and(x, not(y)) 现在我想从它们中构造一个。我已经阅读了几篇论文,但没有找到如何从这些嵌套的逻辑公式中构造它们 据说布尔函数是有根的、有向的、非循环的图。它有几个

假设我有以下布尔函数:

or(x, y) := x || y
and(x, y) := x && y
not(x) := !x
foo(x, y, z) := and(x, or(y, z))
bar(x, y, z, a) := or(foo(x, y, z), not(a))
baz(x, y) := and(x, not(y))
现在我想从它们中构造一个。我已经阅读了几篇论文,但没有找到如何从这些嵌套的逻辑公式中构造它们

据说布尔函数是有根的、有向的、非循环的图。它有几个非终端和终端节点。然后它说每个非终结节点都由一个布尔变量(不是函数)标记,该变量有两个子节点。从上面的函数定义中,我不知道布尔变量是什么。从节点到子节点
a
b
的边分别表示将节点分配到0或1。如果同构子图被合并,并且其两个子图同构的节点被移除,则称为reduced。这是一个降阶二元决策图(ROBDD)

从这一点以及我所遇到的所有资源来看,我一直无法理解如何将这些函数转换为BDD/ROBDS:

foo(1, 0, 1)
bar(1, 0, 1, 0)
baz(1, 0)
或者可能是这些需要转换:

foo(x, y, z)
bar(x, y, z, a)
baz(x, y)
寻求帮助,解释我需要做什么,以便将其转换为有根的、有向的、非循环的图。了解数据结构的外观也会有所帮助。似乎就是这样:

var nonterminal = {
  a: child,
  b: child,
  v: some variable, not sure what
}

但接下来的问题是如何从这些函数
foo
bar
baz

构建图形。您可以通过评估所有变量赋值来实现,例如

foo(0,0,0) = 0
foo(0,0,1) = 0
foo(0,1,0) = 0
...
然后创建图形,从根开始。每个函数参数都会获得一条带有赋值的边,叶节点会带有结果值:

x0 -0-> y0 -0-> z0 -0-> 0
x0 -0-> y1 -0-> z1 -1-> 0
x0 -0-> y2 -1-> z2 -0-> 0
...
合并节点(y0=y1=y2,z0=z1):

减少节点(有一些规则允许加入节点或跳过节点)。例如,由于根的
0
总是指向叶的
0
,因此您可以跳过后面的决定:

x0 -0-> 0
...

请注意,必须使用变量名标记节点,以便在以下图形边上分配变量名。该算法并不十分复杂(当然存在一个更有效的算法),但我希望它能将策略可视化。

基本逻辑运算和、或、异或等都可以在BDD表示的函数之间进行计算,以生成BDD表示的新函数。除了处理终端的方式外,这些算法都很相似,大致如下:

  • 如果结果是端子,则返回该端子
  • 如果缓存了
    (op,A,B)
    ,则返回缓存结果
  • 区分3种情况(实际上你可以概括这一点)

  • A.var==B.var
    ,创建一个节点
    (A.var,OP(A.lo,B.lo),OP(A.hi,B.hi))
    ,其中
    OP
    表示递归调用此过程
  • A.var
    ,创建一个节点
    (A.var,OP(A.lo,B),OP(A.hi,B))
  • A.var>B.var
    ,创建一个节点
    (B.var,OP(A,B.lo),OP(A,B.hi))
  • 缓存结果
“创建节点”当然应该自行消除重复数据,以满足“减少”的要求。分为3种情况,以满足订购要求

通过应用这种自底向上的方法,可以在BDD中转换由简单操作组成的复杂函数,每次转换时只需执行BDD的简单组合。当然,这会生成不属于最终结果的节点。变量和常量具有平凡的BDD

例如,
和(x,或(y,z))
是通过先深入到树中,为变量
x
(一个普通节点,
(x,0,1)
)创建一个BDD,然后为
y
z
,执行
(上述算法的一个实例,其中只有第一步真正关心操作是
)在表示
y
z
的BDD上,然后对结果执行
,BDD表示变量
x
。具体结果取决于您选择的变量顺序


对自身内部的其他函数求值的函数需要函数组合(如果已经用BDD表示调用的函数)对于BDD,这是可能的,但有一些最坏的情况,或者只是内联调用函数的定义。

存储BDD的数据结构可以基于
格式的三元组(level,u,v)
where
u
级别的变量为FALSE时,布尔函数是什么节点;
v
级别的变量为TRUE时,布尔函数是什么节点

可以使用Python包(
pip install dd
安装纯Python实现)对所描述的示例进行编程

从dd导入自动引用为_bdd
bdd=_bdd.bdd()
bdd.declare('x','y','z','a'))
x\u或y=bdd.add\u expr('x\/y')
x_和y=bdd.add_expr('x/\y')
not_x=bdd.add_expr(“~x”)
#变量重命名:x到y,y到z
let={'x':'y','y':'z'}
y_或z=bdd.let(let,x_或y)
#使用“BDD.apply”方法`
foo=bdd.apply('and',bdd.var('x'),y_或z)
#使用公式
foo \=bdd.add \'x/\(y\/z)'
断言foo==foo_
#使用BDD节点引用的字符串表示法
foo\uu=bdd.add\u expr('x/\{u}'。格式(u=y\u或uz))
断言foo==foo_
bar=bdd.apply('or',foo,~bdd.var('a'))
bar=bdd.add_expr(“{u}\/~a.”格式(u=foo))
断言条==条_
let={'y':~bdd.var('y')}
baz=bdd.let(let,x_和y)
baz=bdd.add\u expr('x/\~y')
断言baz==baz_
#使用GraphViz绘制图表
bdd.dump('foo.png',[foo])
此示例包括在BDD之间直接应用运算符(使用方法
BDD.apply
或解析调用这些运算符的布尔公式)和函数组合
x0 -0-> 0
...