使用 z3.BitVecRef 与整数
Using z3.BitVecRef vs Integer
z3 求解器中的常量可以是通常的 python 类型 (1) 或 z3 Ref (2),如以下人工示例所示,其中 x
和 y
通过这两种类型接受相同的约束集:
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 从出现在程序中的文字值插入隐式强制转换。虽然这对编程来说很方便,但如果将它与整数进行比较,可能会导致误解;这首先是不允许的。希望一切顺利!
z3 求解器中的常量可以是通常的 python 类型 (1) 或 z3 Ref (2),如以下人工示例所示,其中 x
和 y
通过这两种类型接受相同的约束集:
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 从出现在程序中的文字值插入隐式强制转换。虽然这对编程来说很方便,但如果将它与整数进行比较,可能会导致误解;这首先是不允许的。希望一切顺利!