author | bulwahn |
Wed, 20 Apr 2011 07:44:23 +0200 | |
changeset 42420 | 8a09dfeb2cec |
parent 35762 | af3ff2ba4c54 |
child 58623 | 2db1df2c8467 |
permissions | -rw-r--r-- |
12560 | 1 |
(* Title: ZF/Induct/Primrec.thy |
12088 | 2 |
Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
3 |
Copyright 1994 University of Cambridge |
|
12610 | 4 |
*) |
12088 | 5 |
|
12610 | 6 |
header {* Primitive Recursive Functions: the inductive definition *} |
12088 | 7 |
|
16417 | 8 |
theory Primrec imports Main begin |
12560 | 9 |
|
12610 | 10 |
text {* |
11 |
Proof adopted from \cite{szasz}. |
|
12 |
||
13 |
See also \cite[page 250, exercise 11]{mendelson}. |
|
14 |
*} |
|
15 |
||
16 |
||
17 |
subsection {* Basic definitions *} |
|
18 |
||
24893 | 19 |
definition |
20 |
SC :: "i" where |
|
12610 | 21 |
"SC == \<lambda>l \<in> list(nat). list_case(0, \<lambda>x xs. succ(x), l)" |
12560 | 22 |
|
24893 | 23 |
definition |
24 |
CONSTANT :: "i=>i" where |
|
19676 | 25 |
"CONSTANT(k) == \<lambda>l \<in> list(nat). k" |
12560 | 26 |
|
24893 | 27 |
definition |
28 |
PROJ :: "i=>i" where |
|
12610 | 29 |
"PROJ(i) == \<lambda>l \<in> list(nat). list_case(0, \<lambda>x xs. x, drop(i,l))" |
12560 | 30 |
|
24893 | 31 |
definition |
32 |
COMP :: "[i,i]=>i" where |
|
26059 | 33 |
"COMP(g,fs) == \<lambda>l \<in> list(nat). g ` map(\<lambda>f. f`l, fs)" |
12610 | 34 |
|
24893 | 35 |
definition |
36 |
PREC :: "[i,i]=>i" where |
|
12610 | 37 |
"PREC(f,g) == |
38 |
\<lambda>l \<in> list(nat). list_case(0, |
|
39 |
\<lambda>x xs. rec(x, f`xs, \<lambda>y r. g ` Cons(r, Cons(y, xs))), l)" |
|
40 |
-- {* Note that @{text g} is applied first to @{term "PREC(f,g)`y"} and then to @{text y}! *} |
|
12560 | 41 |
|
12088 | 42 |
consts |
12610 | 43 |
ACK :: "i=>i" |
12560 | 44 |
primrec |
12610 | 45 |
"ACK(0) = SC" |
19676 | 46 |
"ACK(succ(i)) = PREC (CONSTANT (ACK(i) ` [1]), COMP(ACK(i), [PROJ(0)]))" |
12560 | 47 |
|
24892 | 48 |
abbreviation |
49 |
ack :: "[i,i]=>i" where |
|
50 |
"ack(x,y) == ACK(x) ` [y]" |
|
12560 | 51 |
|
52 |
||
12610 | 53 |
text {* |
54 |
\medskip Useful special cases of evaluation. |
|
55 |
*} |
|
12560 | 56 |
|
57 |
lemma SC: "[| x \<in> nat; l \<in> list(nat) |] ==> SC ` (Cons(x,l)) = succ(x)" |
|
12610 | 58 |
by (simp add: SC_def) |
12560 | 59 |
|
19676 | 60 |
lemma CONSTANT: "l \<in> list(nat) ==> CONSTANT(k) ` l = k" |
61 |
by (simp add: CONSTANT_def) |
|
12560 | 62 |
|
63 |
lemma PROJ_0: "[| x \<in> nat; l \<in> list(nat) |] ==> PROJ(0) ` (Cons(x,l)) = x" |
|
12610 | 64 |
by (simp add: PROJ_def) |
12560 | 65 |
|
66 |
lemma COMP_1: "l \<in> list(nat) ==> COMP(g,[f]) ` l = g` [f`l]" |
|
12610 | 67 |
by (simp add: COMP_def) |
12560 | 68 |
|
69 |
lemma PREC_0: "l \<in> list(nat) ==> PREC(f,g) ` (Cons(0,l)) = f`l" |
|
12610 | 70 |
by (simp add: PREC_def) |
12560 | 71 |
|
12610 | 72 |
lemma PREC_succ: |
73 |
"[| x \<in> nat; l \<in> list(nat) |] |
|
74 |
==> PREC(f,g) ` (Cons(succ(x),l)) = |
|
75 |
g ` Cons(PREC(f,g)`(Cons(x,l)), Cons(x,l))" |
|
76 |
by (simp add: PREC_def) |
|
12560 | 77 |
|
78 |
||
12610 | 79 |
subsection {* Inductive definition of the PR functions *} |
80 |
||
12560 | 81 |
consts |
12610 | 82 |
prim_rec :: i |
12088 | 83 |
|
84 |
inductive |
|
12610 | 85 |
domains prim_rec \<subseteq> "list(nat)->nat" |
12560 | 86 |
intros |
87 |
"SC \<in> prim_rec" |
|
19676 | 88 |
"k \<in> nat ==> CONSTANT(k) \<in> prim_rec" |
12560 | 89 |
"i \<in> nat ==> PROJ(i) \<in> prim_rec" |
12610 | 90 |
"[| g \<in> prim_rec; fs\<in>list(prim_rec) |] ==> COMP(g,fs) \<in> prim_rec" |
91 |
"[| f \<in> prim_rec; g \<in> prim_rec |] ==> PREC(f,g) \<in> prim_rec" |
|
92 |
monos list_mono |
|
19676 | 93 |
con_defs SC_def CONSTANT_def PROJ_def COMP_def PREC_def |
12610 | 94 |
type_intros nat_typechecks list.intros |
26059 | 95 |
lam_type list_case_type drop_type map_type |
12610 | 96 |
apply_type rec_type |
12560 | 97 |
|
98 |
||
12610 | 99 |
lemma prim_rec_into_fun [TC]: "c \<in> prim_rec ==> c \<in> list(nat) -> nat" |
100 |
by (erule subsetD [OF prim_rec.dom_subset]) |
|
12560 | 101 |
|
102 |
lemmas [TC] = apply_type [OF prim_rec_into_fun] |
|
103 |
||
104 |
declare prim_rec.intros [TC] |
|
105 |
declare nat_into_Ord [TC] |
|
106 |
declare rec_type [TC] |
|
107 |
||
12610 | 108 |
lemma ACK_in_prim_rec [TC]: "i \<in> nat ==> ACK(i) \<in> prim_rec" |
18415 | 109 |
by (induct set: nat) simp_all |
12560 | 110 |
|
12610 | 111 |
lemma ack_type [TC]: "[| i \<in> nat; j \<in> nat |] ==> ack(i,j) \<in> nat" |
112 |
by auto |
|
12560 | 113 |
|
12610 | 114 |
|
115 |
subsection {* Ackermann's function cases *} |
|
12560 | 116 |
|
12610 | 117 |
lemma ack_0: "j \<in> nat ==> ack(0,j) = succ(j)" |
118 |
-- {* PROPERTY A 1 *} |
|
119 |
by (simp add: SC) |
|
120 |
||
12560 | 121 |
lemma ack_succ_0: "ack(succ(i), 0) = ack(i,1)" |
12610 | 122 |
-- {* PROPERTY A 2 *} |
19676 | 123 |
by (simp add: CONSTANT PREC_0) |
12560 | 124 |
|
125 |
lemma ack_succ_succ: |
|
12610 | 126 |
"[| i\<in>nat; j\<in>nat |] ==> ack(succ(i), succ(j)) = ack(i, ack(succ(i), j))" |
127 |
-- {* PROPERTY A 3 *} |
|
19676 | 128 |
by (simp add: CONSTANT PREC_succ COMP_1 PROJ_0) |
12560 | 129 |
|
12610 | 130 |
lemmas [simp] = ack_0 ack_succ_0 ack_succ_succ ack_type |
131 |
and [simp del] = ACK.simps |
|
12560 | 132 |
|
133 |
||
18415 | 134 |
lemma lt_ack2: "i \<in> nat ==> j \<in> nat ==> j < ack(i,j)" |
12610 | 135 |
-- {* PROPERTY A 4 *} |
20503 | 136 |
apply (induct i arbitrary: j set: nat) |
12610 | 137 |
apply simp |
138 |
apply (induct_tac j) |
|
139 |
apply (erule_tac [2] succ_leI [THEN lt_trans1]) |
|
140 |
apply (rule nat_0I [THEN nat_0_le, THEN lt_trans]) |
|
141 |
apply auto |
|
142 |
done |
|
12560 | 143 |
|
144 |
lemma ack_lt_ack_succ2: "[|i\<in>nat; j\<in>nat|] ==> ack(i,j) < ack(i, succ(j))" |
|
12610 | 145 |
-- {* PROPERTY A 5-, the single-step lemma *} |
18415 | 146 |
by (induct set: nat) (simp_all add: lt_ack2) |
12560 | 147 |
|
148 |
lemma ack_lt_mono2: "[| j<k; i \<in> nat; k \<in> nat |] ==> ack(i,j) < ack(i,k)" |
|
12610 | 149 |
-- {* PROPERTY A 5, monotonicity for @{text "<"} *} |
150 |
apply (frule lt_nat_in_nat, assumption) |
|
151 |
apply (erule succ_lt_induct) |
|
152 |
apply assumption |
|
153 |
apply (rule_tac [2] lt_trans) |
|
154 |
apply (auto intro: ack_lt_ack_succ2) |
|
155 |
done |
|
12560 | 156 |
|
157 |
lemma ack_le_mono2: "[|j\<le>k; i\<in>nat; k\<in>nat|] ==> ack(i,j) \<le> ack(i,k)" |
|
12610 | 158 |
-- {* PROPERTY A 5', monotonicity for @{text \<le>} *} |
159 |
apply (rule_tac f = "\<lambda>j. ack (i,j) " in Ord_lt_mono_imp_le_mono) |
|
160 |
apply (assumption | rule ack_lt_mono2 ack_type [THEN nat_into_Ord])+ |
|
161 |
done |
|
12560 | 162 |
|
163 |
lemma ack2_le_ack1: |
|
12610 | 164 |
"[| i\<in>nat; j\<in>nat |] ==> ack(i, succ(j)) \<le> ack(succ(i), j)" |
165 |
-- {* PROPERTY A 6 *} |
|
166 |
apply (induct_tac j) |
|
167 |
apply simp_all |
|
168 |
apply (rule ack_le_mono2) |
|
169 |
apply (rule lt_ack2 [THEN succ_leI, THEN le_trans]) |
|
170 |
apply auto |
|
171 |
done |
|
12560 | 172 |
|
173 |
lemma ack_lt_ack_succ1: "[| i \<in> nat; j \<in> nat |] ==> ack(i,j) < ack(succ(i),j)" |
|
12610 | 174 |
-- {* PROPERTY A 7-, the single-step lemma *} |
175 |
apply (rule ack_lt_mono2 [THEN lt_trans2]) |
|
176 |
apply (rule_tac [4] ack2_le_ack1) |
|
177 |
apply auto |
|
178 |
done |
|
12560 | 179 |
|
180 |
lemma ack_lt_mono1: "[| i<j; j \<in> nat; k \<in> nat |] ==> ack(i,k) < ack(j,k)" |
|
12610 | 181 |
-- {* PROPERTY A 7, monotonicity for @{text "<"} *} |
182 |
apply (frule lt_nat_in_nat, assumption) |
|
183 |
apply (erule succ_lt_induct) |
|
184 |
apply assumption |
|
185 |
apply (rule_tac [2] lt_trans) |
|
186 |
apply (auto intro: ack_lt_ack_succ1) |
|
187 |
done |
|
12560 | 188 |
|
189 |
lemma ack_le_mono1: "[| i\<le>j; j \<in> nat; k \<in> nat |] ==> ack(i,k) \<le> ack(j,k)" |
|
12610 | 190 |
-- {* PROPERTY A 7', monotonicity for @{text \<le>} *} |
191 |
apply (rule_tac f = "\<lambda>j. ack (j,k) " in Ord_lt_mono_imp_le_mono) |
|
192 |
apply (assumption | rule ack_lt_mono1 ack_type [THEN nat_into_Ord])+ |
|
193 |
done |
|
12560 | 194 |
|
195 |
lemma ack_1: "j \<in> nat ==> ack(1,j) = succ(succ(j))" |
|
12610 | 196 |
-- {* PROPERTY A 8 *} |
18415 | 197 |
by (induct set: nat) simp_all |
12560 | 198 |
|
199 |
lemma ack_2: "j \<in> nat ==> ack(succ(1),j) = succ(succ(succ(j#+j)))" |
|
12610 | 200 |
-- {* PROPERTY A 9 *} |
18415 | 201 |
by (induct set: nat) (simp_all add: ack_1) |
12560 | 202 |
|
203 |
lemma ack_nest_bound: |
|
12610 | 204 |
"[| i1 \<in> nat; i2 \<in> nat; j \<in> nat |] |
205 |
==> ack(i1, ack(i2,j)) < ack(succ(succ(i1#+i2)), j)" |
|
206 |
-- {* PROPERTY A 10 *} |
|
207 |
apply (rule lt_trans2 [OF _ ack2_le_ack1]) |
|
208 |
apply simp |
|
209 |
apply (rule add_le_self [THEN ack_le_mono1, THEN lt_trans1]) |
|
210 |
apply auto |
|
211 |
apply (force intro: add_le_self2 [THEN ack_lt_mono1, THEN ack_lt_mono2]) |
|
212 |
done |
|
12560 | 213 |
|
214 |
lemma ack_add_bound: |
|
12610 | 215 |
"[| i1 \<in> nat; i2 \<in> nat; j \<in> nat |] |
216 |
==> ack(i1,j) #+ ack(i2,j) < ack(succ(succ(succ(succ(i1#+i2)))), j)" |
|
217 |
-- {* PROPERTY A 11 *} |
|
13339
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12610
diff
changeset
|
218 |
apply (rule_tac j = "ack (succ (1), ack (i1 #+ i2, j))" in lt_trans) |
12610 | 219 |
apply (simp add: ack_2) |
220 |
apply (rule_tac [2] ack_nest_bound [THEN lt_trans2]) |
|
221 |
apply (rule add_le_mono [THEN leI, THEN leI]) |
|
222 |
apply (auto intro: add_le_self add_le_self2 ack_le_mono1) |
|
223 |
done |
|
12560 | 224 |
|
225 |
lemma ack_add_bound2: |
|
12610 | 226 |
"[| i < ack(k,j); j \<in> nat; k \<in> nat |] |
12560 | 227 |
==> i#+j < ack(succ(succ(succ(succ(k)))), j)" |
12610 | 228 |
-- {* PROPERTY A 12. *} |
229 |
-- {* Article uses existential quantifier but the ALF proof used @{term "k#+#4"}. *} |
|
230 |
-- {* Quantified version must be nested @{text "\<exists>k'. \<forall>i,j \<dots>"}. *} |
|
231 |
apply (rule_tac j = "ack (k,j) #+ ack (0,j) " in lt_trans) |
|
232 |
apply (rule_tac [2] ack_add_bound [THEN lt_trans2]) |
|
233 |
apply (rule add_lt_mono) |
|
234 |
apply auto |
|
235 |
done |
|
12560 | 236 |
|
12610 | 237 |
|
238 |
subsection {* Main result *} |
|
12560 | 239 |
|
240 |
declare list_add_type [simp] |
|
241 |
||
242 |
lemma SC_case: "l \<in> list(nat) ==> SC ` l < ack(1, list_add(l))" |
|
12610 | 243 |
apply (unfold SC_def) |
244 |
apply (erule list.cases) |
|
245 |
apply (simp add: succ_iff) |
|
246 |
apply (simp add: ack_1 add_le_self) |
|
247 |
done |
|
12560 | 248 |
|
249 |
lemma lt_ack1: "[| i \<in> nat; j \<in> nat |] ==> i < ack(i,j)" |
|
19676 | 250 |
-- {* PROPERTY A 4'? Extra lemma needed for @{text CONSTANT} case, constant functions. *} |
12610 | 251 |
apply (induct_tac i) |
252 |
apply (simp add: nat_0_le) |
|
253 |
apply (erule lt_trans1 [OF succ_leI ack_lt_ack_succ1]) |
|
254 |
apply auto |
|
255 |
done |
|
12560 | 256 |
|
19676 | 257 |
lemma CONSTANT_case: |
258 |
"[| l \<in> list(nat); k \<in> nat |] ==> CONSTANT(k) ` l < ack(k, list_add(l))" |
|
259 |
by (simp add: CONSTANT_def lt_ack1) |
|
12560 | 260 |
|
12610 | 261 |
lemma PROJ_case [rule_format]: |
12560 | 262 |
"l \<in> list(nat) ==> \<forall>i \<in> nat. PROJ(i) ` l < ack(0, list_add(l))" |
12610 | 263 |
apply (unfold PROJ_def) |
264 |
apply simp |
|
265 |
apply (erule list.induct) |
|
266 |
apply (simp add: nat_0_le) |
|
267 |
apply simp |
|
268 |
apply (rule ballI) |
|
13339
0f89104dd377
Fixed quantified variable name preservation for ball and bex (bounded quants)
paulson
parents:
12610
diff
changeset
|
269 |
apply (erule_tac n = i in natE) |
12610 | 270 |
apply (simp add: add_le_self) |
271 |
apply simp |
|
272 |
apply (erule bspec [THEN lt_trans2]) |
|
273 |
apply (rule_tac [2] add_le_self2 [THEN succ_leI]) |
|
274 |
apply auto |
|
275 |
done |
|
12560 | 276 |
|
12610 | 277 |
text {* |
278 |
\medskip @{text COMP} case. |
|
279 |
*} |
|
12560 | 280 |
|
281 |
lemma COMP_map_lemma: |
|
12610 | 282 |
"fs \<in> list({f \<in> prim_rec. \<exists>kf \<in> nat. \<forall>l \<in> list(nat). f`l < ack(kf, list_add(l))}) |
283 |
==> \<exists>k \<in> nat. \<forall>l \<in> list(nat). |
|
284 |
list_add(map(\<lambda>f. f ` l, fs)) < ack(k, list_add(l))" |
|
18415 | 285 |
apply (induct set: list) |
12610 | 286 |
apply (rule_tac x = 0 in bexI) |
287 |
apply (simp_all add: lt_ack1 nat_0_le) |
|
288 |
apply clarify |
|
289 |
apply (rule ballI [THEN bexI]) |
|
290 |
apply (rule add_lt_mono [THEN lt_trans]) |
|
291 |
apply (rule_tac [5] ack_add_bound) |
|
292 |
apply blast |
|
293 |
apply auto |
|
294 |
done |
|
12560 | 295 |
|
12610 | 296 |
lemma COMP_case: |
297 |
"[| kg\<in>nat; |
|
298 |
\<forall>l \<in> list(nat). g`l < ack(kg, list_add(l)); |
|
299 |
fs \<in> list({f \<in> prim_rec . |
|
300 |
\<exists>kf \<in> nat. \<forall>l \<in> list(nat). |
|
12560 | 301 |
f`l < ack(kf, list_add(l))}) |] |
302 |
==> \<exists>k \<in> nat. \<forall>l \<in> list(nat). COMP(g,fs)`l < ack(k, list_add(l))" |
|
12610 | 303 |
apply (simp add: COMP_def) |
304 |
apply (frule list_CollectD) |
|
305 |
apply (erule COMP_map_lemma [THEN bexE]) |
|
306 |
apply (rule ballI [THEN bexI]) |
|
307 |
apply (erule bspec [THEN lt_trans]) |
|
308 |
apply (rule_tac [2] lt_trans) |
|
309 |
apply (rule_tac [3] ack_nest_bound) |
|
310 |
apply (erule_tac [2] bspec [THEN ack_lt_mono2]) |
|
311 |
apply auto |
|
312 |
done |
|
12560 | 313 |
|
12610 | 314 |
text {* |
315 |
\medskip @{text PREC} case. |
|
316 |
*} |
|
12560 | 317 |
|
12610 | 318 |
lemma PREC_case_lemma: |
319 |
"[| \<forall>l \<in> list(nat). f`l #+ list_add(l) < ack(kf, list_add(l)); |
|
320 |
\<forall>l \<in> list(nat). g`l #+ list_add(l) < ack(kg, list_add(l)); |
|
321 |
f \<in> prim_rec; kf\<in>nat; |
|
322 |
g \<in> prim_rec; kg\<in>nat; |
|
12560 | 323 |
l \<in> list(nat) |] |
324 |
==> PREC(f,g)`l #+ list_add(l) < ack(succ(kf#+kg), list_add(l))" |
|
12610 | 325 |
apply (unfold PREC_def) |
326 |
apply (erule list.cases) |
|
327 |
apply (simp add: lt_trans [OF nat_le_refl lt_ack2]) |
|
328 |
apply simp |
|
329 |
apply (erule ssubst) -- {* get rid of the needless assumption *} |
|
330 |
apply (induct_tac a) |
|
331 |
apply simp_all |
|
332 |
txt {* base case *} |
|
333 |
apply (rule lt_trans, erule bspec, assumption) |
|
334 |
apply (simp add: add_le_self [THEN ack_lt_mono1]) |
|
335 |
txt {* ind step *} |
|
336 |
apply (rule succ_leI [THEN lt_trans1]) |
|
337 |
apply (rule_tac j = "g ` ?ll #+ ?mm" in lt_trans1) |
|
338 |
apply (erule_tac [2] bspec) |
|
339 |
apply (rule nat_le_refl [THEN add_le_mono]) |
|
340 |
apply typecheck |
|
341 |
apply (simp add: add_le_self2) |
|
342 |
txt {* final part of the simplification *} |
|
343 |
apply simp |
|
344 |
apply (rule add_le_self2 [THEN ack_le_mono1, THEN lt_trans1]) |
|
345 |
apply (erule_tac [4] ack_lt_mono2) |
|
346 |
apply auto |
|
347 |
done |
|
12560 | 348 |
|
349 |
lemma PREC_case: |
|
12610 | 350 |
"[| f \<in> prim_rec; kf\<in>nat; |
351 |
g \<in> prim_rec; kg\<in>nat; |
|
352 |
\<forall>l \<in> list(nat). f`l < ack(kf, list_add(l)); |
|
353 |
\<forall>l \<in> list(nat). g`l < ack(kg, list_add(l)) |] |
|
354 |
==> \<exists>k \<in> nat. \<forall>l \<in> list(nat). PREC(f,g)`l< ack(k, list_add(l))" |
|
355 |
apply (rule ballI [THEN bexI]) |
|
356 |
apply (rule lt_trans1 [OF add_le_self PREC_case_lemma]) |
|
357 |
apply typecheck |
|
358 |
apply (blast intro: ack_add_bound2 list_add_type)+ |
|
359 |
done |
|
12560 | 360 |
|
361 |
lemma ack_bounds_prim_rec: |
|
12610 | 362 |
"f \<in> prim_rec ==> \<exists>k \<in> nat. \<forall>l \<in> list(nat). f`l < ack(k, list_add(l))" |
18415 | 363 |
apply (induct set: prim_rec) |
19676 | 364 |
apply (auto intro: SC_case CONSTANT_case PROJ_case COMP_case PREC_case) |
12610 | 365 |
done |
12560 | 366 |
|
12610 | 367 |
theorem ack_not_prim_rec: |
368 |
"(\<lambda>l \<in> list(nat). list_case(0, \<lambda>x xs. ack(x,x), l)) \<notin> prim_rec" |
|
369 |
apply (rule notI) |
|
370 |
apply (drule ack_bounds_prim_rec) |
|
371 |
apply force |
|
372 |
done |
|
12088 | 373 |
|
374 |
end |