如何使用包模型创建具有出现位的BDD

时间:2017-11-12 07:42:23

标签: python bag binary-decision-diagram

我正在通过一份许可指南,将产品系列表示为行李模型,其中也会考虑事件以提出BDD。

我想在我的问题中加入类似的步骤。文字说

  

如果我们采用bag-model,除了处理功能的重复之外,实现类似于set-model实现。        ROBDD不允许重复节点。为了处理BDD本身中特征的出现次数,我们设计了        编码它的发生级别。我们编码这个数字二进制。例如,如果我们有一个具有3个特征的产品:x,y和z,以及        一个特征的最大出现次数为7,那么我们需要三个二进制位来对其进行编码。让产品系列W有一个        产品具有三个x功能和六个z功能以及零y功能。我们的产品系列包含由BDD代表的产品Pt        在图3.7中。代表此包的BDD以与设定模型类似的方式描述产品。但是,我们编码        在包含bl,b2和b3的节点级别中出现。我们在图3.7中读到,如果此产品中存在x,那么我们必须这样做        选择bl和b2,但不选择b3。这是分别代表b3,b2和bb的二进制代码011,其携带三个for的出现        X。类似地,对于y存在于此产品中,我们得到二进制出现编码为000,即0次出现。对于z,我们得到了        二进制出现110,其中包含数字6。

因此,对于产品族Z = {{(x,3),(y,0),(z,6)}},相应的bdd将为 - >

BDD

对于产品系列W = {{(x,3),(y,1),(z,7)}} BDD将是

BDD2

但是他是如何提出这些BDD的,必须有一些BDD的基本公式。能否帮助我了解如何为特定家庭达成相同的公式,以便我可以在其他用例中进一步使用它。感谢。

1 个答案:

答案 0 :(得分:0)

bag是具有多次出现的元素的集合。 Bags中的标准模块Temporal Logic of Actions (TLA+)包含与行李相对应的数学定义。

要从binary decision diagram的图形转换为公式,我使用下面的代码。来自OP的第一个BDD的答案是:

 /\ b \in 0 .. 7
 /\ x \in 0 .. 1
 /\ y \in 0 .. 1
 /\ z \in 0 .. 1
 /\  \/ (b = 0) /\ (y = 1)
     \/ (b = 3) /\ (x = 1)
     \/ (b = 6) /\ (z = 1)

此表达式以TLA +编写。

上面实际上不是一个包,因为一个包至少包含一个每个元素的出现(所以y没有出现意味着这不是包;省略y应将其转换为与行李相对应的BDD。一个包是否适合产品系列是一个单独的问题,我不会讨论。

您可以调整代码以确认第二张图中显示的BDD公式。

以下代码使用Python包omega == 0.1.1dd == 0.5.1(免责声明:我是他们的作者)。这些工作在纯Python中,这对于这个大小的BDD就足够了(否则构建dd.cudd将允许你使用CUDD - 当然这对于小到足以手写的BDD没有区别。

#!/usr/bin/env python
"""Convert from a BDD figure to a formula."""
from omega.symbolic import fol

# "bare" BDDs (without integers) can be used also
# via the package `dd`
# from dd import autoref as _bdd

# bdd = _bdd.BDD()

ctx = fol.Context()
ctx.declare(x=(0, 1), y=(0, 1), z=(0, 1), b=(0, 7))

bdd = ctx.bdd
# bdd.declare('x', 'y', 'z', 'b1', 'b2', 'b3')

# level of b3
u1 = bdd.add_expr('b_2')
u2 = bdd.add_expr('~ b_2')
# level of b2
u3 = bdd.add_expr('ite(b_1, {u}, False)'.format(u=u1))
u4 = bdd.add_expr('ite(b_1, False, {u})'.format(u=u2))
u5 = bdd.add_expr('ite(b_1, {u1}, {u2})'.format(u1=u1, u2=u2))
u6 = bdd.add_expr('ite(b_1, {u2}, False)'.format(u2=u2))
# level of b1
u7 = bdd.add_expr('ite(b_0, {high}, {low})'.format(
    low=u3, high='False'))
u8 = bdd.add_expr('ite(b_0, {high}, {low})'.format(
    low=u4, high='False'))
u9 = bdd.add_expr('ite(b_0, {high}, {low})'.format(
    low=u5, high='False'))
u10 = bdd.add_expr('ite(b_0, {high}, {low})'.format(
    low=u3, high=u6))
u11 = bdd.add_expr('ite(b_0, {high}, {low})'.format(
    low='False', high=u6))
u12 = bdd.add_expr('ite(b_0, {high}, {low})'.format(
    low=u4, high=u6))
u13 = bdd.add_expr('ite(b_0, {high}, {low})'.format(
    low=u5, high=u6))
# level of z
u14 = bdd.add_expr('ite(z_0, {high}, {low})'.format(
    low='False', high=u7))
u15 = bdd.add_expr('ite(z_0, {high}, {low})'.format(
    low=u8, high=u9))
u16 = bdd.add_expr('ite(z_0, {high}, {low})'.format(
    low=u11, high=u10))
u17 = bdd.add_expr('ite(z_0, {high}, {low})'.format(
    low=u12, high=u13))
# level of y
u18 = bdd.add_expr('ite(y_0, {high}, {low})'.format(
    low=u14, high=u15))
u19 = bdd.add_expr('ite(y_0, {high}, {low})'.format(
    low=u16, high=u17))
# level of x
from_fig = bdd.add_expr('ite(x_0, {high}, {low})'.format(
    low=u18, high=u19))

# the variable order from the first figure in the OP
levels = dict(x_0=0, y_0=1, z_0=2, b_0=3, b_1=4, b_2=5)
fol._bdd.reorder(bdd, levels)
bdd.dump('foo_1.png', [from_fig])
# a better variable order
levels = dict(b_0=0, b_1=1, b_2=2, x_0=3, y_0=4, z_0=5)
fol._bdd.reorder(bdd, levels)
bdd.dump('foo_2.png', [from_fig])

# Create the BDD directly from an expression
s = '''
    \/ (b = 3 /\ x = 1)
    \/ (b = 0 /\ y = 1)
    \/ (b = 6 /\ z = 1)
    '''
from_formula = ctx.add_expr(s)
assert from_formula == from_fig

# print a minimal formula in disjunctive normal form
# use this to covert BDDs to expressions
print(ctx.to_expr(from_fig, show_dom=True))

可以使用pip安装依赖项:

pip install dd==0.5.1
pip install omega==0.1.1

enter image description here

通过重新排序上述代码中的变量级别,我们可以获得更小的(RO)BDD:

enter image description here

上述BDD使用negated edges表示,详见tutorial on BDDs