Z3求解器简介及环境搭建

0、引言

Z3 是微软研究领域最先进的定理证明器。它可以用来检查逻辑公式在一个或多个理论上的可满足性。Z3为软件分析及验证工具提供了一个引人注目的匹配, 因为几个常见的软件构造直接映射到支持的理论中

1Z3的基本架构:

在深入研究Z3的体系结构细节之前,让我们看一下Z3的体系结构,以了解它是如何执行的。Z3集成了一个SAT求解器、一个核心理论求解器(同余闭合核)、4个辅助求解计算器以及一个e匹配抽象机(e-match)。它的体系结构如图1所示。

图 1 架构图

Z3的简化器(simplifier )采用了一种不完整但有效的简化方案。例如,它将p^true简化为p,将x=4^f(x)简化为f(4)(在这两个例子中,运算符^用作逻辑运算符And。Z3的编译器被认为是一个节点,它将简化的输入转换成由一组子句和同余闭包节点组成的不同的数据结构。同余闭包核心处理等式和未解的函数。它接收来自SAT求解器的赋值,并使用E-matching方法对其进行处理。SAT求解器对公式进行求解,并将结果传递回同余闭合核。然后同余闭合核对结果进行处理。有四种主要类型的理论求解器,用于算术,数组和其他。它们是线性算术、位向量、数组和元组。理论求解基于同余闭包算法,这是大多数SMT求解器使用的算法。因此,同余闭包可以作为核心解算器,其他理论解算器可以作为外围辅助解算器。

2、程序源码组织结构

Z3最初并不是一个开源软件,而是在公司内部和研究团队中使用的。因此,Z3的源代码一开始组织并不太好。在Z3对开源候,为了更好地为其他用户提供使用,开发人员开始重写代码的某些部分并清理了Z3存储库。他们将所有代码都放到z3/src目录中,并使在z3/src的子目录中更容易找到某个模块。现在Z3的源代码可读性很好,而且组织结构比较清晰。

图 2 源码组织图

Z3项目库有以下四个子目录:

1)、z3/doc,用于生成API doc文件和代码doc文件。

2)、z3/examples,它提供了一组示例或基准测试,帮助用户理解如何用不同的API语言表示问题。

3)、z3/scripts,包含用了于更新外部z3 API的文件

4)、z3/src,它包含了z3的所有核心模块。

3、模块分析

通过对代码组织的了解,我们可以继续将Z3划分如下几个模块。(如图3中的文件夹模块所示)

1)、Make和Built模块:为使用Z3做准备。

2)、RiSE4fun模块:在线工具其他项目模块:集成Z3到其他项目。

3)、scripts模块:支持make和build模块,文档更新功能模块:包含解析器、测试器、求解器、sat、model等一系列子模块的核心模块。

4)、API、sat和math模块:支持不同输入格式的源代码Doc模块:生成API和代码文档。

此外,位于另一个存储库中的测试模块是整个项目的单独部分,它提供了测试基础设施和基准测试。

4、层次分析

一个软件应用程序,在开发软件体系结构时要考虑三个方面的问题,即描述/工具层、业务/领域层和数据/代码访问层。这种分层结构为我们分析Z3项目提供了参考。在这里我们使用支持层而不是数据访问层,因为我们认为这样更合适。

1)、工具层(utility):这一层用于用户和Z3之间的交互。我们可以在不同的平台上使用Z3和命令行。此外,我们也可以在RiSE4fun网站上测试Z3,或者将Z3插入到其他项目中。Make和build模块是使用命令行Z3的重要部分。它们是用于使用前的编译等工作。这两个模块依赖于核心层中的脚本模块,因为脚本模块中的python文件对于执行make和build是必需的。

2)核心层(core):这一层主要是Z3核心功能的实现。在核心层,大部分模块用于实现Z3的功能的源码实现。作为一个定理证明者,给出一个定理的正确结果的必要步骤包括解析(看看语法和语义是否正确)、测试(结果)、解决(问题)、判断(它是否是一个可满足的sat定理)和生成模型(如果这个定理是一个可满足的)。这些模块及其依赖关系如图3所示。此外,脚本也是整个项目的核心模块,没有脚本Z3是无法安装和使用的。

3)、支持层(support):这一层提供了支持核心层操作的基本功能、理论和公式。这一层中的API、math和smt模块都是用于此目的的。此外,doc模块也在这一层,因为它提供API和代码文档,并且支持Z3的实现和使用。

图 3  Z3层次图

此外,还有一个名为test的文件夹,它包含用于测试Z3的测试基础设施和基准。

5、特征分析

特性被定义为软件项目的一个区别特征(例如,性能、可移植性或功能)。当一个系统有许多可供用户选择的选项和功能时,它就被称为功能丰富的系统。Z3的典型特征见下表。

特征

描述

编译

如何构建Z3

API

提供那些编程语言可供用户构建应用

OS

Z3支持的操作系统

用户界面

在哪里可以使用Z3

输入格式

如何输入逻辑公式

求解

当公式满足时,用户如何获取模型及相关变量的解

理论

可用Z3求解的相关理论领域

 

编译器: Windows用户可以使用Visual Studio编译Z3源代码,而其他平台可以使用Makefile(基于g++和clang++)编译Z3作为替代。

API:  Z3是一个低级工具。在需要解决逻辑公式的其他工具的上下文中,最好将其作为组件使用。因此,Z3公开了许多API工具,以方便工具映射到Z3。这些编程api由. net、c++、C、Java、Ocmal和Python组成。操作系统:Z3支持所有主要的操作系统,包括Windows、MacOS X、Linux和FreeBSD,从而促进了Z3的普及。

用户界面:有一个在线工具rise4fun,使用基于SMT 2语言的文本界面显示Z3的主要功能。然而,大多数应用程序使用Z3编程API来访问这些特性。可以通过构建Z3的源代码或通过外部IDE访问这些Z3编程api。

输入格式:与上述用户界面对应,需要满足性检查和求解的逻辑公式可以用SMT 2.0语言或Z3 API输入(参见示例)。此外,还可以将本机文本输入Z3。

解决方案生成:用户可以测试某个理论是否可以满足,例如,当使用在线工具rise4fun时,可以通过命令check-sat进行测试。此外,用户可以选择是否为该模型生成一个可能的解决方案,然后在使用rise4fun时由命令get-model来完成。

理论: Z3的本质是检验逻辑公式对一个或多个理论的可满足性。用户可以检查可满足性,并得到Z3支持的任何理论的模型。

从用户的角度出发,是在线或本地使用Z3的选择。当在线使用Z3时,和所使用的操作系统没有相关性。但是,如果Z3在本地运行,用户必须选择是使用预构建的二进制版本(可以选择使用外部IDE),还是调用API。Z3可以用Visual Studio或Makefile构建。

虽然Z3本身主要是用c++编写的,但它在src/api/目录中以不同的编程语言为更广泛的用户提供了多个api。例如,它为c++用户提供了一个头文件z3++.h。此外,还有一个软件包com.microsoft。用于Java用户的z3。当使用在线版本Z3时,用户只能使用该网站支持的解析器,例如,rise4fun的Z3只支持SMT-LIB 2.0标准。在本地运行时,用户通常可以有更广泛的输入格式选择。Z3理解一组默认的文件扩展名,并在目录src/parsers/中调用正确的解析器来解析它。

6、C++接口

 Z3 -Visual Studio相关环境配置

1)、生成库文件:

(1)、在Cmake中分别选择源代码文件夹,及生成的库文件的目录位置

(2)、分别点击configure,generate按钮

图 4 编译Z3源文件

2)启动visual studio,创建新的项目

图 5 创建新项目

图 6

3)、在项目中添加Z3的相关文件

(1)、在项目中添加三个文件夹,分别为include、lib、bin。

(2)、将Z3中src/api、src/api/C++中的相关头文件拷贝到项目文件的include文件夹中,从Z3编译后的文件夹built/debug中,分别将libz3.lib,libz3.dll拷贝到项目文件的lib、bin文件夹中。

图 7

图 8

图 9 头文件及依赖

4)、配置项目

(1)、在项目属性--->VC++目录---->包含目录 中载入项目中include文件夹路径

(2)、在项目属性--->VC++目录---->库目录 中载入项目中lib文件夹路径

(3)、在项目属性---->调试 --->环境 设置 PATH= 项目下bin文件夹路径(也可将动态库文件拷贝至sytem32下)

图 10 项目配置头文件及lib库

图 11 动态库路径配置

5)、演示示例代码

c++接口类之间的继承关系及和Z3中的对应

图 13 C++接口对应Z3内部模块

7、Z3中的优化计算(opt)

1)、对Z3中优化模块的实测

图 14 z3原始样例

在该示例中,根据变量,x,y都约束在自然数内的一个集合中。 x+y的值小于等于11。求x,y极大值的帕累托(pareto)前沿

  在示例中,将变量x,y的取值范围扩大到整数内的某个区间,继续求解x,y极大值时的pareto前沿。发现仍然可解。

 图 15

约束优化

 在自然数集上的某个集合中最优,可解。。

图 16 

在整数范围某个约束区间,最优可解。。。

图 17

在有理数的某个区域非线性求最优值,没有返回结果。。。

图 18

但是在有理数某个区域的线性极值可解。。。

19

当x,y在实数的某个区域内取值的时候,程序均不能执行。

优化资料查询

Z3优化器不能真正处理非线性算法。(在这种情况下,非线性意味着要乘/除两个符号量。乘以/除以常数应该没问题。在这些情况下,诀窍是做一个迭代循环。将断言放入其中,然后迭代以获得“更好”的值,只要满足约束。当然,这并不能保证收敛,所以必须在某个时候“终止”循环。

  

example:

from z3 import *

s = Solver()

Power = Real ('Power')

s.add (Power >= 0);

s.add (Power <= 4000)

Mass = Real ('Mass')

s.add (Mass >= 1000);

s.add (Mass <= 2000);

Speed = Real ('Speed');

s.add (Speed == Power/Mass);

i = 1

m = None

while s.check() == sat:

  m = s.model ()

  print ("Iteration %d: " % i),

  print m[Speed]

  s.add (Speed > m[Speed])

  i = i+1

print "Final model: "

print m

 

 

 

 

参考:

1. Z3 wiki, https://github.com/Z3Prover/z3/wiki/Contribution-Guidelines.

2. De Moura L, Bjørner N. Generalized, efficient array decision procedures[C]//Formal Methods in Computer-Aided Design, 2009. FMCAD 2009. IEEE, 2009: 45-52.

3. Bjørner N, Phan A D. vZ-Maximal Satisfaction with Z3[C]//SCSS. 2014: 1-9.

4. Blog by Georgios Gousios, http://www.gousios.gr/blog/How-do-project-owners-use-pull-requests-on-Github/.

5. De Moura L, Bjørner N. Z3: An efficient SMT solver[M]//Tools and Algorithms for the Construction and Analysis of Systems. Springer Berlin Heidelberg, 2008: 337-340.

6.https://stackoverflow.com/questions/49160039/optimizing-a-multiplication-and-division/49180970#49180970

7.https://stackoverflow.com/questions/13898175/how-does-z3-handle-non-linear-integer-arithmetic?noredirect=1

 

  • 10
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值