使用 z3.BitVecRef 与整数

Using z3.BitVecRef vs Integer

z3 求解器中的常量可以是通常的 python 类型 (1) 或 z3 Ref (2),如以下人工示例所示,其中 xy通过这两种类型接受相同的约束集:

from z3 import *

s = Solver()
x, y = BitVecs("x y",7)
d = BitVecVal(6, 7)

                   #constraints:
#                   ------------
s.add(x & 6 != 6)  #1'th or 2'th bit unset using Integer    #....(1)
#                                                   vs
s.add(y & d != d)  #1'th or 2'th bit unset using BitVecVal  #....(2)


check = s.check()
if check == sat:
    print(s.model())

那么,(1)、(2)中有没有一个更喜欢?似乎,我不明白为什么有常量排序,如果可以用通常的 python 类型来完成。

Z3的结果SMT代码如下所示:

#  
def toSMT2Benchmark(f, status="unknown", name="benchmark", logic=""):
  v = (Ast * 0)()
  return Z3_benchmark_to_smtlib_string(f.ctx_ref(), name, logic, status, "", 0, v, f.as_ast())

print(toSMT2Benchmark(x & 6 != 6))
print(toSMT2Benchmark(y & d != d))

输出:

; benchmark
(set-info :status unknown)
(declare-fun x () (_ BitVec 7))
(assert
 (and (distinct (bvand x (_ bv6 7)) (_ bv6 7)) true))
(check-sat)

; benchmark
(set-info :status unknown)
(declare-fun y () (_ BitVec 7))
(assert
 (and (distinct (_ bv6 7) (bvand y (_ bv6 7))) true))
(check-sat)

因此,这两种形式确实为 Z3 创建了几乎相同的输入。

从求解器生成 SMTLib 的更简单方法是简单地打印 s.sexpr():

from z3 import *

s = Solver()
x, y = BitVecs("x y",7)
d = BitVecVal(6, 7)

s.add(x & 6 != 6)  #1'th or 2'th bit unset using Integer    #....(1)

check = s.check()
print(s.sexpr())
if check == sat:
    print(s.model())

这会打印:

declare-fun k!0 () (_ BitVec 2))
(declare-fun x () (_ BitVec 7))
(declare-fun k!1 () Bool)
(declare-fun k!2 () Bool)
(assert (distinct (bvand x #b0000110) #b0000110))
(model-del k!0)
(model-add x () (_ BitVec 7) (concat #x0 k!0 #b0))
(model-del k!1)
(model-add k!0 () (_ BitVec 2) (ite k!1 #b11 (bvnot #b11)))
(model-del k!2)
(model-add k!1 () Bool (not k!2))

[x = 0]

这里有两点需要注意:

  • s.sexpr() 可用于随时打印任何求解器状态的“内部”形式。
  • 从未在你的约束的第一种形式中实际使用了一个整数:因为你将它与bit-vector进行比较,z3自动将它强制转换为位向量.事实上,将 bit-vector 与整数值进行比较 而不是 是有效的,即 type-error。你可以这样看:
s.add(x & 6 != IntVal(6))

为此,z3 会抛出 sort-mismatch 错误:

z3.z3types.Z3Exception: sort mismatch

简而言之,SMTLib 是一个带有simple-types 的逻辑,一个bit-vector 只能与另一个bit-vector 进行比较。碰巧 Python API 从出现在程序中的文字值插入隐式强制转换。虽然这对编程来说很方便,但如果将它与整数进行比较,可能会导致误解;这首先是不允许的。希望一切顺利!