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