mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +00:00 
			
		
		
		
	three smt2 examples added and one python example updated (#5690)
This commit is contained in:
		
							parent
							
								
									71cbb160d2
								
							
						
					
					
						commit
						cbdd7b0696
					
				
					 4 changed files with 445 additions and 23 deletions
				
			
		
							
								
								
									
										168
									
								
								examples/SMT-LIB2/bounded model checking/bubble_sort.smt2
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								examples/SMT-LIB2/bounded model checking/bubble_sort.smt2
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,168 @@ | ||||||
|  | ;   File name:    bubble_sort.smt2 | ||||||
|  | ;  | ||||||
|  | ;   BUBBLESORT  -  Copyright (c) March, 2021 - Matteo Nicoli | ||||||
|  | ; | ||||||
|  | ;   An example of bounded model checking of the classic bubble sort algorithm. | ||||||
|  | ;   we will copy the array values into a list in order to check whether the  | ||||||
|  | ;   array is ordered or not. That's because: | ||||||
|  | ;       - it's easier to walk recursively through a list | ||||||
|  | ;       - it gives an example of how list and sequences work in Z3 | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ; size of the array | ||||||
|  | (declare-const dim Int) | ||||||
|  | 
 | ||||||
|  | ; arrays declaration | ||||||
|  | (declare-const A0 (Array Int Int)) | ||||||
|  | (declare-const A1 (Array Int Int)) | ||||||
|  | (declare-const A2 (Array Int Int)) | ||||||
|  | (declare-const A3 (Array Int Int)) | ||||||
|  | 
 | ||||||
|  | ; indexes declaration | ||||||
|  | (declare-const i0 Int) | ||||||
|  | (declare-const i1 Int) | ||||||
|  | (declare-const i2 Int) | ||||||
|  | (declare-const i3 Int) | ||||||
|  | 
 | ||||||
|  | (declare-const j0 Int) | ||||||
|  | (declare-const j1 Int) | ||||||
|  | (declare-const j2 Int) | ||||||
|  | (declare-const j3 Int) | ||||||
|  | 
 | ||||||
|  | (declare-const tmp0 Int) | ||||||
|  | (declare-const tmp1 Int) | ||||||
|  | (declare-const tmp2 Int) | ||||||
|  | 
 | ||||||
|  | ; lists declaration (for post condition) | ||||||
|  | (declare-const l0 (List Int)) | ||||||
|  | (declare-const l1 (List Int)) | ||||||
|  | (declare-const l2 (List Int)) | ||||||
|  | (declare-const l3 (List Int)) | ||||||
|  | (declare-const l4 (List Int)) | ||||||
|  | 
 | ||||||
|  | (define-fun init_indexes ((_i Int) (_j Int)) Bool | ||||||
|  |     (and | ||||||
|  |         (= _i 0) | ||||||
|  |         (= _j 0) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | (define-fun inner_loop  | ||||||
|  |                         ( | ||||||
|  |                             (_A0 (Array Int Int)) | ||||||
|  |                             (_A1 (Array Int Int)) | ||||||
|  |                             (tmp Int) | ||||||
|  |                             (_i0 Int) | ||||||
|  |                             (_dim Int) | ||||||
|  |                         ) Bool | ||||||
|  |     (ite | ||||||
|  |         (> (select _A0 _i0) (select _A0 (+ _i0 1))) | ||||||
|  |         (and | ||||||
|  |             (= tmp (select _A0 _i0)) | ||||||
|  |             (= _A1 (store _A0 _i0 (select _A0 (+ _i0 1)))) | ||||||
|  |             (= _A1 (store _A0 (+ _i0 1) tmp)) | ||||||
|  |         ) | ||||||
|  |         (= _A1 _A0) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ; the body of the bubblesort algorithm | ||||||
|  | (define-fun bsort_step  | ||||||
|  |                         ( | ||||||
|  |                             (_A0 (Array Int Int)) | ||||||
|  |                             (_A1 (Array Int Int)) | ||||||
|  |                             (tmp Int) | ||||||
|  |                             (_i0 Int) | ||||||
|  |                             (_j0 Int) | ||||||
|  |                             (_i1 Int) | ||||||
|  |                             (_j1 Int) | ||||||
|  |                             (_dim Int) | ||||||
|  |                         ) Bool | ||||||
|  |     (ite | ||||||
|  |         (< _j0 (- _dim 1)) | ||||||
|  |         (and  | ||||||
|  |             (ite  | ||||||
|  |                 (< _i0 (- _dim 1)) | ||||||
|  |                 (and | ||||||
|  |                     (inner_loop _A0 _A1 tmp _i0 _dim) | ||||||
|  |                     (= _i1 (+ _i0 1)) | ||||||
|  |                 ) | ||||||
|  |                 (= _j1 (+ _j0 1)) | ||||||
|  |             ) | ||||||
|  |             (= _j1 (+ _j0 1)) | ||||||
|  |         ) | ||||||
|  |         (and | ||||||
|  |             (= _j1 (+ _j0 1)) | ||||||
|  |             (= _A1 _A0) | ||||||
|  |         ) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ; the function by which we check whether the list is ordered | ||||||
|  | (define-fun-rec check ((_l (List Int))) Bool | ||||||
|  |     (ite  | ||||||
|  |         (= _l nil) | ||||||
|  |         true | ||||||
|  |         (ite | ||||||
|  |             (not (= (tail _l) nil)) | ||||||
|  |             (and | ||||||
|  |                 (>= (head _l) (head (tail _l))) | ||||||
|  |                 (check (tail _l)) | ||||||
|  |             ) | ||||||
|  |             true | ||||||
|  |         ) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ; sets the size of the array | ||||||
|  | (assert (= dim 4)) | ||||||
|  | 
 | ||||||
|  | ; initialization of the counters | ||||||
|  | (assert (init_indexes i0 j0)) | ||||||
|  | 
 | ||||||
|  | ; the first step of the sorting algorithm | ||||||
|  | (assert (bsort_step A0 A1 tmp0 i0 j0 i1 j1 dim)) | ||||||
|  | (assert (bsort_step A1 A2 tmp1 i1 j1 i2 j2 dim)) | ||||||
|  | (assert (bsort_step A2 A3 tmp2 i2 j2 i3 j3 dim)) | ||||||
|  | 
 | ||||||
|  | ; filling the list for test | ||||||
|  | (assert | ||||||
|  |     (and | ||||||
|  |         (= l0 nil) | ||||||
|  |         (= l1 (insert (select A3 0) l0)) | ||||||
|  |         (= l2 (insert (select A3 1) l1)) | ||||||
|  |         (= l3 (insert (select A3 2) l2)) | ||||||
|  |         (= l4 (insert (select A3 3) l3)) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | (echo "BUBBLE SORT") | ||||||
|  | 
 | ||||||
|  | (push) | ||||||
|  | 
 | ||||||
|  | ; (negated) post-condition | ||||||
|  | (assert (not (check l4))) | ||||||
|  | 
 | ||||||
|  | (echo "Testing the validity of the algorithm; `unsat` expected: ") | ||||||
|  | 
 | ||||||
|  | ; `unsat` expected | ||||||
|  | (check-sat) | ||||||
|  | 
 | ||||||
|  | (echo "---------------------") | ||||||
|  | 
 | ||||||
|  | (pop) | ||||||
|  | 
 | ||||||
|  | ; post-condition | ||||||
|  | (assert (check l4)) | ||||||
|  | 
 | ||||||
|  | (echo "Getting a model; `sat` expected: ") | ||||||
|  | 
 | ||||||
|  | ; `sat` expected | ||||||
|  | (check-sat) | ||||||
|  | 
 | ||||||
|  | (echo "---------------------") | ||||||
|  | 
 | ||||||
|  | (echo "Model: ") | ||||||
|  | (get-value (A3)) | ||||||
|  | (exit) | ||||||
							
								
								
									
										114
									
								
								examples/SMT-LIB2/bounded model checking/loop_unrolling.smt2
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								examples/SMT-LIB2/bounded model checking/loop_unrolling.smt2
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,114 @@ | ||||||
|  | ;   File name:    loop_unrolling.smt2 | ||||||
|  | ;  | ||||||
|  | ;   Copyright (c) March, 2021 - Matteo Nicoli | ||||||
|  | ; | ||||||
|  | ; | ||||||
|  | ;   Let's start considering a simple C program involving an iteration: | ||||||
|  | ;    | ||||||
|  | ;       #define DIM 2 | ||||||
|  | ;        | ||||||
|  | ;       /* uninterpreted functions */ | ||||||
|  | ;       long get_number(); | ||||||
|  | ;       void fill_array(long *A); | ||||||
|  | ;        | ||||||
|  | ;       int main() | ||||||
|  | ;       { | ||||||
|  | ;           long x = get_number(); | ||||||
|  | ;           long A[DIM]; | ||||||
|  | ;           long i = 0; | ||||||
|  | ;           long found = 0;  | ||||||
|  | ;            | ||||||
|  | ;           fill_array(A); | ||||||
|  | ; | ||||||
|  | ;           while(i < DIM) { | ||||||
|  | ;               if(x == A[i])  | ||||||
|  | ;                   found = 1; | ||||||
|  | ;               i++;  | ||||||
|  | ;           } | ||||||
|  | ;       } | ||||||
|  | ; | ||||||
|  | ;   Below, we can see its SSA representation in SMT-LIB2. | ||||||
|  | ;   Our goal is to verify that, at the end of the program, the variable `found` | ||||||
|  | ;   is equal to 1 if, and only if, `x` is an element of the array. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | (declare-const x Int) | ||||||
|  | (declare-const A (Array Int Int)) | ||||||
|  | (declare-const i_0 Int) | ||||||
|  | (declare-const found_0 Int) | ||||||
|  | 
 | ||||||
|  | (declare-const found_1 Int) | ||||||
|  | (declare-const found_2 Int) | ||||||
|  | (declare-const i_1 Int) | ||||||
|  | (declare-const i_2 Int) | ||||||
|  | 
 | ||||||
|  | ; Pre-condition: variables initialization | ||||||
|  | (assert | ||||||
|  |     (and | ||||||
|  |         (= i_0 0) | ||||||
|  |         (= found_0 0) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ; Transition funcion | ||||||
|  | (define-fun body ((f_0 Int) (f Int) (i_0 Int) (i_1 Int)(_A (Array Int Int)) (_x Int)) Bool | ||||||
|  |     (and | ||||||
|  |         (= f (ite (= _x (select _A i_0)) 1 f_0)) | ||||||
|  |         (= i_1 (+ i_0 1)) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ; Post-condition function | ||||||
|  | (define-fun post ((_f Int) (_i Int) (_x Int) (_A (Array Int Int))) Bool | ||||||
|  |     (= | ||||||
|  |         (= _f 1) | ||||||
|  |         (= _x (select _A _i)) | ||||||
|  |     )    | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ; Transition function is called DIM times: | ||||||
|  | ; for practical reasons, we are considering here DIM = 2 | ||||||
|  | (assert (body found_0 found_1 i_0 i_1 A x)) | ||||||
|  | (assert (body found_1 found_2 i_1 i_2 A x)) | ||||||
|  | 
 | ||||||
|  | (push) | ||||||
|  | 
 | ||||||
|  | (echo "Bounded model checking with loop unrolling") | ||||||
|  | 
 | ||||||
|  | (echo "------------------------------------------") | ||||||
|  | 
 | ||||||
|  | ; Post-condition (negated) is called DIM times | ||||||
|  | (assert | ||||||
|  |     (not | ||||||
|  |         (or | ||||||
|  |             (post found_2 i_0 x A)       | ||||||
|  |             (post found_2 i_1 x A) | ||||||
|  |         ) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | (echo "Testing the validity of the post-condition: `unsat expected`") | ||||||
|  | 
 | ||||||
|  | ; `unsat` expected | ||||||
|  | (check-sat) | ||||||
|  | 
 | ||||||
|  | (pop) | ||||||
|  | 
 | ||||||
|  | ; Post-condition (called DIM times) | ||||||
|  | (assert | ||||||
|  |     (or | ||||||
|  |         (post found_2 i_0 x A)       | ||||||
|  |         (post found_2 i_1 x A) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | (echo "Getting a model; `sat` expected: ") | ||||||
|  | 
 | ||||||
|  | ; `sat` expected | ||||||
|  | (check-sat) | ||||||
|  | 
 | ||||||
|  | (echo "------------------------------------------") | ||||||
|  | 
 | ||||||
|  | (echo "Model: ") | ||||||
|  | (get-value (x A found_2)) | ||||||
|  | (exit) | ||||||
|  | @ -0,0 +1,116 @@ | ||||||
|  | ;   File name:    loop_unrolling_bitvec.smt2 | ||||||
|  | ;  | ||||||
|  | ;   Copyright (c) March, 2021 - Matteo Nicoli | ||||||
|  | ; | ||||||
|  | ; | ||||||
|  | ;   Let's start considering a simple C program involving an iteration: | ||||||
|  | ;    | ||||||
|  | ;       #define DIM 2 | ||||||
|  | ;        | ||||||
|  | ;       /* uninterpreted functions */ | ||||||
|  | ;       long get_number(); | ||||||
|  | ;       void fill_array(long *A); | ||||||
|  | ;        | ||||||
|  | ;       int main() | ||||||
|  | ;       { | ||||||
|  | ;           long x = get_number(); | ||||||
|  | ;           long A[DIM]; | ||||||
|  | ;           long i = 0; | ||||||
|  | ;           long found = 0;  | ||||||
|  | ;            | ||||||
|  | ;           fill_array(A); | ||||||
|  | ; | ||||||
|  | ;           while(i < DIM) { | ||||||
|  | ;               if(x == A[i])  | ||||||
|  | ;                   found = 1; | ||||||
|  | ;               i++;  | ||||||
|  | ;           } | ||||||
|  | ;       } | ||||||
|  | ; | ||||||
|  | ;   Below, we can see its SSA representation in SMT-LIB2. | ||||||
|  | ;   Our goal is to verify that, at the end of the program, the variable `found` | ||||||
|  | ;   is equal to 1 if, and only if, `x` is an element of the array. | ||||||
|  | ;   We define our custom sort `IntValue` that represents a 32-bit integer value. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | (define-sort IntValue () (_ BitVec 32)) | ||||||
|  | (declare-const x IntValue) | ||||||
|  | (declare-const A (Array IntValue IntValue)) | ||||||
|  | (declare-const i_0 IntValue) | ||||||
|  | (declare-const found_0 IntValue) | ||||||
|  | 
 | ||||||
|  | (declare-const found_1 IntValue) | ||||||
|  | (declare-const found_2 IntValue) | ||||||
|  | (declare-const i_1 IntValue) | ||||||
|  | (declare-const i_2 IntValue) | ||||||
|  | 
 | ||||||
|  | ; Pre-condition: variables initialization | ||||||
|  | (assert | ||||||
|  |     (and | ||||||
|  |         (= i_0 #x00000000) | ||||||
|  |         (= found_0 #x00000000) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ; Transition funcion | ||||||
|  | (define-fun body ((f_0 IntValue) (f IntValue) (i_0 IntValue) (i_1 IntValue)(_A (Array IntValue IntValue)) (_x IntValue)) Bool | ||||||
|  |     (and | ||||||
|  |         (= f (ite (= _x (select _A i_0)) #x00000001 f_0)) | ||||||
|  |         (= i_1 (bvadd i_0 #x00000001)) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ; Post-condition function | ||||||
|  | (define-fun post ((_f IntValue) (_i IntValue) (_x IntValue) (_A (Array IntValue IntValue))) Bool | ||||||
|  |     (= | ||||||
|  |         (= _f #x00000001) | ||||||
|  |         (= _x (select _A _i)) | ||||||
|  |     )    | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | ; Transition function is called DIM times: | ||||||
|  | ; for practical reasons, we are considering here DIM = 2 | ||||||
|  | (assert (body found_0 found_1 i_0 i_1 A x)) | ||||||
|  | (assert (body found_1 found_2 i_1 i_2 A x)) | ||||||
|  | 
 | ||||||
|  | (push) | ||||||
|  | 
 | ||||||
|  | (echo "Bounded model checking with loop unrolling") | ||||||
|  | 
 | ||||||
|  | (echo "------------------------------------------") | ||||||
|  | 
 | ||||||
|  | ; Post-condition (negated) is called DIM times | ||||||
|  | (assert | ||||||
|  |     (not | ||||||
|  |         (or | ||||||
|  |             (post found_2 i_0 x A)       | ||||||
|  |             (post found_2 i_1 x A) | ||||||
|  |         ) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | (echo "Testing the validity of the post-condition: `unsat expected`") | ||||||
|  | 
 | ||||||
|  | ; `unsat` expected | ||||||
|  | (check-sat) | ||||||
|  | 
 | ||||||
|  | (pop) | ||||||
|  | 
 | ||||||
|  | ; Post-condition (called DIM times) | ||||||
|  | (assert | ||||||
|  |     (or | ||||||
|  |         (post found_2 i_0 x A)       | ||||||
|  |         (post found_2 i_1 x A) | ||||||
|  |     ) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | (echo "Getting a model; `sat` expected: ") | ||||||
|  | 
 | ||||||
|  | ; `sat` expected | ||||||
|  | (check-sat) | ||||||
|  | 
 | ||||||
|  | (echo "------------------------------------------") | ||||||
|  | 
 | ||||||
|  | (echo "Model: ") | ||||||
|  | (get-value (x A found_2)) | ||||||
|  | (exit) | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| # BUBBLESORT  -  Copyright (c) June, 2020 - Matteo Nicoli | #    File name:    bubble_sort.py | ||||||
|  | # | ||||||
|  | #    BUBBLESORT  -  Copyright (c) June, 2020 - Matteo Nicoli | ||||||
| 
 | 
 | ||||||
| from z3 import Solver, Int, Array, IntSort, And, Not, If, Select, Store, sat | from z3 import Solver, Int, Array, IntSort, And, Not, If, Select, Store, sat | ||||||
| 
 | 
 | ||||||
|  | @ -36,34 +38,56 @@ def check(variables, Ar, dim) : | ||||||
|         yield variables[e] == Select(Ar,e) |         yield variables[e] == Select(Ar,e) | ||||||
| 
 | 
 | ||||||
| def mk_post_condition(values) : | def mk_post_condition(values) : | ||||||
|     condition = [] |     condition = [v1 <= v2 for v1,v2 in zip(values,values[1:])] | ||||||
|     for v1,v2 in zip(values,values[1:]) : |  | ||||||
|         condition.append(v1 <= v2) |  | ||||||
|     return And(*condition) |     return And(*condition) | ||||||
| 
 | 
 | ||||||
| dim = int(input("size of the array: ")) |  | ||||||
| 
 | 
 | ||||||
| i = [Int(f"i_{x}") for x in range(dim + 1)] | def main() : | ||||||
| j = [Int(f"j_{x}") for x in range(dim + 1)] |     dim = int(input("size of the array: ")) | ||||||
| A = [Array(f"A_{x}",IntSort(),IntSort()) for x in range(dim + 1)] |  | ||||||
| tmp = [Int(f"tmp_{x}") for x in range(dim)] |  | ||||||
| 
 | 
 | ||||||
| s = Solver() |     i = [Int(f"i_{x}") for x in range(dim + 1)] | ||||||
|  |     j = [Int(f"j_{x}") for x in range(dim + 1)] | ||||||
|  |     A = [Array(f"A_{x}",IntSort(),IntSort()) for x in range(dim + 1)] | ||||||
|  |     tmp = [Int(f"tmp_{x}") for x in range(dim)] | ||||||
| 
 | 
 | ||||||
| init_condition = init(i[0],j[0]) |     s = Solver() | ||||||
| s.add(init_condition) |  | ||||||
| 
 | 
 | ||||||
| tran_condition= mk_tran_condition(A, i, j, tmp, dim) |     init_condition = init(i[0],j[0]) | ||||||
| s.add(And(*tran_condition)) |     s.add(init_condition) | ||||||
| 
 | 
 | ||||||
| values = [Int(f"n_{x}") for x in range(dim)] |     tran_condition = mk_tran_condition(A, i, j, tmp, dim) | ||||||
| init_check_condition = check(values,A[-1],dim) |     s.add(And(*tran_condition)) | ||||||
| s.add(And(*init_check_condition)) |  | ||||||
| 
 | 
 | ||||||
| post_condition = mk_post_condition(values) |     values = [Int(f"n_{x}") for x in range(dim)] | ||||||
| s.add(Not(post_condition)) |     init_check_condition = check(values,A[-1],dim) | ||||||
|  |     s.add(And(*init_check_condition)) | ||||||
| 
 | 
 | ||||||
| if s.check() == sat : |     post_condition = mk_post_condition(values) | ||||||
|     print(f"counterexample:\n{s.model()}") | 
 | ||||||
| else : |     print("Bubble sort") | ||||||
|     print("valid") |     print("---------------------") | ||||||
|  | 
 | ||||||
|  |     s.push() | ||||||
|  |     s.add(Not(post_condition)) | ||||||
|  | 
 | ||||||
|  |     print("Testing the validity of the algorithm; `valid expected`:") | ||||||
|  | 
 | ||||||
|  |     if s.check() == sat : | ||||||
|  |         print(f"counterexample:\n{s.model()}") | ||||||
|  |     else : | ||||||
|  |         print("valid") | ||||||
|  | 
 | ||||||
|  |     print("---------------------") | ||||||
|  | 
 | ||||||
|  |     s.pop() | ||||||
|  | 
 | ||||||
|  |     s.add(post_condition) | ||||||
|  |     print("Getting a model...") | ||||||
|  |     print("Model:") | ||||||
|  | 
 | ||||||
|  |     if s.check() == sat : | ||||||
|  |         print(s.model()) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__" : | ||||||
|  |     main() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue