Z3py对喇叭条的不变诱导

时间:2016-08-06 17:44:33

标签: logic z3 z3py logic-programming

我目前正在使用Z3py来推导一些不变量,这些不变量被编码为horn-clauses的组合,同时也为不变量提供模板。如果你看到下面的代码片段,我首先从一个简单的例子开始。

x = 0;
while(x < 5){
  x += 1
}
assert(x == 5)

这转化为喇叭条款

x = 0 =&gt; INV(x)的

x&lt; 5 / \ Inv(x)=&gt; Inv(x +1)

不(x <5)/ \ Inv(x)=&gt; x = 5

这里的不变量是x <= 5。

我提供了a * x + b&lt; = c形式的不变量的模板 因此,所有求解器必须做的是猜测a,b和c的一组值,它们可以减少到x <= 5。

然而,当我编码时,我一直不满意。如果试图断言Not(x == 5)我得到a = 2,b = 1/8和c = 2这对我来说没什么意义作为反例。

我在下面提供了我的代码,非常感谢有关纠正编码的任何帮助。

x = Real('x')
x_2 = Real('x_2')
a = Real('a')
b = Real('b')
c = Real('c')
s = Solver()
s.add(ForAll([x],And(
Implies(x == 0 , a*x + b <= c),
Implies(And(x_2 == x + 1, x < 5, a*x + b <= c), a*x_2 + b <= c),
Implies(And(a*x + b <= c, Not(x < 5)), x==5)
)))
if (s.check() == sat):
    print(s.model())

编辑:对我来说很陌生。如果我删除x_2定义并在第二个horn子句中将x_2替换为(x + 1)以及删除x_2 = x_2 + 1,那么无论是否写入Not(x == 5)或x == 5,我都会感到不满在最后的角色条款中。

1 个答案:

答案 0 :(得分:0)

阻止原始编码工作的原因有两个:

1)对于x_2 == x + 1的单个值,不可能满足所有x的{​​{1}}。因此,如果您要撰写x_2,则x_2 == x + 1x都需要进行普遍量化。

2)有些令人惊讶的是,这个问题在整数中是可以满足的,但在实际中却不是。您可以看到x_2子句的问题。如果x < 5 /\ Inv(x) => Inv(x + 1)是整数,则x会满足此要求。但是,如果允许x <= 5为任何实际值,那么您可以xx == 4.5x < 5,但不是x <= 5,所以x + 1 <= 5在实际中不满足这个问题。

此外,您可能会发现定义Inv(x) = (x <= 5)很有帮助,它可以清除代码。以下是对这些更改的问题编码:

Inv(x)

还有一件事:将from z3 import * # Changing these from 'Int' to 'Real' changes the problem from sat to unsat. x = Int('x') x_2 = Int('x_2') a = Int('a') b = Int('b') c = Int('c') def Inv(x): return a*x + b <= c s = Solver() # I think this is the simplest encoding for your problem. clause1 = Implies(x == 0 , Inv(x)) clause2 = Implies(And(x < 5, Inv(x)), Inv(x + 1)) clause3 = Implies(And(Inv(x), Not(x < 5)), x == 5) s.add(ForAll([x], And(clause1, clause2, clause3))) # Alternatively, if clause2 is specified with x_2, then x_2 needs to be # universally quantified. Note the ForAll([x, x_2]... #clause2 = Implies(And(x_2 == x + 1, x < 5, Inv(x)), Inv(x_2)) #s.add(ForAll([x, x_2], And(clause1, clause2, clause3))) # Print result all the time, to avoid confusing unknown with unsat. result = s.check() print result if (result == sat): print(s.model()) 作为模板编写对我来说有点奇怪,因为对于某个整数a*x + b <= c,这与a*x <= d相同。