Z3Py--Introduction

Z3 API in Python 学习笔记

简介

本教程演示了 Z3Py 的主要功能,即 Z3 在 Python 中的 API。使用 Z3Py 有很多好处。首先,对于那些见过编程语言但从未见过函数式语言的人来说,Z3Py 更加熟悉。

安装 Z3Py

可以使用以下命令从 pypi 安装 Z3Py 的 Python 绑定:

pip install z3-solver
入门示例

以下是一个简单的示例:

x = Int('x')
y = Int('y')
solve(x > 2, y < 10, x + 2*y == 7)

此示例创建了两个整数变量 xy,并定义了三个约束条件。solve 函数用于求解这些约束。

表达式简化

Z3Py 可以简化表达式:

x = Int('x')
y = Int('y')
print(simplify(x + y + 2*x + 3))
print(simplify(x < y + x + 2))
print(simplify(And(x + 1 >= 3, x**2 + x**2 + y**2 + 2 >= 5)))
/*
3 + 3*x + y
Not(y <= -2)
And(x >= 2, 2*x**2 + y**2 >= 3)
*/
配置选项

可以通过 set_option 配置 Z3 环境,例如显示结果的小数位数:

x = Real('x')
y = Real('y')
set_option(precision=30)
solve(x**2 + y**2 == 3, x**3 == 2)
/*
[y = -1.188528059421316533710369365015?,
 x = 1.259921049894873164767210607278?]
*/
创建有理数

Z3Py 可以处理大整数、有理数和无理代数数:

print(RealVal(1)/3)
print(Q(1, 3))
//1/3
//1/3
布尔逻辑

Z3 支持布尔运算符,例如 And, Or, Not, Implies, If 等:

p = Bool('p')
q = Bool('q')
r = Bool('r')
solve(Implies(p, q), r == Not(q), Or(Not(p), r))
//[q = True, p = False, r = False]
使用 Solver API

Z3 提供了不同的求解器。以下示例展示了基本的 Solver API:

x = Int('x')
y = Int('y')
s = Solver()
s.add(x > 10, y == x + 2)
print(s.check()) //sat
使用求解器遍历约束

可以遍历求解器中断言的约束并收集性能统计信息:

x = Real('x')
y = Real('y')
s = Solver()
s.add(x > 1, y > 1, Or(x + y > 3, x - y < 2))
for c in s.assertions():
    print(c)
print(s.statistics())
/*
x > 1
y > 1
Or(x + y > 3, x - y < 2)
(:max-memory   21.15
 :memory       21.15
 :num-allocs   449202
 :rlimit-count 38)
*/
检查模型

以下示例展示了检查模型的基本方法:

x, y, z = Reals('x y z')
s = Solver()
s.add(x > 1, y > 1, x + y > 3, z - x < 10)
print(s.check())
m = s.model()
for d in m.decls():
    print("%s = %s" % (d.name(), m[d]))
/*
sat
y = 2
x = 3/2
z = 0
*/
算术操作

Z3 支持实数和整数变量,可以在一个问题中混合使用:

x = Real('x')
y = Int('y')
a, b, c = Reals('a b c')
s, r = Ints('s r')
print(x + y + 1 + (a + s))
//x + ToReal(y) + 1 + a + ToReal(s)
使用简化器

可以使用 simplify 对 Z3 表达式应用简单的转换:

x, y = Reals('x y')
t = simplify((x + y)**3, som=True)
print(t)
//x*x*x + 3*x*x*y + 3*x*y*y + y*y*y
使用位向量

现代 CPU 和主流编程语言使用定长位向量的算术。以下示例展示了如何创建位向量变量和常量:

x = BitVec('x', 16)
y = BitVec('y', 16)
print(x + 2)
print(simplify(x + y - 1))
/*x + 2
65535 + x + y*/
函数

Z3 中的函数没有副作用,是全定义的,即它们在所有输入值上都有定义:

x = Int('x')
y = Int('y')
f = Function('f', IntSort(), IntSort())
solve(f(f(x)) == x, f(x) == y, x != y)
//[x = 0, y = 1, f = [1 -> 0, else -> 1]]
使用 list comprehensions

可以使用 Python 的 list comprehensions 创建 Z3 表达式和问题:

# Create list [1, ..., 5] 
print ([ x + 1 for x in range(5) ])

# Create two lists containg 5 integer variables
X = [ Int('x%s' % i) for i in range(5) ]
Y = [ Int('y%s' % i) for i in range(5) ]
print (X)

# Create a list containing X[i]+Y[i]
X_plus_Y = [ X[i] + Y[i] for i in range(5) ]
print (X_plus_Y)

# Create a list containing X[i] > Y[i]
X_gt_Y = [ X[i] > Y[i] for i in range(5) ]
print (X_gt_Y)

print (And(X_gt_Y))

# Create a 3x3 "matrix" (list of lists) of integer variables
X = [ [ Int("x_%s_%s" % (i+1, j+1)) for j in range(3) ] 
      for i in range(3) ]
pp(X)
# [1, 2, 3, 4, 5]
#[x0, x1, x2, x3, x4]
#[x0 + y0, x1 + y1, x2 + y2, x3 + y3, x4 + y4]
#[x0 > y0, x1 > y1, x2 > y2, x3 > y3, x4 > y4]
#And(x0 > y0, x1 > y1, x2 > y2, x3 > y3, x4 > y4)
#[[x_1_1, x_1_2, x_1_3],
# [x_2_1, x_2_2, x_2_3],
# [x_3_1, x_3_2, x_3_3]]
示例问题

问题1

d, a, t, v_i, v_f = Reals('d a t v__i v__f')
equations = [d == v_i * t + (a*t**2)/2, v_f == v_i + a*t]
problem = [v_i == 30, v_f == 0, a == -8]
solve(equations + problem)

问题2

d, a, t, v_i, v_f = Reals('d a t v__i v__f')
equations = [d == v_i * t + (a*t**2)/2, v_f == v_i + a*t]
problem = [v_i == 0, t == 4.10, a == 6]
solve(equations + problem)
位操作技巧

使用 Z3 证明位操作技巧是否有效:

x = BitVec('x', 32)
powers = [2**i for i in range(32)]
fast = And(x != 0, x & (x - 1) == 0)
slow = Or([x == p for p in powers])
prove(fast == slow)
print ("trying to prove buggy version...")
fast   = x & (x - 1) == 0
prove(fast == slow)
#And(x != 0, x & x - 1 == 0)
#proved
#trying to prove buggy version...
#counterexample
#[x = 0]

证明有相反的位

x      = BitVec('x', 32)
y      = BitVec('y', 32)

# Claim: (x ^ y) < 0 iff x and y have opposite signs
trick  = (x ^ y) < 0

# Naive way to check if x and y have opposite signs
opposite = Or(And(x < 0, y >= 0),
              And(x >= 0, y < 0))

prove(trick == opposite)
//proved
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值