1476
|
1 |
(* Title: HOL/Hoare/Examples.thy
|
|
2 |
Author: Norbert Galm
|
5646
|
3 |
Copyright 1998 TUM
|
67410
|
4 |
*)
|
1335
|
5 |
|
72990
|
6 |
section \<open>Various examples\<close>
|
13682
|
7 |
|
72990
|
8 |
theory Examples
|
|
9 |
imports Hoare_Logic Arith2
|
|
10 |
begin
|
13682
|
11 |
|
72990
|
12 |
subsection \<open>Arithmetic\<close>
|
|
13 |
|
|
14 |
subsubsection \<open>Multiplication by successive addition\<close>
|
13682
|
15 |
|
13737
|
16 |
lemma multiply_by_add: "VARS m s a b
|
67613
|
17 |
{a=A \<and> b=B}
|
13682
|
18 |
m := 0; s := 0;
|
67613
|
19 |
WHILE m\<noteq>a
|
|
20 |
INV {s=m*b \<and> a=A \<and> b=B}
|
13682
|
21 |
DO s := s+b; m := m+(1::nat) OD
|
|
22 |
{s = A*B}"
|
|
23 |
by vcg_simp
|
|
24 |
|
63106
|
25 |
lemma multiply_by_add_time: "VARS m s a b t
|
67613
|
26 |
{a=A \<and> b=B \<and> t=0}
|
63106
|
27 |
m := 0; t := t+1; s := 0; t := t+1;
|
67613
|
28 |
WHILE m\<noteq>a
|
|
29 |
INV {s=m*b \<and> a=A \<and> b=B \<and> t = 2*m + 2}
|
63106
|
30 |
DO s := s+b; t := t+1; m := m+(1::nat); t := t+1 OD
|
|
31 |
{s = A*B \<and> t = 2*A + 2}"
|
|
32 |
by vcg_simp
|
|
33 |
|
|
34 |
lemma multiply_by_add2: "VARS M N P :: int
|
67613
|
35 |
{m=M \<and> n=N}
|
13789
|
36 |
IF M < 0 THEN M := -M; N := -N ELSE SKIP FI;
|
|
37 |
P := 0;
|
|
38 |
WHILE 0 < M
|
67613
|
39 |
INV {0 \<le> M \<and> (\<exists>p. p = (if m<0 then -m else m) & p*N = m*n & P = (p-M)*N)}
|
13789
|
40 |
DO P := P+N; M := M - 1 OD
|
|
41 |
{P = m*n}"
|
|
42 |
apply vcg_simp
|
63106
|
43 |
apply (auto simp add:int_distrib)
|
|
44 |
done
|
|
45 |
|
|
46 |
lemma multiply_by_add2_time: "VARS M N P t :: int
|
67613
|
47 |
{m=M \<and> n=N \<and> t=0}
|
63106
|
48 |
IF M < 0 THEN M := -M; t := t+1; N := -N; t := t+1 ELSE SKIP FI;
|
|
49 |
P := 0; t := t+1;
|
|
50 |
WHILE 0 < M
|
67613
|
51 |
INV {0 \<le> M & (\<exists>p. p = (if m<0 then -m else m) & p*N = m*n & P = (p-M)*N & t \<ge> 0 & t \<le> 2*(p-M)+3)}
|
63106
|
52 |
DO P := P+N; t := t+1; M := M - 1; t := t+1 OD
|
|
53 |
{P = m*n & t \<le> 2*abs m + 3}"
|
|
54 |
apply vcg_simp
|
|
55 |
apply (auto simp add:int_distrib)
|
13789
|
56 |
done
|
13682
|
57 |
|
67410
|
58 |
|
72990
|
59 |
subsubsection \<open>Euclid's algorithm for GCD\<close>
|
13682
|
60 |
|
13737
|
61 |
lemma Euclid_GCD: "VARS a b
|
13682
|
62 |
{0<A & 0<B}
|
|
63 |
a := A; b := B;
|
13857
|
64 |
WHILE a \<noteq> b
|
13682
|
65 |
INV {0<a & 0<b & gcd A B = gcd a b}
|
|
66 |
DO IF a<b THEN b := b-a ELSE a := a-b FI OD
|
|
67 |
{a = gcd A B}"
|
|
68 |
apply vcg
|
67410
|
69 |
\<comment> \<open>Now prove the verification conditions\<close>
|
13682
|
70 |
apply auto
|
|
71 |
apply(simp add: gcd_diff_r less_imp_le)
|
16796
|
72 |
apply(simp add: linorder_not_less gcd_diff_l)
|
13682
|
73 |
apply(erule gcd_nnn)
|
|
74 |
done
|
|
75 |
|
63106
|
76 |
lemma Euclid_GCD_time: "VARS a b t
|
|
77 |
{0<A & 0<B & t=0}
|
|
78 |
a := A; t := t+1; b := B; t := t+1;
|
|
79 |
WHILE a \<noteq> b
|
|
80 |
INV {0<a & 0<b & gcd A B = gcd a b & a\<le>A & b\<le>B & t \<le> max A B - max a b + 2}
|
|
81 |
DO IF a<b THEN b := b-a; t := t+1 ELSE a := a-b; t := t+1 FI OD
|
|
82 |
{a = gcd A B & t \<le> max A B + 2}"
|
|
83 |
apply vcg
|
67410
|
84 |
\<comment> \<open>Now prove the verification conditions\<close>
|
63106
|
85 |
apply auto
|
|
86 |
apply(simp add: gcd_diff_r less_imp_le)
|
|
87 |
apply(simp add: linorder_not_less gcd_diff_l)
|
|
88 |
apply(erule gcd_nnn)
|
|
89 |
done
|
|
90 |
|
67410
|
91 |
|
72990
|
92 |
subsubsection \<open>Dijkstra's extension of Euclid's algorithm for simultaneous GCD and SCM\<close>
|
67410
|
93 |
|
|
94 |
text \<open>
|
|
95 |
From E.W. Disjkstra. Selected Writings on Computing, p 98 (EWD474),
|
|
96 |
where it is given without the invariant. Instead of defining \<open>scm\<close>
|
|
97 |
explicitly we have used the theorem \<open>scm x y = x * y / gcd x y\<close> and avoided
|
|
98 |
division by mupltiplying with \<open>gcd x y\<close>.
|
|
99 |
\<close>
|
13682
|
100 |
|
|
101 |
lemmas distribs =
|
|
102 |
diff_mult_distrib diff_mult_distrib2 add_mult_distrib add_mult_distrib2
|
|
103 |
|
13737
|
104 |
lemma gcd_scm: "VARS a b x y
|
13682
|
105 |
{0<A & 0<B & a=A & b=B & x=B & y=A}
|
|
106 |
WHILE a ~= b
|
|
107 |
INV {0<a & 0<b & gcd A B = gcd a b & 2*A*B = a*x + b*y}
|
|
108 |
DO IF a<b THEN (b := b-a; x := x+y) ELSE (a := a-b; y := y+x) FI OD
|
|
109 |
{a = gcd A B & 2*A*B = a*(x+y)}"
|
|
110 |
apply vcg
|
|
111 |
apply simp
|
16796
|
112 |
apply(simp add: distribs gcd_diff_r linorder_not_less gcd_diff_l)
|
13682
|
113 |
apply(simp add: distribs gcd_nnn)
|
|
114 |
done
|
|
115 |
|
67410
|
116 |
|
72990
|
117 |
subsubsection \<open>Power by iterated squaring and multiplication\<close>
|
13682
|
118 |
|
13737
|
119 |
lemma power_by_mult: "VARS a b c
|
13682
|
120 |
{a=A & b=B}
|
|
121 |
c := (1::nat);
|
|
122 |
WHILE b ~= 0
|
|
123 |
INV {A^B = c * a^b}
|
|
124 |
DO WHILE b mod 2 = 0
|
|
125 |
INV {A^B = c * a^b}
|
|
126 |
DO a := a*a; b := b div 2 OD;
|
|
127 |
c := c*a; b := b - 1
|
|
128 |
OD
|
|
129 |
{c = A^B}"
|
|
130 |
apply vcg_simp
|
|
131 |
apply(case_tac "b")
|
42154
|
132 |
apply simp
|
13682
|
133 |
apply simp
|
|
134 |
done
|
|
135 |
|
67410
|
136 |
|
72990
|
137 |
subsubsection \<open>Factorial\<close>
|
13682
|
138 |
|
13737
|
139 |
lemma factorial: "VARS a b
|
13682
|
140 |
{a=A}
|
|
141 |
b := 1;
|
63106
|
142 |
WHILE a > 0
|
13682
|
143 |
INV {fac A = b * fac a}
|
|
144 |
DO b := b*a; a := a - 1 OD
|
|
145 |
{b = fac A}"
|
|
146 |
apply vcg_simp
|
|
147 |
apply(clarsimp split: nat_diff_split)
|
|
148 |
done
|
|
149 |
|
63106
|
150 |
lemma factorial_time: "VARS a b t
|
|
151 |
{a=A & t=0}
|
|
152 |
b := 1; t := t+1;
|
|
153 |
WHILE a > 0
|
|
154 |
INV {fac A = b * fac a & a \<le> A & t = 2*(A-a)+1}
|
|
155 |
DO b := b*a; t := t+1; a := a - 1; t := t+1 OD
|
|
156 |
{b = fac A & t = 2*A + 1}"
|
|
157 |
apply vcg_simp
|
|
158 |
apply(clarsimp split: nat_diff_split)
|
|
159 |
done
|
|
160 |
|
13684
|
161 |
lemma [simp]: "1 \<le> i \<Longrightarrow> fac (i - Suc 0) * i = fac i"
|
|
162 |
by(induct i, simp_all)
|
|
163 |
|
63106
|
164 |
lemma factorial2: "VARS i f
|
13684
|
165 |
{True}
|
|
166 |
i := (1::nat); f := 1;
|
|
167 |
WHILE i <= n INV {f = fac(i - 1) & 1 <= i & i <= n+1}
|
|
168 |
DO f := f*i; i := i+1 OD
|
|
169 |
{f = fac n}"
|
|
170 |
apply vcg_simp
|
|
171 |
apply(subgoal_tac "i = Suc n")
|
|
172 |
apply simp
|
|
173 |
apply arith
|
|
174 |
done
|
13682
|
175 |
|
63106
|
176 |
lemma factorial2_time: "VARS i f t
|
|
177 |
{t=0}
|
|
178 |
i := (1::nat); t := t+1; f := 1; t := t+1;
|
|
179 |
WHILE i \<le> n INV {f = fac(i - 1) & 1 \<le> i & i \<le> n+1 & t = 2*(i-1)+2}
|
|
180 |
DO f := f*i; t := t+1; i := i+1; t := t+1 OD
|
|
181 |
{f = fac n & t = 2*n+2}"
|
|
182 |
apply vcg_simp
|
|
183 |
apply auto
|
|
184 |
apply(subgoal_tac "i = Suc n")
|
|
185 |
apply simp
|
|
186 |
apply arith
|
|
187 |
done
|
|
188 |
|
13682
|
189 |
|
72990
|
190 |
subsubsection \<open>Square root\<close>
|
67410
|
191 |
|
|
192 |
\<comment> \<open>the easy way:\<close>
|
13682
|
193 |
|
13737
|
194 |
lemma sqrt: "VARS r x
|
13682
|
195 |
{True}
|
63106
|
196 |
r := (0::nat);
|
|
197 |
WHILE (r+1)*(r+1) <= X
|
|
198 |
INV {r*r \<le> X}
|
13682
|
199 |
DO r := r+1 OD
|
|
200 |
{r*r <= X & X < (r+1)*(r+1)}"
|
|
201 |
apply vcg_simp
|
|
202 |
done
|
|
203 |
|
63106
|
204 |
lemma sqrt_time: "VARS r t
|
|
205 |
{t=0}
|
|
206 |
r := (0::nat); t := t+1;
|
|
207 |
WHILE (r+1)*(r+1) <= X
|
|
208 |
INV {r*r \<le> X & t = r+1}
|
|
209 |
DO r := r+1; t := t+1 OD
|
|
210 |
{r*r <= X & X < (r+1)*(r+1) & (t-1)*(t-1) \<le> X}"
|
|
211 |
apply vcg_simp
|
|
212 |
done
|
|
213 |
|
67410
|
214 |
\<comment> \<open>without multiplication\<close>
|
63106
|
215 |
lemma sqrt_without_multiplication: "VARS u w r
|
|
216 |
{x=X}
|
|
217 |
u := 1; w := 1; r := (0::nat);
|
|
218 |
WHILE w <= X
|
|
219 |
INV {u = r+r+1 & w = (r+1)*(r+1) & r*r <= X}
|
13682
|
220 |
DO r := r + 1; w := w + u + 2; u := u + 2 OD
|
|
221 |
{r*r <= X & X < (r+1)*(r+1)}"
|
|
222 |
apply vcg_simp
|
|
223 |
done
|
|
224 |
|
|
225 |
|
72990
|
226 |
subsection \<open>Lists\<close>
|
13682
|
227 |
|
13737
|
228 |
lemma imperative_reverse: "VARS y x
|
13682
|
229 |
{x=X}
|
|
230 |
y:=[];
|
|
231 |
WHILE x ~= []
|
|
232 |
INV {rev(x)@y = rev(X)}
|
|
233 |
DO y := (hd x # y); x := tl x OD
|
|
234 |
{y=rev(X)}"
|
|
235 |
apply vcg_simp
|
|
236 |
apply(simp add: neq_Nil_conv)
|
|
237 |
apply auto
|
|
238 |
done
|
|
239 |
|
63106
|
240 |
lemma imperative_reverse_time: "VARS y x t
|
|
241 |
{x=X & t=0}
|
|
242 |
y:=[]; t := t+1;
|
|
243 |
WHILE x ~= []
|
|
244 |
INV {rev(x)@y = rev(X) & t = 2*(length y) + 1}
|
|
245 |
DO y := (hd x # y); t := t+1; x := tl x; t := t+1 OD
|
|
246 |
{y=rev(X) & t = 2*length X + 1}"
|
|
247 |
apply vcg_simp
|
|
248 |
apply(simp add: neq_Nil_conv)
|
|
249 |
apply auto
|
|
250 |
done
|
|
251 |
|
13737
|
252 |
lemma imperative_append: "VARS x y
|
13682
|
253 |
{x=X & y=Y}
|
|
254 |
x := rev(x);
|
|
255 |
WHILE x~=[]
|
|
256 |
INV {rev(x)@y = X@Y}
|
|
257 |
DO y := (hd x # y);
|
|
258 |
x := tl x
|
|
259 |
OD
|
|
260 |
{y = X@Y}"
|
|
261 |
apply vcg_simp
|
|
262 |
apply(simp add: neq_Nil_conv)
|
|
263 |
apply auto
|
|
264 |
done
|
|
265 |
|
63106
|
266 |
lemma imperative_append_time_no_rev: "VARS x y t
|
|
267 |
{x=X & y=Y}
|
|
268 |
x := rev(x); t := 0;
|
|
269 |
WHILE x~=[]
|
|
270 |
INV {rev(x)@y = X@Y & length x \<le> length X & t = 2 * (length X - length x)}
|
|
271 |
DO y := (hd x # y); t := t+1;
|
|
272 |
x := tl x; t := t+1
|
|
273 |
OD
|
|
274 |
{y = X@Y & t = 2 * length X}"
|
|
275 |
apply vcg_simp
|
|
276 |
apply(simp add: neq_Nil_conv)
|
|
277 |
apply auto
|
|
278 |
done
|
|
279 |
|
13682
|
280 |
|
72990
|
281 |
subsection \<open>Arrays\<close>
|
13682
|
282 |
|
72990
|
283 |
subsubsection \<open>Search for a key\<close>
|
67410
|
284 |
|
13737
|
285 |
lemma zero_search: "VARS A i
|
13682
|
286 |
{True}
|
|
287 |
i := 0;
|
67613
|
288 |
WHILE i < length A & A!i \<noteq> key
|
|
289 |
INV {\<forall>j. j<i --> A!j \<noteq> key}
|
13682
|
290 |
DO i := i+1 OD
|
|
291 |
{(i < length A --> A!i = key) &
|
67613
|
292 |
(i = length A --> (\<forall>j. j < length A \<longrightarrow> A!j \<noteq> key))}"
|
13682
|
293 |
apply vcg_simp
|
|
294 |
apply(blast elim!: less_SucE)
|
|
295 |
done
|
|
296 |
|
63106
|
297 |
lemma zero_search_time: "VARS A i t
|
|
298 |
{t=0}
|
|
299 |
i := 0; t := t+1;
|
67613
|
300 |
WHILE i < length A \<and> A!i \<noteq> key
|
|
301 |
INV {(\<forall>j. j<i \<longrightarrow> A!j \<noteq> key) \<and> i \<le> length A \<and> t = i+1}
|
63106
|
302 |
DO i := i+1; t := t+1 OD
|
67613
|
303 |
{(i < length A \<longrightarrow> A!i = key) \<and>
|
|
304 |
(i = length A \<longrightarrow> (\<forall>j. j < length A --> A!j \<noteq> key)) \<and> t \<le> length A + 1}"
|
63106
|
305 |
apply vcg_simp
|
|
306 |
apply(blast elim!: less_SucE)
|
|
307 |
done
|
|
308 |
|
67410
|
309 |
text \<open>
|
|
310 |
The \<open>partition\<close> procedure for quicksort.
|
|
311 |
\<^item> \<open>A\<close> is the array to be sorted (modelled as a list).
|
|
312 |
\<^item> Elements of \<open>A\<close> must be of class order to infer at the end
|
|
313 |
that the elements between u and l are equal to pivot.
|
13682
|
314 |
|
67410
|
315 |
Ambiguity warnings of parser are due to \<open>:=\<close> being used
|
|
316 |
both for assignment and list update.
|
|
317 |
\<close>
|
13682
|
318 |
lemma Partition:
|
81195
|
319 |
fixes pivot
|
|
320 |
defines "leq \<equiv> \<lambda>A i. \<forall>k. k<i \<longrightarrow> A!k \<le> pivot"
|
|
321 |
and "geq \<equiv> \<lambda>A i. \<forall>k. i<k \<and> k<length A \<longrightarrow> pivot \<le> A!k"
|
|
322 |
shows
|
|
323 |
"VARS A u l
|
|
324 |
{0 < length(A::('a::order)list)}
|
|
325 |
l := 0; u := length A - Suc 0;
|
|
326 |
WHILE l \<le> u
|
|
327 |
INV {leq A l \<and> geq A u \<and> u<length A \<and> l\<le>length A}
|
|
328 |
DO WHILE l < length A \<and> A!l \<le> pivot
|
|
329 |
INV {leq A l & geq A u \<and> u<length A \<and> l\<le>length A}
|
|
330 |
DO l := l+1 OD;
|
|
331 |
WHILE 0 < u & pivot \<le> A!u
|
|
332 |
INV {leq A l & geq A u \<and> u<length A \<and> l\<le>length A}
|
|
333 |
DO u := u - 1 OD;
|
|
334 |
IF l \<le> u THEN A := A[l := A!u, u := A!l] ELSE SKIP FI
|
|
335 |
OD
|
|
336 |
{leq A u & (\<forall>k. u<k \<and> k<l --> A!k = pivot) \<and> geq A l}"
|
|
337 |
proof -
|
|
338 |
have eq: "m - Suc 0 < n \<Longrightarrow> m < Suc n" for m n
|
|
339 |
by arith
|
|
340 |
show ?thesis
|
|
341 |
apply (simp add: assms)
|
|
342 |
apply vcg_simp
|
|
343 |
apply (force simp: neq_Nil_conv)
|
|
344 |
apply (blast elim!: less_SucE intro: Suc_leI)
|
|
345 |
apply (blast elim!: less_SucE intro: less_imp_diff_less dest: eq)
|
|
346 |
apply (force simp: nth_list_update)
|
|
347 |
done
|
|
348 |
qed
|
13682
|
349 |
|
62390
|
350 |
end
|