| author | paulson | 
| Thu, 29 Mar 2007 11:12:39 +0200 | |
| changeset 22546 | c40d7ab8cbc5 | 
| 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: 
12610diff
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: 
12610diff
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 |