adding remarks after static inspection of the invocation of the SML code generator
1 (* Title: HOL/Proofs/Extraction/Higman.thy
2 Author: Stefan Berghofer, TU Muenchen
3 Author: Monika Seisenberger, LMU Muenchen
6 header {* Higman's lemma *}
9 imports Main "~~/src/HOL/Library/State_Monad" Random
13 Formalization by Stefan Berghofer and Monika Seisenberger,
14 based on Coquand and Fridlender \cite{Coquand93}.
17 datatype letter = A | B
19 inductive emb :: "letter list \<Rightarrow> letter list \<Rightarrow> bool"
21 emb0 [Pure.intro]: "emb [] bs"
22 | emb1 [Pure.intro]: "emb as bs \<Longrightarrow> emb as (b # bs)"
23 | emb2 [Pure.intro]: "emb as bs \<Longrightarrow> emb (a # as) (a # bs)"
25 inductive L :: "letter list \<Rightarrow> letter list list \<Rightarrow> bool"
26 for v :: "letter list"
28 L0 [Pure.intro]: "emb w v \<Longrightarrow> L v (w # ws)"
29 | L1 [Pure.intro]: "L v ws \<Longrightarrow> L v (w # ws)"
31 inductive good :: "letter list list \<Rightarrow> bool"
33 good0 [Pure.intro]: "L w ws \<Longrightarrow> good (w # ws)"
34 | good1 [Pure.intro]: "good ws \<Longrightarrow> good (w # ws)"
36 inductive R :: "letter \<Rightarrow> letter list list \<Rightarrow> letter list list \<Rightarrow> bool"
39 R0 [Pure.intro]: "R a [] []"
40 | R1 [Pure.intro]: "R a vs ws \<Longrightarrow> R a (w # vs) ((a # w) # ws)"
42 inductive T :: "letter \<Rightarrow> letter list list \<Rightarrow> letter list list \<Rightarrow> bool"
45 T0 [Pure.intro]: "a \<noteq> b \<Longrightarrow> R b ws zs \<Longrightarrow> T a (w # zs) ((a # w) # zs)"
46 | T1 [Pure.intro]: "T a ws zs \<Longrightarrow> T a (w # ws) ((a # w) # zs)"
47 | T2 [Pure.intro]: "a \<noteq> b \<Longrightarrow> T a ws zs \<Longrightarrow> T a ws ((b # w) # zs)"
49 inductive bar :: "letter list list \<Rightarrow> bool"
51 bar1 [Pure.intro]: "good ws \<Longrightarrow> bar ws"
52 | bar2 [Pure.intro]: "(\<And>w. bar (w # ws)) \<Longrightarrow> bar ws"
54 theorem prop1: "bar ([] # ws)" by iprover
56 theorem lemma1: "L as ws \<Longrightarrow> L (a # as) ws"
57 by (erule L.induct, iprover+)
59 lemma lemma2': "R a vs ws \<Longrightarrow> L as vs \<Longrightarrow> L (a # as) ws"
70 lemma lemma2: "R a vs ws \<Longrightarrow> good vs \<Longrightarrow> good ws"
73 apply (erule good.cases)
81 lemma lemma3': "T a vs ws \<Longrightarrow> L as vs \<Longrightarrow> L (a # as) ws"
94 lemma lemma3: "T a ws zs \<Longrightarrow> good ws \<Longrightarrow> good zs"
96 apply (erule good.cases)
101 apply (erule good.cases)
104 apply (erule lemma3')
108 lemma lemma4: "R a ws zs \<Longrightarrow> ws \<noteq> [] \<Longrightarrow> T a ws zs"
109 apply (induct set: R)
112 apply (erule R.cases)
115 apply (rule_tac b=B in T0)
118 apply (rule_tac b=A in T0)
126 lemma letter_neq: "(a::letter) \<noteq> b \<Longrightarrow> c \<noteq> a \<Longrightarrow> c = b"
129 apply (case_tac c, simp, simp)
130 apply (case_tac c, simp, simp)
132 apply (case_tac c, simp, simp)
133 apply (case_tac c, simp, simp)
136 lemma letter_eq_dec: "(a::letter) = b \<or> a \<noteq> b"
147 assumes ab: "a \<noteq> b" and bar: "bar xs"
148 shows "\<And>ys zs. bar ys \<Longrightarrow> T a xs zs \<Longrightarrow> T b ys zs \<Longrightarrow> bar zs" using bar
150 fix xs zs assume "T a xs zs" and "good xs"
151 hence "good zs" by (rule lemma3)
152 then show "bar zs" by (rule bar1)
155 assume I: "\<And>w ys zs. bar ys \<Longrightarrow> T a (w # xs) zs \<Longrightarrow> T b ys zs \<Longrightarrow> bar zs"
157 thus "\<And>zs. T a xs zs \<Longrightarrow> T b ys zs \<Longrightarrow> bar zs"
159 fix ys zs assume "T b ys zs" and "good ys"
160 then have "good zs" by (rule lemma3)
161 then show "bar zs" by (rule bar1)
163 fix ys zs assume I': "\<And>w zs. T a xs zs \<Longrightarrow> T b (w # ys) zs \<Longrightarrow> bar zs"
164 and ys: "\<And>w. bar (w # ys)" and Ta: "T a xs zs" and Tb: "T b ys zs"
171 thus ?thesis by simp (rule prop1)
174 from letter_eq_dec show ?thesis
177 from ab have "bar ((a # cs) # zs)" by (iprover intro: I ys Ta Tb)
178 thus ?thesis by (simp add: Cons ca)
180 assume "c \<noteq> a"
181 with ab have cb: "c = b" by (rule letter_neq)
182 from ab have "bar ((b # cs) # zs)" by (iprover intro: I' Ta Tb)
183 thus ?thesis by (simp add: Cons cb)
191 assumes bar: "bar xs"
192 shows "\<And>zs. xs \<noteq> [] \<Longrightarrow> R a xs zs \<Longrightarrow> bar zs" using bar
195 assume "R a xs zs" and "good xs"
196 then have "good zs" by (rule lemma2)
197 then show "bar zs" by (rule bar1)
200 assume I: "\<And>w zs. w # xs \<noteq> [] \<Longrightarrow> R a (w # xs) zs \<Longrightarrow> bar zs"
201 and xsb: "\<And>w. bar (w # xs)" and xsn: "xs \<noteq> []" and R: "R a xs zs"
208 show ?case by (rule prop1)
211 from letter_eq_dec show ?case
214 thus ?thesis by (iprover intro: I [simplified] R)
216 from R xsn have T: "T a xs zs" by (rule lemma4)
217 assume "c \<noteq> a"
218 thus ?thesis by (iprover intro: prop2 Cons xsb xsn R T)
224 theorem higman: "bar []"
229 show "bar [[]]" by (rule prop1)
231 fix c cs assume "bar [cs]"
232 thus "bar [c # cs]" by (rule prop3) (simp, iprover)
237 is_prefix :: "'a list \<Rightarrow> (nat \<Rightarrow> 'a) \<Rightarrow> bool"
239 "is_prefix [] f = True"
240 | "is_prefix (x # xs) f = (x = f (length xs) \<and> is_prefix xs f)"
244 shows "is_prefix ws f \<Longrightarrow> \<exists>i. emb (f i) w \<and> i < length ws" using L
247 hence "emb (f (length ws)) w" by simp
248 moreover have "length ws < length (v # ws)" by simp
249 ultimately show ?case by iprover
252 then obtain i where emb: "emb (f i) w" and "i < length ws"
254 hence "i < length (v # ws)" by simp
255 with emb show ?case by iprover
259 assumes good: "good ws"
260 shows "is_prefix ws f \<Longrightarrow> \<exists>i j. emb (f i) (f j) \<and> i < j" using good
263 hence "w = f (length ws)" and "is_prefix ws f" by simp_all
264 with good0 show ?case by (iprover dest: L_idx)
271 assumes bar: "bar ws"
272 shows "is_prefix ws f \<Longrightarrow> \<exists>i j. emb (f i) (f j) \<and> i < j" using bar
275 thus ?case by (rule good_idx)
278 hence "is_prefix (f (length ws) # ws) f" by simp
279 thus ?case by (rule bar2)
283 Strong version: yields indices of words that can be embedded into each other.
286 theorem higman_idx: "\<exists>(i::nat) j. emb (f i) (f j) \<and> i < j"
288 show "bar []" by (rule higman)
289 show "is_prefix [] f" by simp
293 Weak version: only yield sequence containing words
294 that can be embedded into each other.
297 theorem good_prefix_lemma:
298 assumes bar: "bar ws"
299 shows "is_prefix ws f \<Longrightarrow> \<exists>vs. is_prefix vs f \<and> good vs" using bar
302 thus ?case by iprover
305 from bar2.prems have "is_prefix (f (length ws) # ws) f" by simp
306 thus ?case by (iprover intro: bar2)
309 theorem good_prefix: "\<exists>vs. is_prefix vs f \<and> good vs"
311 by (rule good_prefix_lemma) simp+
313 subsection {* Extracting the program *}
315 declare R.induct [ind_realizer]
316 declare T.induct [ind_realizer]
317 declare L.induct [ind_realizer]
318 declare good.induct [ind_realizer]
319 declare bar.induct [ind_realizer]
324 Program extracted from the proof of @{text higman_idx}:
325 @{thm [display] higman_idx_def [no_vars]}
326 Corresponding correctness theorem:
327 @{thm [display] higman_idx_correctness [no_vars]}
328 Program extracted from the proof of @{text higman}:
329 @{thm [display] higman_def [no_vars]}
330 Program extracted from the proof of @{text prop1}:
331 @{thm [display] prop1_def [no_vars]}
332 Program extracted from the proof of @{text prop2}:
333 @{thm [display] prop2_def [no_vars]}
334 Program extracted from the proof of @{text prop3}:
335 @{thm [display] prop3_def [no_vars]}
339 subsection {* Some examples *}
341 instantiation LT and TT :: default
344 definition "default = L0 [] []"
346 definition "default = T0 A [] [] [] R0"
352 function mk_word_aux :: "nat \<Rightarrow> Random.seed \<Rightarrow> letter list \<times> Random.seed" where
353 "mk_word_aux k = exec {
354 i \<leftarrow> Random.range 10;
355 (if i > 7 \<and> k > 2 \<or> k > 1000 then Pair []
357 let l = (if i mod 2 = 0 then A else B);
358 ls \<leftarrow> mk_word_aux (Suc k);
361 by pat_completeness auto
362 termination by (relation "measure ((op -) 1001)") auto
364 definition mk_word :: "Random.seed \<Rightarrow> letter list \<times> Random.seed" where
365 "mk_word = mk_word_aux 0"
367 primrec mk_word_s :: "nat \<Rightarrow> Random.seed \<Rightarrow> letter list \<times> Random.seed" where
368 "mk_word_s 0 = mk_word"
369 | "mk_word_s (Suc n) = exec {
370 _ \<leftarrow> mk_word;
374 definition g1 :: "nat \<Rightarrow> letter list" where
375 "g1 s = fst (mk_word_s s (20000, 1))"
377 definition g2 :: "nat \<Rightarrow> letter list" where
378 "g2 s = fst (mk_word_s s (50000, 1))"
380 fun f1 :: "nat \<Rightarrow> letter list" where
383 | "f1 (Suc (Suc 0)) = [A, B]"
386 fun f2 :: "nat \<Rightarrow> letter list" where
389 | "f2 (Suc (Suc 0)) = [B, A]"
394 val higman_idx = @{code higman_idx};
400 val (i1, j1) = higman_idx g1;
401 val (v1, w1) = (g1 i1, g1 j1);
402 val (i2, j2) = higman_idx g2;
403 val (v2, w2) = (g2 i2, g2 j2);
404 val (i3, j3) = higman_idx f1;
405 val (v3, w3) = (f1 i3, f1 j3);
406 val (i4, j4) = higman_idx f2;
407 val (v4, w4) = (f2 i4, f2 j4);
411 text {* The same story with the legacy SML code generator,
412 this can be removed once the code generator is removed. *}
422 val m = 2147483647.0;
426 in t - m * real (Real.floor(t/m)) end;
430 val r = nextRand seed;
431 val i = Real.round (r / m * 10.0);
432 in if i > 7 andalso l > 2 then (r, []) else
433 apsnd (cons (if i mod 2 = 0 then A else B)) (mk_word r (l+1))
436 fun f s zero = mk_word s 0
437 | f s (Suc n) = f (fst (mk_word s 0)) n;
439 val g1 = snd o (f 20000.0);
441 val g2 = snd o (f 50000.0);
444 | f1 (Suc zero) = [B]
445 | f1 (Suc (Suc zero)) = [A,B]
449 | f2 (Suc zero) = [B]
450 | f2 (Suc (Suc zero)) = [B,A]
453 val (i1, j1) = higman g1;
454 val (v1, w1) = (g1 i1, g1 j1);
455 val (i2, j2) = higman g2;
456 val (v2, w2) = (g2 i2, g2 j2);
457 val (i3, j3) = higman f1;
458 val (v3, w3) = (f1 i3, f1 j3);
459 val (i4, j4) = higman f2;
460 val (v4, w4) = (f2 i4, f2 j4);