各位小伙伴大家好,今天我将给大家演示一个非常高级的工具,SMT求解器。应用领域非常广,解各类方程,解各类编程问题(例如解数独),解逻辑题等都不在话下。
今天小小明就将带大家看看这其中的精彩:

文章目录
🎨z3-solver求解器🎨
🔦简介🔫
z3-solver是由Microsoft Research(微软)开发的SMT求解器,它用于检查逻辑表达式的可满足性,可以找到一组约束中的其中一个可行解,缺点是无法找出所有的可行解(对于规划求解问题可以是scipy)。
z3-solver可应用于软/硬件的验证与测试、约束求解、混合系统的分析、安全、生物,以及几何求解等问题。Z3 主要由 C++ 开发,提供了 .NET、C、C++、Java、Python 等语言调用接口,下面以python接口展开讲解。
z3可直接通过pip安装:
pip install z3-solver
参考示例:https://ericpony.github.io/z3py-tutorial/guide-examples.htm
z3中有3种类型的变量,分别是整型(Int),实型(Real)和向量(BitVec)。
对于整数类型数据,基本API:
- Int(name, ctx=None),创建一个整数变量,name是名字
- Ints (names, ctx=None),创建多个整数变量,names是空格分隔名字
- IntVal (val, ctx=None),创建一个整数常量,有初始值,没名字。
对于实数类型的API与整数类型一致,向量(BitVec)则稍有区别:
- Bitvec(name,bv,ctx=None),创建一个位向量,name是他的名字,bv表示大小
- BitVecs(name,bv,ctx=None),创建一个有多变量的位向量,name是名字,bv表示大小
- BitVecVal(val,bv,ctx=None),创建一个位向量,有初始值,没名字。
simplify(表达式),对可以简化的表达式进行简化。
完整API文档可参考:https://z3prover.github.io/api/html/namespacez3py.html
下面我们看看z3的基本用法:
🔀数学运算🎦
先以一个简单例子入门:
♊️二元一次方程♋️
比如使用z3解二元一次方程:
x − y = 3 x-y = 3 x−y=3
3 x − 8 y = 4 3x-8y=4 3x−8y=4
solve直接求解:
from z3 import *
x, y = Reals('x y')
solve(x-y == 3, 3*x-8*y == 4)
[y = 1, x = 4]
如果需要取出指定变量的结果,可以使用Solver求解器:
- s=solver(),创建一个解的对象。
- s.add(条件),为解增加一个限制条件
- s.check(),检查解是否存在,如果存在,会返回"sat"
- modul(),输出解得结果
x, y = Reals('x y')
solver = Solver()
qs = [x-y == 3, 3*x-8*y == 4]
for q in qs:
solver.add(q)
if solver.check() == sat:
result = solver.model()
print(result)
print("x =", result[x], ", y =", result[y])
[y = 1, x = 4]
x = 4 , y = 1
可以通过solver.assertions()查看求解器已经添加的约束和约束的个数:
assertions = solver.assertions()
print(assertions)
print(len(assertions))
[x - y == 3, 3*x - 8*y == 4]
2
如果需要删除约束条件,则需要在添加约束前调用solver.push()方法。
下面我们如下方程为例进行演示:
x > 10 x > 10 x>10
y = x + 2 y = x + 2 y=x+2
获取结果:
x, y = Ints('x y')
solver = Solver()
solver.add(x > 10, y == x + 2)
print("当前约束:", solver.assertions())
if solver.check() == sat:
print("结果:", solver.model())
else:
print(solver.check())
当前约束: [x > 10, y == x + 2]
结果: [x = 11, y = 13]
下面我们再增加一个可以被删除的约束y < 11:
solver.push()
solver.add(y < 11)
print("当前约束:", solver.assertions())
if solver.check() == sat:
print("结果:", solver.model())
else:
print(solver.check())
当前约束: [x > 10, y == x + 2, y < 11]
unsat
可以看到这种约束下,无有效解。
删除约束,再计算一次:
solver.pop()
print("当前约束:", solver.assertions())
if solver.check() == sat:
print("结果:", solver.model())
else:
print(solver.check())
当前约束: [x > 10, y == x + 2]
结果: [x = 11, y = 13]
⚠️注意:没有push过的约束条件时直接pop会导致报出
Z3Exception: b'index out of bounds'错误。
🚦线性多项式约束🚧
约束条件为:
x > 2 y < 10 x + 2 ∗ y = 7 x > 2 \\ y < 10 \\ x + 2 * y = 7 \\ x>2y<10x+2∗y=7
上述约束x和y都是整数,我们需要找到其中一个可行解:
x, y = Ints('x y')
solve([x > 2, y < 10, x + 2*y == 7])
结果:
[y = 0, x = 7]
当然,实际可行的解不止这一个,z3只能找到其中一个可行的解。
💧非线性多项式约束🌌
约束条件为:
x 2 + y 2 > 3 x^2 + y^2 > 3 x2+y2

本文介绍了z3-solver求解器的使用,包括解决二元一次方程、线性多项式约束、非线性多项式约束、高中物理问题、综合性编程问题(如数独、八皇后问题)以及逻辑题。z3能快速找到一个问题的可行解,但不保证找到所有解。此外,还展示了如何通过Python解决安装依赖问题和逻辑推理题。
最低0.47元/天 解锁文章
215





