Z3约束求解
pip install z3-solver
函数介绍与使用
数据类型
数据类型 | 示例 | 解释 |
---|---|---|
Bool | x = Bool(‘x’) | 创建一个布尔变量x |
Bools | x, y, z = Bools(‘x y z’) | 创建三个布尔变量x,y,z,以此类推,后面的Ints,Reals,BitVecs等都可以用这种方式创建 |
BitVec | x = BitVec(‘x’, 8) | 创建一个8位的二进制向量变量x |
Int | x = Int(‘x’) | 创建一个整数变量x |
Real | x = Real(‘x’) | 创建一个实数变量x |
常用函数
函数 | 功能 |
---|---|
And(a, b) | 逻辑与,返回a和b的逻辑与,表示同时满足a和b |
Or(a, b) | 逻辑或,返回a和b的逻辑或,表示满足a或b |
Not(a) | 逻辑非,返回a的逻辑非,表示不满足a |
Xor(a, b) | 逻辑异或,返回a和b的逻辑异或,表示满足a或b,但不同时满足 |
If(a, b, c) | 条件选择,返回a和b的条件选择,表示满足a时返回b,否则返回c |
Distinct(a, b, c) | 不同,返回a、b、c的不同关系,表示a、b、c中没有相同的值 |
Sum(a, b, c) | 求和,返回a、b、c的求和,表示a、b、c的和 |
Implies(a, b) | 蕴含,返回a和b的蕴含关系,表示a成立那b必然成立,否则无所谓 |
PbEq([(x, 1), (y, 2), (z, 3)] , n) | 伪布尔约束,x,y,z为布尔变量,1,2,3为权重,n为目标值,表示满足x*1+y*2+z*3=n |
函数详解
- PbEq
用于表示多个布尔变量中恰好有几个为真
这里约束的表达式是 变量真值 * 权重 = 目标值 当所有权重为1时,表示多个目标只有一个成立
s.add(PbEq([(x, 1), (y, 2), (z, 3)], 6)) # 约束条件是x*1+y*2+z*3=6
表示条件x,y,z中只有一个为真s.add(PbEq([(x, 1), (y, 1), (z, 1)], 1))
创建Solver对象
创建Solver对象,用于添加约束条件 Solver用来“管理”和“求解”你添加进去的逻辑约束条件 他能做三件事
- 接收你的逻辑条件(例如:x + y == 3)
- 自动进行逻辑推理和求解
- 告诉你是否有解(SAT),并返回满足条件的解(Model)
from z3 import *
solver = Solver()
创建变量
若要创建少量变量,只需
x,y,z = 变量类型('x y z')
x, y, z = [Int(n) for n in ['x', 'y', 'z']] #与上面相同
若要创建大量变量,可以使用列表推导式
x = [变量类型(f'x{i}') for i in range(10000)] # 10000个变量,使用x[i]访问
添加约束条件
使用Solver对象的add方法添加约束条件
solver.add(x == 3)
调用check方法检查是否满足约束条件
调用Solver对象的check方法,检查是否满足约束条件 如果有解,返回sat,否则返回unsat
if solver.check() == sat:
# 有解,输出模型变量的值
m = solver.model()
print(m[x])
else:
print('无解')
调用model方法获取模型
调用Solver对象的model方法,获取模型 模型是一个字典,键是变量,值是变量取值
m = solver.model()
print(m[x])
求解示例
from z3 import *
# 创建Solver对象
solver = Solver()
# 创建变量
x, y, z = Bools('x y z')
# 添加约束条件
solver.add(x == True)
solver.add(y == False)
solver.add(z == True)
# 调用check方法检查是否满足约束条件
if solver.check() == sat:
# 调用model方法获取模型
m = solver.model()
# 输出模型变量的值
print(m[x], m[y], m[z])
else:
print('无解')
流程图
graph TD A[创建Solver对象] --> B[创建变量] B --> C[添加约束条件] C --> D[调用check方法] D --> E[有解] E --> F[调用model方法] F --> G[输出模型变量的值] D --> H[无解]