【问题标题】:Invariant induction over horn-clauses with Z3py用 Z3py 对喇叭子句进行不变归纳
【发布时间】:2016-12-12 22:09:42
【问题描述】:

我目前正在使用 Z3py 来推断一些不变量,这些不变量被编码为角子句的结合,同时还为不变量提供了模板。如果您看到下面的代码 sn-p,我首先从一个简单的示例开始。

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

这翻译成喇叭子句

x = 0 => Inv(x)

x Inv(x +1)

非(x x = 5

这里的不变量是 x

我为 a*x + b

但是,当我对其进行编码时,我总是感到不安。如果尝试断言 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,我都会感到不安在最后的号角子句中。

【问题讨论】:

  • 我想我修好了。我将所有 Reals 更改为 Ints 并删除了 x_2 定义,如我的编辑中所述。突然它起作用了,我得到了 x

标签: logic z3 z3py logic-programming


【解决方案1】:

有两件事使您的原始编码无法正常工作:

1) 对于单个值 x_2,不可能满足所有 xx_2 == x + 1。因此,如果你要写x_2 == x + 1xx_2 都需要被普遍量化。

2) 有点令人惊讶的是,这个问题在整数中是可满足的,但在实数中是不可满足的。您可以看到子句x &lt; 5 /\ Inv(x) =&gt; Inv(x + 1) 的问题。如果x 是一个整数,那么x &lt;= 5 可以满足这一要求。但是,如果允许x 为任何实值,那么您可以有x == 4.5,它同时满足x &lt; 5x &lt;= 5,但不满足x + 1 &lt;= 5,所以Inv(x) = (x &lt;= 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 &lt;= c 写为模板对我来说有点奇怪,因为对于某个整数d,这与a*x &lt;= d 相同。

【讨论】:

  • 非常感谢!是的,模板有点多余。这是因为我正在开发一个模板生成器,它查看可能引入冗余的基本组件(例如 '+' 和 '-' )的可能组合。这是我稍后会优化的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多