58 |
57 |
59 So we apply the $i$th @{text "orule"}, but we have to show the @{text "As"} (by assumption) |
58 So we apply the $i$th @{text "orule"}, but we have to show the @{text "As"} (by assumption) |
60 and all @{text "(\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>*"}. For the latter we use the assumptions |
59 and all @{text "(\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>*"}. For the latter we use the assumptions |
61 @{text "(\<forall>ys. Bs \<longrightarrow> (\<forall>preds. orules \<longrightarrow> pred ss))\<^isup>*"} and @{text "orules"}. |
60 @{text "(\<forall>ys. Bs \<longrightarrow> (\<forall>preds. orules \<longrightarrow> pred ss))\<^isup>*"} and @{text "orules"}. |
62 |
61 |
63 *} |
62 |
64 |
63 \begin{center} |
65 |
64 **************************** |
66 text {* |
65 \end{center} |
67 First we have to produce for each predicate the definition of the form |
66 *} |
|
67 |
|
68 |
|
69 text {* |
|
70 For building testcases let us give some shorthands for the definitions of @{text "even/odd"} and |
|
71 @{text "fresh"}. (FIXME put in a figure) |
|
72 *} |
|
73 |
|
74 ML{*val eo_defs = [@{thm even_def}, @{thm odd_def}] |
|
75 val eo_rules = |
|
76 [@{prop "even 0"}, |
|
77 @{prop "\<And>n. odd n \<Longrightarrow> even (Suc n)"}, |
|
78 @{prop "\<And>n. even n \<Longrightarrow> odd (Suc n)"}] |
|
79 val eo_orules = |
|
80 [@{prop "even 0"}, |
|
81 @{prop "\<forall>n. odd n \<longrightarrow> even (Suc n)"}, |
|
82 @{prop "\<forall>n. even n \<longrightarrow> odd (Suc n)"}] |
|
83 val eo_preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}] |
|
84 val eo_prednames = [@{binding "even"}, @{binding "odd"}] |
|
85 val eo_syns = [NoSyn, NoSyn] |
|
86 val eo_arg_tyss = [[@{typ "nat"}],[@{typ "nat"}]] *} |
|
87 |
|
88 |
|
89 ML{*val fresh_defs = [@{thm fresh_def}] |
|
90 val fresh_rules = |
|
91 [@{prop "\<And>a b. a\<noteq>b \<Longrightarrow> a\<sharp>Var b"}, |
|
92 @{prop "\<And>a s t. a\<sharp>t \<Longrightarrow> a\<sharp>s \<Longrightarrow> a\<sharp>App t s"}, |
|
93 @{prop "\<And>a t. a\<sharp>Lam a t"}, |
|
94 @{prop "\<And>a b t. a\<noteq>b \<Longrightarrow> a\<sharp>t \<Longrightarrow> a\<sharp>Lam b t"}] |
|
95 val fresh_orules = |
|
96 [@{prop "\<forall>a b. a\<noteq>b \<longrightarrow> a\<sharp>Var b"}, |
|
97 @{prop "\<forall>a s t. a\<sharp>t \<longrightarrow> a\<sharp>s \<longrightarrow> a\<sharp>App t s"}, |
|
98 @{prop "\<forall>a t. a\<sharp>Lam a t"}, |
|
99 @{prop "\<forall>a b t. a\<noteq>b \<longrightarrow> a\<sharp>t \<longrightarrow> a\<sharp>Lam b t"}] |
|
100 val fresh_preds = [@{term "fresh::string\<Rightarrow>trm\<Rightarrow>bool"}] *} |
|
101 |
|
102 |
|
103 subsection {* Definitions *} |
|
104 |
|
105 text {* |
|
106 First we have to produce for each predicate the definition, whose general form is |
68 |
107 |
69 @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"} |
108 @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"} |
70 |
109 |
71 and then ``register'' the definitions with Isabelle. |
110 and then ``register'' the definition inside a local theory. |
72 To do the latter, we use the following wrapper for |
111 To do the latter, we use the following wrapper for |
73 @{ML LocalTheory.define}. The wrapper takes a predicate name, a syntax |
112 @{ML LocalTheory.define}. The wrapper takes a predicate name, a syntax |
74 annotation and a term representing the right-hand side of the definition. |
113 annotation and a term representing the right-hand side of the definition. |
75 *} |
114 *} |
76 |
115 |
100 warning (str_of_thm_no_vars lthy' def); lthy' |
139 warning (str_of_thm_no_vars lthy' def); lthy' |
101 end *} |
140 end *} |
102 |
141 |
103 text {* |
142 text {* |
104 which makes the definition @{prop "MyTrue \<equiv> True"} and then prints it out. |
143 which makes the definition @{prop "MyTrue \<equiv> True"} and then prints it out. |
105 Since we are testing the function inside \isacommand{local\_setup}, i.e.~make |
144 Since we are testing the function inside \isacommand{local\_setup}, i.e., make |
106 changes to the ambient theory, we can query the definition using the usual |
145 changes to the ambient theory, we can query the definition with the usual |
107 command \isacommand{thm}: |
146 command \isacommand{thm}: |
108 |
147 |
109 \begin{isabelle} |
148 \begin{isabelle} |
110 \isacommand{thm}~@{text "MyTrue_def"}\\ |
149 \isacommand{thm}~@{text "MyTrue_def"}\\ |
111 @{text "> MyTrue \<equiv> True"} |
150 @{text "> MyTrue \<equiv> True"} |
112 \end{isabelle} |
151 \end{isabelle} |
113 |
152 |
114 The next two functions construct the right-hand sides of the definitions, which |
153 The next two functions construct the right-hand sides of the definitions, |
115 are of the form |
154 which are terms of the form |
116 |
155 |
117 @{text [display] "\<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"} |
156 @{text [display] "\<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"} |
118 |
157 |
119 The variables @{text "zs"} need to be chosen so that they do not occur |
158 When constructing them, the variables @{text "zs"} need to be chosen so that |
120 in the @{text orules} and also be distinct from the @{text "preds"}. |
159 they do not occur in the @{text orules} and also be distinct from the @{text |
|
160 "preds"}. |
|
161 |
121 |
162 |
122 The first function constructs the term for one particular predicate, say |
163 The first function constructs the term for one particular predicate, say |
123 @{text "pred"}; the number of arguments of this predicate is |
164 @{text "pred"}. The number of arguments of this predicate is |
124 determined by the number of argument types given in @{text "arg_tys"}. |
165 determined by the number of argument types given in @{text "arg_tys"}. |
125 The other arguments are all @{text "preds"} and the @{text "orules"}. |
166 The other arguments are all the @{text "preds"} and the @{text "orules"}. |
126 *} |
167 *} |
127 |
168 |
128 ML %linenosgray{*fun defs_aux lthy orules preds (pred, arg_tys) = |
169 ML %linenosgray{*fun defs_aux lthy orules preds (pred, arg_tys) = |
129 let |
170 let |
130 fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P |
171 fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P |
151 strings. |
192 strings. |
152 |
193 |
153 The unique free variables are applied to the predicate (Line 11) using the |
194 The unique free variables are applied to the predicate (Line 11) using the |
154 function @{ML list_comb}; then the @{text orules} are prefixed (Line 12); in |
195 function @{ML list_comb}; then the @{text orules} are prefixed (Line 12); in |
155 Line 13 we quantify over all predicates; and in line 14 we just abstract |
196 Line 13 we quantify over all predicates; and in line 14 we just abstract |
156 over all the @{text "zs"}, i.e.~the fresh arguments of the |
197 over all the @{text "zs"}, i.e., the fresh arguments of the |
157 predicate. A testcase for this function is |
198 predicate. A testcase for this function is |
158 *} |
199 *} |
159 |
200 |
160 local_setup %gray{* fn lthy => |
201 local_setup %gray{* fn lthy => |
161 let |
202 let |
162 val orules = [@{prop "even 0"}, |
|
163 @{prop "\<forall>n::nat. odd n \<longrightarrow> even (Suc n)"}, |
|
164 @{prop "\<forall>n::nat. even n \<longrightarrow> odd (Suc n)"}] |
|
165 val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}] |
|
166 val pred = @{term "even::nat\<Rightarrow>bool"} |
203 val pred = @{term "even::nat\<Rightarrow>bool"} |
167 val arg_tys = [@{typ "nat"}] |
204 val arg_tys = [@{typ "nat"}] |
168 val def = defs_aux lthy orules preds (pred, arg_tys) |
205 val def = defs_aux lthy eo_orules eo_preds (pred, arg_tys) |
169 in |
206 in |
170 warning (Syntax.string_of_term lthy def); lthy |
207 warning (Syntax.string_of_term lthy def); lthy |
171 end *} |
208 end *} |
172 |
209 |
173 text {* |
210 text {* |
174 It calls @{ML defs_aux} for the definition of @{text "even"} and prints |
211 The testcase calls @{ML defs_aux} for the predicate @{text "even"} and prints |
175 out the definition. So we obtain as printout |
212 out the generated definition. So we obtain as printout |
176 |
213 |
177 @{text [display] |
214 @{text [display] |
178 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
215 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
179 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"} |
216 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"} |
180 |
217 |
199 meta-quanti\-fications. In Line 4, we transform these introduction rules into |
236 meta-quanti\-fications. In Line 4, we transform these introduction rules into |
200 the object logic (since definitions cannot be stated with |
237 the object logic (since definitions cannot be stated with |
201 meta-connectives). To do this transformation we have to obtain the theory |
238 meta-connectives). To do this transformation we have to obtain the theory |
202 behind the local theory (Line 3); with this theory we can use the function |
239 behind the local theory (Line 3); with this theory we can use the function |
203 @{ML ObjectLogic.atomize_term} to make the transformation (Line 4). The call |
240 @{ML ObjectLogic.atomize_term} to make the transformation (Line 4). The call |
204 to @{ML defs_aux} in Line 5 produces all left-hand sides of the |
241 to @{ML defs_aux} in Line 5 produces all right-hand sides of the |
205 definitions. The actual definitions are then made in Line 7. The result |
242 definitions. The actual definitions are then made in Line 7. The result |
206 of the function is a list of theorems and a local theory. A testcase for |
243 of the function is a list of theorems and a local theory. A testcase for |
207 this function is |
244 this function is |
208 *} |
245 *} |
209 |
246 |
210 local_setup %gray {* fn lthy => |
247 local_setup %gray {* fn lthy => |
211 let |
248 let |
212 val rules = [@{prop "even 0"}, |
249 val (defs, lthy') = |
213 @{prop "\<And>n::nat. odd n \<Longrightarrow> even (Suc n)"}, |
250 definitions eo_rules eo_preds eo_prednames eo_syns eo_arg_tyss lthy |
214 @{prop "\<And>n::nat. even n \<Longrightarrow> odd (Suc n)"}] |
251 in |
215 val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}] |
252 warning (str_of_thms_no_vars lthy' defs); lthy |
216 val prednames = [@{binding "even"}, @{binding "odd"}] |
|
217 val syns = [NoSyn, NoSyn] |
|
218 val arg_tyss = [[@{typ "nat"}], [@{typ "nat"}]] |
|
219 val (defs, lthy') = definitions rules preds prednames syns arg_tyss lthy |
|
220 in |
|
221 warning (str_of_thms_no_vars lthy' defs); lthy' |
|
222 end *} |
253 end *} |
223 |
254 |
224 text {* |
255 text {* |
225 where we feed into the functions all parameters corresponding to |
256 where we feed into the functions all parameters corresponding to |
226 the @{text even}-@{text odd} example. The definitions we obtain |
257 the @{text even}-@{text odd} example. The definitions we obtain |
227 are: |
258 are: |
228 |
259 |
229 \begin{isabelle} |
260 \begin{isabelle} |
230 \isacommand{thm}~@{text "even_def odd_def"}\\ |
|
231 @{text [break] |
261 @{text [break] |
232 "> even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
262 "> even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
233 > \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z, |
263 > \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z, |
234 > odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
264 > odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
235 > \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"} |
265 > \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"} |
236 \end{isabelle} |
266 \end{isabelle} |
237 |
267 |
|
268 Note that in the testcase we return the local theory @{text lthy} |
|
269 (not the modified @{text lthy'}). As a result the test case has no effect |
|
270 on the ambient theory. The reason is that if we make again the |
|
271 definition, we pollute the name space with two versions of @{text "even"} |
|
272 and @{text "odd"}. |
238 |
273 |
239 This completes the code for making the definitions. Next we deal with |
274 This completes the code for making the definitions. Next we deal with |
240 the induction principles. Recall that the proof of the induction principle |
275 the induction principles. |
|
276 *} |
|
277 |
|
278 subsection {* Introduction Rules *} |
|
279 |
|
280 text {* |
|
281 Recall that the proof of the induction principle |
241 for @{text "even"} was: |
282 for @{text "even"} was: |
242 *} |
283 *} |
243 |
284 |
244 lemma man_ind_principle: |
285 lemma manual_ind_prin: |
245 assumes prems: "even n" |
286 assumes prem: "even n" |
246 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n" |
287 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n" |
247 apply(atomize (full)) |
288 apply(atomize (full)) |
248 apply(cut_tac prems) |
289 apply(cut_tac prems) |
249 apply(unfold even_def) |
290 apply(unfold even_def) |
250 apply(drule spec[where x=P]) |
291 apply(drule spec[where x=P]) |
293 text {* |
335 text {* |
294 Now the complete tactic for proving the induction principles can |
336 Now the complete tactic for proving the induction principles can |
295 be implemented as follows: |
337 be implemented as follows: |
296 *} |
338 *} |
297 |
339 |
298 ML %linenosgray{*fun induction_tac defs prems insts = |
340 ML %linenosgray{*fun induction_tac defs prem insts = |
299 EVERY1 [ObjectLogic.full_atomize_tac, |
341 EVERY1 [ObjectLogic.full_atomize_tac, |
300 cut_facts_tac prems, |
342 cut_facts_tac prem, |
301 K (rewrite_goals_tac defs), |
343 K (rewrite_goals_tac defs), |
302 inst_spec_tac insts, |
344 inst_spec_tac insts, |
303 assume_tac]*} |
345 assume_tac]*} |
304 |
346 |
305 text {* |
347 text {* |
306 We only have to give it the definitions, the premise (like @{text "even n"}) |
348 We have to give it as arguments the definitions, the premise |
307 and the instantiations as arguments. Compare this with the manual proof |
349 (for example @{text "even n"}) and the instantiations. Compare this with the |
308 given for the lemma @{thm [source] man_ind_principle}: there is almos a |
350 manual proof given for the lemma @{thm [source] manual_ind_prin}: |
309 one-to-one correspondence between the \isacommand{apply}-script and the |
351 as you can see there is almost a one-to-one correspondence between the \isacommand{apply}-script |
310 @{ML induction_tac}. A testcase for this tactic is the function |
352 and the @{ML induction_tac}. A testcase for this tactic is the function |
311 *} |
353 *} |
312 |
354 |
313 ML{*fun test_tac prems = |
355 ML{*fun test_tac prem = |
314 let |
356 let |
315 val defs = [@{thm even_def}, @{thm odd_def}] |
|
316 val insts = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] |
357 val insts = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] |
317 in |
358 in |
318 induction_tac defs prems insts |
359 induction_tac eo_defs prem insts |
319 end*} |
360 end*} |
320 |
361 |
321 text {* |
362 text {* |
322 which indeed proves the induction principle: |
363 which indeed proves the induction principle: |
323 *} |
364 *} |
324 |
365 |
325 lemma auto_ind_principle: |
366 lemma automatic_ind_prin: |
326 assumes prems: "even n" |
367 assumes prem: "even z" |
327 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n" |
368 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z" |
328 apply(tactic {* test_tac @{thms prems} *}) |
369 apply(tactic {* test_tac @{thms prem} *}) |
329 done |
370 done |
330 |
371 |
331 text {* |
372 text {* |
332 While the tactic for the induction principle is relatively simple, |
373 While the tactic for the induction principle is relatively simple, |
333 it is a bit harder to construct the goals from the introduction |
374 it is a bit harder to construct the goals from the introduction |
334 rules the user provides. In general we have to construct for each predicate |
375 rules the user provides. In general we have to construct for each predicate |
335 @{text "pred"} a goal of the form |
376 @{text "pred"} a goal of the form |
336 |
377 |
337 @{text [display] |
378 @{text [display] |
338 "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P$ ?zs"} |
379 "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"} |
339 |
380 |
340 where the predicates @{text preds} are replaced in the introduction |
381 where the predicates @{text preds} are replaced in the introduction |
341 rules by new distinct variables written @{text "Ps"}. |
382 rules by new distinct variables @{text "?Ps"}. |
342 We also need to generate fresh arguments for the predicate @{text "pred"} in |
383 We also need to generate fresh arguments @{text "?zs"} for the predicate |
343 the premise and the @{text "?P"} in the conclusion. Note |
384 @{text "pred"} and the @{text "?P"} in the conclusion. Note |
344 that the @{text "?Ps"} and @{text "?zs"} need to be |
385 that the @{text "?Ps"} and @{text "?zs"} need to be |
345 schematic variables that can be instantiated. This corresponds to what the |
386 schematic variables that can be instantiated by the user. |
346 @{thm [source] auto_ind_principle} looks like: |
387 |
347 |
388 We generate these goals in two steps. The first function expects that the |
348 \begin{isabelle} |
389 introduction rules are already appropriately substituted. The argument |
349 \isacommand{thm}~@{thm [source] auto_ind_principle}\\ |
390 @{text "srules"} stands for these substituted rules; @{text cnewpreds} are |
350 @{text "> \<lbrakk>even ?n; ?P 0; \<And>m. ?Q m \<Longrightarrow> ?P (Suc m); \<And>m. ?P m \<Longrightarrow> ?Q (Suc m)\<rbrakk> \<Longrightarrow> ?P ?n"} |
391 the certified terms coresponding to the variables @{text "?Ps"}; @{text |
351 \end{isabelle} |
392 "pred"} is the predicate for which we prove the introduction principle; |
352 |
393 @{text "newpred"} is its replacement and @{text "arg_tys"} are the argument |
353 We achieve |
394 types of this predicate. |
354 that in two steps. |
395 *} |
355 |
396 |
356 The function below expects that the introduction rules are already appropriately |
397 ML %linenosgray{*fun prove_induction lthy defs srules cnewpreds ((pred, newpred), arg_tys) = |
357 substituted. The argument @{text "srules"} stands for these substituted |
|
358 rules; @{text cnewpreds} are the certified terms coresponding |
|
359 to the variables @{text "Ps"}; @{text "pred"} is the predicate for |
|
360 which we prove the introduction principle; @{text "newpred"} is its |
|
361 replacement and @{text "tys"} are the argument types of this predicate. |
|
362 *} |
|
363 |
|
364 ML %linenosgray{*fun prove_induction lthy defs srules cnewpreds ((pred, newpred), arg_tys) = |
|
365 let |
398 let |
366 val zs = replicate (length arg_tys) "z" |
399 val zs = replicate (length arg_tys) "z" |
367 val (newargnames, lthy') = Variable.variant_fixes zs lthy; |
400 val (newargnames, lthy') = Variable.variant_fixes zs lthy; |
368 val newargs = map Free (newargnames ~~ arg_tys) |
401 val newargs = map Free (newargnames ~~ arg_tys) |
369 |
402 |
378 |
411 |
379 text {* |
412 text {* |
380 In Line 3 we produce names @{text "zs"} for each type in the |
413 In Line 3 we produce names @{text "zs"} for each type in the |
381 argument type list. Line 4 makes these names unique and declares them as |
414 argument type list. Line 4 makes these names unique and declares them as |
382 \emph{free} (but fixed) variables in the local theory @{text "lthy'"}. In |
415 \emph{free} (but fixed) variables in the local theory @{text "lthy'"}. In |
383 Line 5 we just construct the terms corresponding to these variables. |
416 Line 5 we construct the terms corresponding to these variables. |
384 The term variables are applied to the predicate in Line 7 (this corresponds |
417 The variables are applied to the predicate in Line 7 (this corresponds |
385 to the first premise @{text "pred zs"} of the induction principle). |
418 to the first premise @{text "pred zs"} of the induction principle). |
386 In Line 8 and 9, we first construct the term @{text "P zs"} |
419 In Line 8 and 9, we first construct the term @{text "P zs"} |
387 and then add the (substituded) introduction rules as premises. In case that |
420 and then add the (substituded) introduction rules as premises. In case that |
388 no introduction rules are given, the conclusion of this implication needs |
421 no introduction rules are given, the conclusion of this implication needs |
389 to be wrapped inside a @{term Trueprop}, otherwise the Isabelle's goal |
422 to be wrapped inside a @{term Trueprop}, otherwise the Isabelle's goal |
390 mechanism will fail. |
423 mechanism will fail. |
391 |
424 |
392 In Line 11 we set up the goal to be proved; in the next line we call the tactic |
425 In Line 11 we set up the goal to be proved; in the next line we call the |
393 for proving the induction principle. This tactic expects the definitions, the |
426 tactic for proving the induction principle. As mentioned before, this tactic |
394 premise and the (certified) predicates with which the introduction rules |
427 expects the definitions, the premise and the (certified) predicates with |
395 have been substituted. The code in these two lines will return a theorem. |
428 which the introduction rules have been substituted. The code in these two |
396 However, it is a theorem |
429 lines will return a theorem. However, it is a theorem |
397 proved inside the local theory @{text "lthy'"}, where the variables @{text |
430 proved inside the local theory @{text "lthy'"}, where the variables @{text |
398 "zs"} are fixed, but free. By exporting this theorem from @{text |
431 "zs"} are fixed, but free. By exporting this theorem from @{text |
399 "lthy'"} (which contains the @{text "zs"} as free) to @{text |
432 "lthy'"} (which contains the @{text "zs"} as free) to @{text |
400 "lthy"} (which does not), we obtain the desired schematic variables. |
433 "lthy"} (which does not), we obtain the desired schematic variables @{text "?zs"}. |
|
434 A testcase for this function is |
401 *} |
435 *} |
402 |
436 |
403 local_setup %gray{* fn lthy => |
437 local_setup %gray{* fn lthy => |
404 let |
438 let |
405 val defs = [@{thm even_def}, @{thm odd_def}] |
|
406 val srules = [@{prop "P (0::nat)"}, |
439 val srules = [@{prop "P (0::nat)"}, |
407 @{prop "\<And>n::nat. Q n \<Longrightarrow> P (Suc n)"}, |
440 @{prop "\<And>n::nat. Q n \<Longrightarrow> P (Suc n)"}, |
408 @{prop "\<And>n::nat. P n \<Longrightarrow> Q (Suc n)"}] |
441 @{prop "\<And>n::nat. P n \<Longrightarrow> Q (Suc n)"}] |
409 val cnewpreds = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] |
442 val cnewpreds = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] |
410 val pred = @{term "even::nat\<Rightarrow>bool"} |
443 val pred = @{term "even::nat\<Rightarrow>bool"} |
411 val newpred = @{term "P::nat\<Rightarrow>bool"} |
444 val newpred = @{term "P::nat\<Rightarrow>bool"} |
412 val arg_tys = [@{typ "nat"}] |
445 val arg_tys = [@{typ "nat"}] |
413 val intro = |
446 val intro = |
414 prove_induction lthy defs srules cnewpreds ((pred, newpred), arg_tys) |
447 prove_induction lthy eo_defs srules cnewpreds ((pred, newpred), arg_tys) |
415 in |
448 in |
416 warning (str_of_thm lthy intro); lthy |
449 warning (str_of_thm lthy intro); lthy |
417 end *} |
450 end *} |
418 |
451 |
419 text {* |
452 text {* |
422 @{text [display] |
455 @{text [display] |
423 " \<lbrakk>even ?z; P 0; \<And>n. Q n \<Longrightarrow> P (Suc n); \<And>n. P n \<Longrightarrow> Q (Suc n)\<rbrakk> \<Longrightarrow> P ?z"} |
456 " \<lbrakk>even ?z; P 0; \<And>n. Q n \<Longrightarrow> P (Suc n); \<And>n. P n \<Longrightarrow> Q (Suc n)\<rbrakk> \<Longrightarrow> P ?z"} |
424 |
457 |
425 Note that the export from @{text lthy'} to @{text lthy} in Line 13 above |
458 Note that the export from @{text lthy'} to @{text lthy} in Line 13 above |
426 has turned the free, but fixed, @{text "z"} into a schematic |
459 has turned the free, but fixed, @{text "z"} into a schematic |
427 variable @{text "?z"}. |
460 variable @{text "?z"}. The @{text "P"} and @{text "Q"} are not yet |
|
461 schematic. |
428 |
462 |
429 We still have to produce the new predicates with which the introduction |
463 We still have to produce the new predicates with which the introduction |
430 rules are substituted and iterate @{ML prove_induction} over all |
464 rules are substituted and iterate @{ML prove_induction} over all |
431 predicates. This is what the next function does. |
465 predicates. This is what the second function does: |
432 *} |
466 *} |
433 |
467 |
434 ML %linenosgray{*fun inductions rules defs preds arg_tyss lthy = |
468 ML %linenosgray{*fun inductions rules defs preds arg_tyss lthy = |
435 let |
469 let |
436 val Ps = replicate (length preds) "P" |
470 val Ps = replicate (length preds) "P" |
448 (preds ~~ newpreds ~~ arg_tyss) |
482 (preds ~~ newpreds ~~ arg_tyss) |
449 |> ProofContext.export lthy' lthy |
483 |> ProofContext.export lthy' lthy |
450 end*} |
484 end*} |
451 |
485 |
452 text {* |
486 text {* |
453 In Line 3 we generate a string @{text [quotes] "P"} for each predicate. |
487 In Line 3, we generate a string @{text [quotes] "P"} for each predicate. |
454 In Line 4, we use the same trick as in the previous function, that is making the |
488 In Line 4, we use the same trick as in the previous function, that is making the |
455 @{text "Ps"} fresh and declaring them as fixed, but free, in |
489 @{text "Ps"} fresh and declaring them as fixed, but free, in |
456 the new local theory @{text "lthy'"}. From the local theory we extract |
490 the new local theory @{text "lthy'"}. From the local theory we extract |
457 the ambient theory in Line 6. We need this theory in order to certify |
491 the ambient theory in Line 6. We need this theory in order to certify |
458 the new predicates. In Line 8 we calculate the types of these new predicates |
492 the new predicates. In Line 8, we construct the types of these new predicates |
459 using the given argument types. Next we turn them into terms and subsequently |
493 using the given argument types. Next we turn them into terms and subsequently |
460 certify them (Line 9 and 10). We can now produce the substituted introduction rules |
494 certify them (Line 9 and 10). We can now produce the substituted introduction rules |
461 (Line 11) using the function @{ML subst_free}. Line 14 and 15 just iterate |
495 (Line 11) using the function @{ML subst_free}. Line 14 and 15 just iterate |
462 the proofs for all predicates. |
496 the proofs for all predicates. |
463 From this we obtain a list of theorems. Finally we need to export the |
497 From this we obtain a list of theorems. Finally we need to export the |
464 fixed variables @{text "Ps"} to obtain the schematic variables |
498 fixed variables @{text "Ps"} to obtain the schematic variables @{text "?Ps"} |
465 (Line 16). |
499 (Line 16). |
466 |
500 |
467 A testcase for this function is |
501 A testcase for this function is |
468 *} |
502 *} |
469 |
503 |
470 local_setup %gray {* fn lthy => |
504 local_setup %gray {* fn lthy => |
471 let |
505 let |
472 val rules = [@{prop "even (0::nat)"}, |
506 val ind_thms = inductions eo_rules eo_defs eo_preds eo_arg_tyss lthy |
473 @{prop "\<And>n::nat. odd n \<Longrightarrow> even (Suc n)"}, |
|
474 @{prop "\<And>n::nat. even n \<Longrightarrow> odd (Suc n)"}] |
|
475 val defs = [@{thm even_def}, @{thm odd_def}] |
|
476 val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}] |
|
477 val tyss = [[@{typ "nat"}], [@{typ "nat"}]] |
|
478 val ind_thms = inductions rules defs preds tyss lthy |
|
479 in |
507 in |
480 warning (str_of_thms lthy ind_thms); lthy |
508 warning (str_of_thms lthy ind_thms); lthy |
481 end *} |
509 end *} |
482 |
510 |
483 |
511 |
488 "> even ?z \<Longrightarrow> ?P1 0 \<Longrightarrow> |
516 "> even ?z \<Longrightarrow> ?P1 0 \<Longrightarrow> |
489 > (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?P1 ?z, |
517 > (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?P1 ?z, |
490 > odd ?z \<Longrightarrow> ?P1 0 |
518 > odd ?z \<Longrightarrow> ?P1 0 |
491 > \<Longrightarrow> (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?Pa1 ?z"} |
519 > \<Longrightarrow> (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?Pa1 ?z"} |
492 |
520 |
493 |
521 Note that now both, the @{text "?Ps"} and the @{text "?zs"}, are schematic |
494 Note that now both, the @{text "Ps"} and the @{text "zs"}, are schematic |
|
495 variables. The numbers have been introduced by the pretty-printer and are |
522 variables. The numbers have been introduced by the pretty-printer and are |
496 not significant. |
523 not significant. |
497 |
524 |
498 This completes the code for the induction principles. Finally we can prove the |
525 This completes the code for the induction principles. |
499 introduction rules. Their proofs are quite a bit more involved. To ease them |
526 *} |
500 somewhat we use the following two helper function. |
527 |
|
528 subsection {* Introduction Rules *} |
|
529 |
|
530 text {* |
|
531 Finally we can prove the introduction rules. Their proofs are quite a bit |
|
532 more involved. To ease these proofs somewhat we use the following two helper |
|
533 functions. |
|
534 |
501 *} |
535 *} |
502 |
536 |
503 ML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct) |
537 ML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct) |
504 val imp_elims = fold (fn th => fn th' => [th', th] MRS @{thm mp})*} |
538 val imp_elims = fold (fn th => fn th' => [th', th] MRS @{thm mp})*} |
505 |
539 |
506 text {* |
540 text {* |
507 To see what they do, let us suppose whe have the follwoing three |
541 To see what these functions do, let us suppose whe have the following three |
508 theorems. |
542 theorems. |
509 *} |
543 *} |
510 |
544 |
511 lemma all_elims_test: |
545 lemma all_elims_test: |
512 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" |
546 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" |
546 ML {* prems_of *} |
580 ML {* prems_of *} |
547 ML {* Logic.strip_params *} |
581 ML {* Logic.strip_params *} |
548 ML {* Logic.strip_assums_hyp *} |
582 ML {* Logic.strip_assums_hyp *} |
549 |
583 |
550 ML {* |
584 ML {* |
551 fun chop_print_tac m n ctxt thm = |
585 fun chop_print (params1, params2) (prems1, prems2) ctxt = |
552 let |
586 let |
553 val [trm] = prems_of thm |
|
554 val params = map fst (Logic.strip_params trm) |
|
555 val prems = Logic.strip_assums_hyp trm |
|
556 val (prems1, prems2) = chop (length prems - m) prems; |
|
557 val (params1, params2) = chop (length params - n) params; |
|
558 val _ = warning (Syntax.string_of_term ctxt trm) |
|
559 val _ = warning (commas params) |
|
560 val _ = warning (commas (map (Syntax.string_of_term ctxt) prems)) |
|
561 val _ = warning ((commas params1) ^ " | " ^ (commas params2)) |
587 val _ = warning ((commas params1) ^ " | " ^ (commas params2)) |
562 val _ = warning ((commas (map (Syntax.string_of_term ctxt) prems1)) ^ " | " ^ |
588 val _ = warning ((commas (map (Syntax.string_of_term ctxt) prems1)) ^ " | " ^ |
563 (commas (map (Syntax.string_of_term ctxt) prems2))) |
589 (commas (map (Syntax.string_of_term ctxt) prems2))) |
564 in |
590 in |
565 Seq.single thm |
591 () |
566 end |
592 end |
567 *} |
593 *} |
568 |
594 |
569 ML {* METAHYPS *} |
595 |
570 |
|
571 ML {* |
|
572 fun chop_print_tac2 ctxt prems = |
|
573 let |
|
574 val _ = warning (commas (map (str_of_thm_no_vars ctxt) prems)) |
|
575 in |
|
576 all_tac |
|
577 end |
|
578 *} |
|
579 |
596 |
580 lemma intro1: |
597 lemma intro1: |
581 shows "\<And>m. odd m \<Longrightarrow> even (Suc m)" |
598 shows "\<And>m. odd m \<Longrightarrow> even (Suc m)" |
582 apply(tactic {* ObjectLogic.rulify_tac 1 *}) |
599 apply(tactic {* ObjectLogic.rulify_tac 1 *}) |
583 apply(tactic {* rewrite_goals_tac [@{thm even_def}, @{thm odd_def}] *}) |
600 apply(tactic {* rewrite_goals_tac [@{thm even_def}, @{thm odd_def}] *}) |
584 apply(tactic {* REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1) *}) |
601 apply(tactic {* REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1) *}) |
585 apply(tactic {* chop_print_tac 3 2 @{context} *}) |
|
586 oops |
602 oops |
587 |
603 |
588 ML {* |
604 ML {* fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac *} |
589 fun SUBPROOF_test tac ctxt = |
|
590 SUBPROOF (fn {params, prems, context,...} => |
|
591 let |
|
592 val thy = ProofContext.theory_of context |
|
593 in |
|
594 tac (params, prems, context) |
|
595 THEN Method.insert_tac prems 1 |
|
596 THEN print_tac "SUBPROOF Test" |
|
597 THEN SkipProof.cheat_tac thy |
|
598 end) ctxt 1 |
|
599 *} |
|
600 |
|
601 |
|
602 |
605 |
603 |
606 |
604 lemma fresh_App: |
607 lemma fresh_App: |
605 shows "\<And>a t s. \<lbrakk>a\<sharp>t; a\<sharp>s\<rbrakk> \<Longrightarrow> a\<sharp>App t s" |
608 shows "\<And>a t s. \<lbrakk>a\<sharp>t; a\<sharp>s\<rbrakk> \<Longrightarrow> a\<sharp>App t s" |
606 apply(tactic {* ObjectLogic.rulify_tac 1 *}) |
609 apply(tactic {* ObjectLogic.rulify_tac 1 *}) |
607 apply(tactic {* rewrite_goals_tac [@{thm fresh_def}] *}) |
610 apply(tactic {* rewrite_goals_tac [@{thm fresh_def}] *}) |
608 apply(tactic {* REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1) *}) |
611 apply(tactic {* REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1) *}) |
|
612 apply(tactic {* print_tac "" *}) |
|
613 apply(tactic {* SUBPROOF_test (fn {params, prems, ...} => |
|
614 let |
|
615 val (prems1, prems2) = chop (length prems - length fresh_rules) prems |
|
616 val (params1, params2) = chop (length params - length fresh_preds) params |
|
617 in |
|
618 no_tac |
|
619 end) @{context} *}) |
609 oops |
620 oops |
610 (* |
621 |
611 apply(tactic {* SUBPROOF_test |
|
612 (fn (params, prems, ctxt) => |
|
613 let |
|
614 val (prems1, prems2) = chop (length prems - 4) prems; |
|
615 val (params1, params2) = chop (length params - 1) params; |
|
616 in |
|
617 rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 2))) 1 |
|
618 end) @{context} *}) |
|
619 *) |
|
620 |
622 |
621 ML{*fun subproof2 prem params2 prems2 = |
623 ML{*fun subproof2 prem params2 prems2 = |
622 SUBPROOF (fn {prems, ...} => |
624 SUBPROOF (fn {prems, ...} => |
623 let |
625 let |
624 val prem' = prems MRS prem; |
626 val prem' = prems MRS prem; |