[英]Fill Z3Py Tree with values
我有这种树数据类型,我希望能够在这里上下移动。 但实际上,任何结构都可以工作,只要我能得到一个节点的父/左子/右子。
Tree = Datatype('Tree')
Tree.declare('nil')
Tree.declare('node', ('label', IntSort()), ('left', Tree), ('up', Tree), ('right', Tree))
Tree = Tree.create()
但我不知道如何填充数据结构...我想我可以像下面一样一次创建一个节点,但这似乎是错误的方式。
trees = [Const('t' + str(i), Tree) for i in range(3)]
Tree.up(trees[0]) = Tree.nil
Tree.left(trees[0]) = trees[1]
Tree.right(trees[0]) = trees[2]
Tree.up(trees[1]) = trees[0]
Tree.up(trees[2]) = trees[0]
谢谢你的帮助。
我觉得你对这些数据结构的工作原理有些误解。 Z3的语言,也就是Z3py的语言,是一阶逻辑(模理论)的语言,其中只存在假设/事实。 命令式编程语言的主要区别之一是,您没有破坏性更新*,即您无法更新实体的值。
在您的代码中,您尝试通过基本上操纵指针(例如,通过(尝试)分配)以命令性方式构建数据结构
Tree.up(trees[0]) = Tree.nil
你可能想到的是“把trees[0].up
指向nil
”。 但是,由于破坏性更新不是一阶语言的一部分,因此您必须“思考功能”,即“假设up(trees[0]) == nil
”。 添加这样的假设可以如下完成( 在线上升4fun):
s = Solver()
s.add(
Tree.up(trees[0]) == Tree.nil,
Tree.left(trees[0]) == trees[1],
Tree.right(trees[0]) == trees[2],
Tree.up(trees[1]) == trees[0],
Tree.up(trees[2]) == trees[0]
)
print s.check() # sat -> your constraints are satisfiable
没有破坏性更新的结果是您无法以命令式编程语言的典型方式修改数据结构。 通过这样的更新,可以修改树,例如trees[1].up.left != trees[1]
,例如,通过赋值trees[1].up.left = trees[2]
(对于trees[1] != trees[2]
)。 但是,如果添加相应的假设
s.add(
trees[1] != trees[2],
Tree.left(Tree.up(trees[1])) == trees[2]
)
print s.check() # unsat
你会发现你的约束不再令人满意,因为旧的和新的假设都是矛盾的。
顺便说一句,您对Tree
数据类型的定义使得可以假设Tree.up(nil) == someTree
。 假设t1 != t2
是树的叶子并且left(t1) == right(t1) == nil
并且类似于t2
,那么如果up(nil) == t1
and up(nil) == t2
up(nil) == t1
,你将会有矛盾up(nil) == t2
。 不过,我不知道如何在Z3级别上防止这种情况。
*可以添加破坏性更新作为语法糖,因为它们可以通过所谓的通过转换转化为假设。 例如,这是在中间验证语言Boogie中完成的 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.