我想使用Scala ^ Z3进行增量求解。在每次迭代中,我想
a)添加公式的一部分
b)添加断言
应该为每个后续迭代保留公式,但是如果我无法实现它,我将需要删除断言,因为下一次迭代中的断言将是不同的。
那么有没有办法删除以前的陈述? Z3Context.pop()听起来有点像我需要的,但我找不到它的作用的描述..
非常感谢那里的一些帮助!
祝福, 1428162
答案 0 :(得分:3)
是的,你是对的,你想要pop
(删除)最后一个断言。为此,首先需要使用push
保存当前的断言集。这就是Z3支持范围的方式。
通过添加公式的某些部分,我将假设您的意思是定义一个变量,其中包含一些原始大型公式的额外块,您正在进行增量检查。我还假设原始公式是子公式的大型组合。这个新公式将在推送和弹出之间保持定义(假设您保留一个引用它的变量)。
以下是z3py中大致以下伪代码示例的链接,除了在z3py脚本中我还假设公式和约束实际上是相同的东西,但也许你想要创建一些不同的约束基于子公式的那一部分:http://rise4fun.com/Z3Py/LIxW
我没有使用过Scala ^ Z3,但大致你想要做以下事情:
formula // list containing parts (sub-formulas) of original large formula
while (formulaPart = formula.removeFirst()) // remove first element of list
Z3Context.push() // save current set of assertions
assertion = makeConstraint( formulaPart ) // assertion based on sub-formula
Z3Context.assertCnstr( assertion ) // add new assertion
if !Z3Context.check() // check if assertions cannot be satisfied
Z3Context.pop() // remove most recent assertion
以下是使用.NET API中的pop / push的示例:http://research.microsoft.com/en-us/um/redmond/projects/z3/test__managed_8cs_source.html#l00637
您也对此感兴趣:Soft/Hard constraints in Z3
答案 1 :(得分:2)
是的,ctx.pop()
就是你想要的。它也可以采用参数,如ctx.pop(2)
,但如果省略则默认为1。直观地说,将求解器的状态恢复到“n
推送前”的位置。
所以,如果你这样做:
ctx.assertCnstr(formula1)
ctx.push()
ctx.assertCnstr(extraAssertion)
ctx.check() match {
case Some(true) => ... // SAT
case Some(false) => ... // UNSAT
case None => ... // UNKNOWN
}
ctx.pop(1)
...解决方案的状态将恢复为调用push()
之前的状态。
请注意,它们的行为与Z3 C API中的等效行为完全相同,因此其中的文档也适用。
请注意,从Z3 4.0开始,不推荐在上下文中调用push
和pop
。现在推荐的方法是让上下文首先创建一个求解器,然后直接在求解器上使用push
和pop
(在Z3 4.0之前没有求解器的概念)。 Scala ^ Z3还没有赶上,但你可以预期这种变化最终会被传播。