z3学习笔记(有空继续整理)

一、基本语法

Declare-const: 声明给定类型(type/ sort)的常量

declare-fun:声明一个函数

(declare-fun f (Int Bool) Int):声明一个接收整型和布尔型两个参数的函数,返回int

(define-fun a () Int [val]):是解释。此处表明a的值是val

(define-fun conjecture () Bool

         (=> (and (=> p q) (=> q r))

                   (=> p r)))

(assert (not conjecture))  此处的define-fun是起到把后面bool表达式定义一个别名的作用

Reset:重置清空所有声明和断言

Simplify:简化表达式

Define-sort:给sort类型的表达式定义一个别名

Declare-sort:声明一种未解释的类型A

(declare-sort A)

(declare-const x A)  声明A类型的常量x

 

 

SMT公式的基本构建块我就是常量和函数,而常量实际就是没有参数的函数,所以其所有东西都可以看成一个函数。

(Declare-fun a () int)  等价于 declare-const b int<后者是前者的语法糖>

典型的一阶逻辑中,函数都没有副作用,都是定义在输入值上的,所以没有参数的函数实际就是常量

纯一阶逻辑中的函数和常量符号是未解释的或者说自由的,即没有先验解释附加之上。所以+号不一定代表加法,任何和其兼容的都可以

 

; defining my own division operator where x/0.0 == 0.0 for every x.

(define-fun mydiv ((x Real) (y Real)) Real

  (if (not (= y 0.0))

      (/ x y)

      0.0))

 

 

二、 位向量

现代CPU和主流的编程语言都是基于固定大小的位向量实现的算法。位向量理论允许对无符号/有符号两类算术的语义进行精确建模。

 

位向量常量可能是二进制、十进制和十六进制。二进制格式的位向量#b010大小为3,十六进制格式位向量#x0a0大小是12。必须为十进制格式的位向量字面量指定大小,因为同一大小的十进制数用不同进制表示,位数可能不同,如下示例:

(display #b0100)  //4

(display (_ bv20 8)) //大小为8,数值为20的十进制数,表示为是#x14

(display (_ bv20 7)) //大小为7,数值为20的十进制数,表示为是#b0010100

(display #b0100)  (_bv4 4)

操作包括:加减乘除,模、求余、左右移(有无符号)、与或非、大小等于

数组:

(Select a i)返回数组a中处于位置i的数据;

(store a i v)返回位置i处值为v的数组a

(declare-const a1 (Array Int Int)):声明int类型的数组

 

将所有索引映射到某个固定值的数组可以在Z3中使用const构造来指定。它从数组的范围类型中获取一个值,然后创建一个数组。Z3不能仅通过检查实参类型来推断const构造函数必须返回哪种类型的数组。因此,必须使用限定标识符(如const(数组T1 T2))。下面的示例定义了一个只包含1的常量数组。

(declare-const all1 (Array Int Int))

(declare-const a Int)

(declare-const i Int)

(assert (= all1 ((as const (Array Int Int)) 1))) //all1数组中所有数的值为1

(assert (= a (select all1 i)))   //SAT 

Array的解释特别像函数的解释,都是 用define-fun的方式

 

 

三、 Tatics

Tatics是一系列z3内置的函数结合而成的,可以通过apply命令将多个内置的tatics结合在一起(比如simplify和solve-eqs)。前者用于简化表达式,后者采用高斯消去法来消去变量求解方程。

(apply (then simplify solve-eqs)) //连接器them将simplify应用于输入目标,然后solver-eqs简化simplify产生的每个子公式中的多余变量

split-clause:将约束分为多个子约束

(then t s) applies t to the input goal and s to every subgoal produced by t.

(par-then t s) applies t to the input goal and s to every subgoal produced by t in parallel.

(or-else t s) first applies t to the given goal, if it fails then returns the result of s applied to the given goal.

(par-or t s) applies t and s in parallel until one of them succeed. The tractic fails if t and s fails

(repeat t) Keep applying the given tactic until no subgoal is modified by it.

(repeat t n) Keep applying the given tactic until no subgoal is modified by it, or the num

ber of iterations is greater than n.

Check

 

 

-sat-using类似于check-sat,但其不利用z3自带的solver而是用tatics里提供的tatic

 

四、Sequence

本节描述Z3对字符串、序列和正则表达式的处理。

Z3仅使用一个不完整的启发式求解器解决字符串等式(尽管存在完整的过程),长度和序列(以及正则表达式)的完整组合无论如何都是不可决定的。

string是变量中内在的名字 (declare a String)

(assert (= (str.++ b a) (str.++ "abc" b)))//是否存在连接到“ abc”和后跟b的字符串a和b。

字符串操作:

 

五、Optimization

该功能使用户可以直接使用Z3制定目标函数。 引擎盖下有用于解决SMT公式,MaxSMT及其组合的线性优化问题的方法组合。

算术优化》》

(Maximize t):调用check-sat同时产生值最大的解释

(minimize t): 调用check-sat同时产生值最小的解释

无界对象:z3中的最大可以是无穷(00),最小可以使负无穷(-00)

 

六、题外话

1、若使用z3实现复杂的功能还是使用python或者Haskell, 这些语言提供了对z3更强大的API;

2、虽说C/C++可能执行的比python快,但C++使用z3有很大的局限性,也比较麻烦,所有类型都要声明。

3、当然可以选择C++与python结合,python写约束求解的脚本,C++调用python脚本