2 (* Program verification examples from the book "Software Foundations"
3 http://www.cis.upenn.edu/~bcpierce/sf/
5 Note: we are using int (not nat), so we need extra precondition (e.g. x >= 0)
6 Note: we are also proving termination
14 (* Example: Slow Subtraction *)
16 let slow_subtraction (x: ref int) (z: ref int)
18 ensures { !z = old !z - old !x }
20 invariant { 0 <= !x /\ !z - !x = old (!z - !x) } variant { !x }
25 (* Example: Reduce to Zero *)
27 let reduce_to_zero (x: ref int)
28 requires { !x >= 0 } ensures { !x = 0 }
29 = while !x <> 0 do invariant { !x >= 0 } variant { !x } x := !x - 1 done
31 (* Exercise: Slow Addition *)
33 let slow_addition (x: ref int) (z: ref int)
34 requires { !x >= 0 } ensures { !z = old !z + old !x }
36 invariant { 0 <= !x /\ !z + !x = old (!z + !x) } variant { !x }
45 | even_odd : forall x:int. even x -> even (x+2)
47 lemma even_noneg: forall x:int. even x -> x >= 0
49 lemma even_not_odd : forall x:int. even x -> even (x+1) -> false
51 let parity (x: ref int) (y: ref int)
52 requires { !x >= 0 } ensures { !y=0 <-> even (old !x) }
55 invariant { 0 <= !x /\ (!y=0 /\ even ((old !x) - !x) \/
56 !y=1 /\ even ((old !x) - !x + 1)) }
62 (* Example: Finding Square Roots *)
64 let sqrt (x: ref int) (z: ref int)
66 ensures { !z * !z <= !x < (!z + 1) * (!z + 1) }
68 while (!z + 1) * (!z + 1) <= !x do
69 invariant { 0 <= !z /\ !z * !z <= !x } variant { !x - !z * !z }
73 (* Exercise: Factorial *)
75 function fact int : int
76 axiom fact_0 : fact 0 = 1
77 axiom fact_n : forall n:int. 0 < n -> fact n = n * fact (n-1)
79 let factorial (x: ref int) (y: ref int) (z: ref int)
80 requires { !x >= 0 } ensures { !y = fact !x }
84 invariant { 0 <= !z /\ !y * fact !z = fact !x } variant { !z }
100 function sum (l : list int) : int = match l with
102 | Cons x r -> x + sum r
105 val head (l:list 'a) : 'a
106 requires { l<>Nil } ensures { Some result = hd l }
108 val tail (l:list 'a) : list 'a
109 requires { l<>Nil } ensures { Some result = tl l }
111 let list_sum (l: ref (list int)) (y: ref int)
112 ensures { !y = sum (old !l) }
114 while not (is_nil !l) do
115 invariant { length !l <= length (old !l) /\
116 !y + sum !l = sum (old !l) }
126 val predicate eq (x y: elt)
127 ensures { result <-> x = y }
129 (* note: we avoid the use of an existential quantifier in the invariant *)
130 let list_member (x : ref (list elt)) (y: elt) (z: ref int)
131 ensures { !z=1 <-> mem y (old !x) }
133 while not (is_nil !x) do
134 invariant { length !x <= length (old !x) /\
135 (mem y !x -> mem y (old !x)) /\
136 (!z=1 /\ mem y (old !x) \/
137 !z=0 /\ (mem y (old !x) -> mem y !x)) }
139 if eq y (head !x) then z := 1;