Introduction to Z3 Bow-Yaw Wang Institute of Information Science Academia Sinica, Taiwan December 19, 2017 Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 1 / 26
Outline 1 Introduction to Z3 Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 2 / 26
SMT Solvers I SAT solvers have been used in hardware verification. Propositional logic suffices to model digital circuits. Can we use SAT solvers to verify programs? Not really. In general, we need predicate logic with mathematical vocabulary. The problem is undecidable. However, there are tools that can help us solve simple cases. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 3 / 26
SMT Solvers II Satisfiability Modulo Theories (SMT) solvers are SAT solvers extended with various theories. For instance, theories of linear arithmetic, uninterpreted functions, etc. Such theories allow us to verify properties about programs. The basic idea is not complicated. In addition to propositional atoms, we introduce predicate symbols as new propositional atoms. Efficient SAT algorithms can still be used on top of these propositional atoms. In fact, many SMT solvers are based on SAT solvers. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 4 / 26
SMT Solvers III Similar to SAT solvers, there is a competition for SMT solvers. Recent SMT solvers thus adopt the SMT-LIB input format. In the following, we will introduce the SMT solver Z3. Z3 is developed at Microsoft Research. Source codes are available. We will use its Python interface in class. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 5 / 26
Using Z3 in Python from z3 import # i mport Z3 l i b r a r y s = S o l v e r ( ) # c r e a t e an SMT s o l v e r s p r i n t s. check ( ) # check s a t i s f i a b i l i t y p r i n t s. model ( ) # o b t a i n a model We first import Z3 Python library. Remember to add your Z3 Python path to PYTHONPATH. The Z3 solver checks whether the conjunction of formulae is satisfiable. When there is no formula, the degenerated conjunction is true. The empty model suffices to satisfy the degenerated conjunction. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 6 / 26
Equational Theory I from z3 import s = S o l v e r ( ) m = I n t ( M ) c r e a t e the i n t e g e r c o n s t a n t M n = I n t ( N ) c r e a t e the i n t e g e r c o n s t a n t N s. add (m == n ) add the f o r m u l a M = N p r i n t s. check ( ) i f s. check ( ) == s a t : p r i n t s. model ( ) The Python variable m contains a Z3 Boolean constant M. The Python variable n contains a Z3 Boolean constant N. m == n is the Z3 formula for M = N. Clearly, M = N is satisfiable. The model [ N = 0, M = 0 ] is returned. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 7 / 26
Boolean Theory I from z3 import s = S o l v e r ( ) x = Bool ( X ) # c r e a t e the Boolean c o n s t a n t X s. add ( Not ( x ) ) # add the f o r m u l a X p r i n t s. check ( ) i f s. check ( ) == s a t : p r i n t s. model ( ) Not(x) is the Z3 formula for X. The formula X is satisfiable. The model [ X = False ] is returned. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 8 / 26
Boolean Theory II from z3 import s = S o l v e r ( ) x = Bool ( X ) s. add ( Not ( x ) ) s. add ( x ) # add the f o r m u l a X p r i n t s. check ( ) i f s. check ( ) == s a t : p r i n t s. model ( ) The formulae X and X is not satisfiable. What if we ask Z3 to give a model? Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 9 / 26
Boolean Theory III Boolean sort: BoolSort() Boolean values: BoolVal(False), BoolVal(True) False and True are Python Boolean values Constant declaration: Bool(name) or Bools(names) Unary operator: Not (negation) Binary operators: Or (disjunction), And (conjunction), Xor (exclusive or), Implies (implication) Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 10 / 26
Boolean Theory IV 3 P i g e o n s to l i v e i n 2 h o l e s from z3 import s = S o l v e r ( ) p i g e o n s = [ B o o l V e c t o r ( P, 2 ), B o o l V e c t o r ( Q, 2 ), B o o l V e c t o r ( R, 2) ] each p i g e o n must l i v e i n one h o l e s. add ( Or ( p i g e o n s [ 0 ] [ 0 ], p i g e o n s [ 0 ] [ 1 ] ) ) s. add ( Or ( p i g e o n s [ 1 ] [ 0 ], p i g e o n s [ 1 ] [ 1 ] ) ) s. add ( Or ( p i g e o n s [ 2 ] [ 0 ], p i g e o n s [ 2 ] [ 1 ] ) ) a h o l e r e c e i v e s a t most one p i g e o n s. add ( And ( Or ( Not ( p i g e o n s [ 0 ] [ 0 ] ), Not ( p i g e o n s [ 1 ] [ 0 ] ) ), Or ( Not ( p i g e o n s [ 0 ] [ 0 ] ), Not ( p i g e o n s [ 2 ] [ 0 ] ) ), Or ( Not ( p i g e o n s [ 1 ] [ 0 ] ), Not ( p i g e o n s [ 2 ] [ 0 ] ) ) ) ) s. add ( And ( Or ( Not ( p i g e o n s [ 0 ] [ 1 ] ), Not ( p i g e o n s [ 1 ] [ 1 ] ) ), Or ( Not ( p i g e o n s [ 0 ] [ 1 ] ), Not ( p i g e o n s [ 2 ] [ 1 ] ) ), Or ( Not ( p i g e o n s [ 1 ] [ 1 ] ), Not ( p i g e o n s [ 2 ] [ 1 ] ) ) ) ) p r i n t s. check ( ) Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 11 / 26
Arithmetic Theory I from z3 import s = S o l v e r ( ) i = I n t ( I ) x = Real ( X ) s. add ( i < x ) s. add ( x < i + 1) p r i n t s. check ( ) i f s. check ( ) == s a t : p r i n t s. model ( ) Z3 supports integer and real numbers. Int( I ) declares a Z3 integer constant named I. Real( X ) declares a Z3 real constant named X. We can use Python arithmetic expressions as Z3. The Z3 Python module overloads arithmetic functions. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 12 / 26
Arithmetic Theory II Integer sort: IntSort(), RealSort() Integer values: IntVal(value), RealVal(value) Constant declaration: Int(name) or Real(name) Binary operators: +,,, /, and %. Binary relations: <, <=, >, and >=. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 13 / 26
Bitvector Theory I from z3 import s = S o l v e r ( ) # c r e a t e a 32 b i t b i t v e c t o r c o n s t a n t X x = BitVec ( x, 16) s. add ( x > 0) s. add ( x & ( x 1) == 0) # a t r i c k to f i n d a l l s o l u t i o n s w h i l e s. check ( ) == s a t : p r i n t s. model ( ) [ x ] s. add ( x!= s. model ( ) [ x ] ) Z3 supports bit-vectors. BitVec( x, 16) declares a 16-bit bit-vector constant named x. Again, Python bit-vector expressions are overloaded to construct Z3 bit-vector expressions. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 14 / 26
Bitvector Theory II Sort declaration: BitVecSort(width) Constant declaration: BitVec(name,width) Binary operators: & (bitwise-and), (bitwise-or), (bitwise-invert), ˆ (exclusive-or), +,,, /, %, >> (right-shift), and << (left-shift). Binary relations: <, <=, >, and >=. Additional functions: Concat(bitvecs) represents the concatenation of a list of bit-vectors. Extract(high, low, bitvec) represents a sub bit-vector of bitvec. RotateLeft(bitvec, r) represents the left rotation of bitvec. RotateRight(bitvec, r) represents the right rotation of bitvec. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 15 / 26
Theory of Uninterpreted Functions I from z3 import # d e c l a r e an unknown s o r t o f u n i v e r s e U = D e c l a r e S o r t ( U ) # a and b a r e c o n s t a n t s o f s o r t U a, b = Const ( a, U), Const ( b, U) # f i s an u n t e r p r e t e d f u n c t i o n from U U to U f = F u n c t i o n ( f, U, U, U) s = S o l v e r ( ) s. add ( f ( a, b ) == a ) p r i n t s. check ( ) s. add ( f ( f ( a, b ), b )!= a ) p r i n t s. check ( ) Z3 allows uninterpreted functions. An uninterpreted function need not be fully specified. If a b, f (a, a) can take any value in U. However, Z3 deduces f (f (a, b), b) = a from f (a, b) = a. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 16 / 26
Theory of Uninterpreted Functions II Sort declaration: DeclareSort(name) Constant declaration: Const(name, sort) Uninterpreted function declaration: Function(name, domainsorts, rangesort) Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 17 / 26
Save and Restore Context from z3 import s = S o l v e r ( ) x = Bool ( X ) s. add ( Not ( x ) ) p r i n t s. check ( ) i f s. check ( ) == s a t : p r i n t s. model ( ) s. push ( ) # s a v e t h e c u r r e n t c o n t e x t s. add ( x == BoolVal ( True ) ) p r i n t s. check ( ) i f s. check ( ) == s a t : p r i n t s. model ( ) s. pop ( ) # r e s t o r e t h e s a v e d c o n t e x t p r i n t s. check ( ) i f s. check ( ) == s a t : p r i n t s. model ( ) How do you simulate push and pop in MiniSAT? Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 18 / 26
McCarthy91 i n t mccarthy91 ( i n t n ) { i n t c ; i n t r e t ; r e t = n ; c = 1 ; w h i l e ( c > 0) { i f ( r e t > 100) { r e t = r e t 1 0 ; c ; } e l s e { r e t = r e t + 1 1 ; c++; } } r e t u r n r e t ; } For n 100, mccarthy91(n) is 91. For n > 100, mccarthy91(n) is n 10. Let us try to find an invariant to prove it! Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 19 / 26
Invariant for McCarthy 91 I First, we will set up pre- and post-conditions. Immediately before entering the loop, we have ret = n c = 1. from z3 import n = I n t ( n ) r e t = I n t ( r e t ) c = I n t ( c ) s o l v e r = S o l v e r ( ) This is represented by And(ret == n, c == 1). Immediately after leaving the loop, we want to show (n 100 ret = 91) (n > 100 ret = n 10). This is represented by And(Implies(n <= 100, ret == 91), Implies(n > 100, ret == n 10)). Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 20 / 26
Invariant for McCarthy 91 II Any invariant η must have AR ret = n c = 1 η; AR η (c > 0) [(n 100 ret = 91) (n > 100 ret = n 10)]; and finally, ( η c > 0 ) if (ret > 100) { ret = ret 10; c ; } else { ret = ret + 11; c + +; } ( η ) Suppose we come up with an η and express it in Z3 Python. How do we use Z3 to check them? Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 21 / 26
Invariant for McCarthy 91 III The first two requirements are similar. They are of the form AR φ ψ. It is equivalent to φ ψ is not satisfiable. We use the following Python code: d e f c h e c k i m p l i e s ( phi, p s i ) : s o l v e r. push ( ) f = And ( phi, Not ( p s i ) ) s o l v e r. add ( f ) r e s u l t = s o l v e r. check ( ) s o l v e r. pop ( ) r e t u r n r e s u l t!= s a t Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 22 / 26
Invariant for McCarthy 91 IV For the last requirement, note that ret > 100 η[c c 1][ret ret 10] ( (ret > 100) η[c c + 1][ret ret + 11] if (ret > 100) { ( η[c c 1][ret ret 10] ) ret = ret 10; ( η[c c 1] ) c ; ( η ) } else { ( η[c c + 1][ret ret + 11] ) ret = ret + 11; ( η[c c + 1] ) c + +; ( η ) } ( η ) ) Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 23 / 26
Invariant for McCarthy 91 V Hence it suffices to check AR η c > 0 ( ret > 100 η[c c 1][ret ret 10] (ret > 100) η[c c + 1][ret ret + 11] ) When we guess an η, we can check the last requirement after performing 4 substitutions. Luckily, Z3 Python can do substitutions for us. d e f r e q u i r e m e n t 3 ( e t a ) : b t r u e = I m p l i e s ( r e t > 100, s u b s t i t u t e ( s u b s t i t u t e ( eta, ( c, c 1 ) ), ( r e t, r e t 1 0 ) ) ) b f a l s e = I m p l i e s ( Not ( r e t > 1 0 0 ), s u b s t i t u t e ( s u b s t i t u t e ( eta, ( c, c + 1 ) ), ( r e t, r e t + 1 1 ) ) ) r e t u r n c h e c k i m p l i e s ( And ( Not ( c > 0 ), e t a ), And ( b t r u e, b f a l s e ) ) Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 24 / 26
Invariant for McCarthy 91 VI We have almost everything except η. Here is what we will do: Guess η and express it in Z3 Python. Use Z3 Python to check the three requirements on η. If all three requirements pass, we are done. Otherwise, guess another η and repeat. Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 25 / 26
Invariant for McCarthy 91 VII It may be too hard to guess η for all input n. We hence consider two sub-problems: ( n > 100 )ret = mccarthy91(n)( ret = n 10 ); and ( n 100 )ret = mccarthy91(n)( ret = 91 ) Try to find an invariant for each sub-problem. Then combine two sub-invariants into one for the main problem. Have fun! Bow-Yaw Wang (Academia Sinica) Introduction to Z3 December 19, 2017 26 / 26