183 val prednames = [Binding.name "even", Binding.name "odd"] |
188 val prednames = [Binding.name "even", Binding.name "odd"] |
184 val syns = [NoSyn, NoSyn] |
189 val syns = [NoSyn, NoSyn] |
185 val arg_tyss = [[@{typ "nat"}], [@{typ "nat"}]] |
190 val arg_tyss = [[@{typ "nat"}], [@{typ "nat"}]] |
186 val (defs, lthy') = definitions rules preds prednames syns arg_tyss lthy |
191 val (defs, lthy') = definitions rules preds prednames syns arg_tyss lthy |
187 in |
192 in |
188 warning (str_of_thms lthy' defs); lthy |
193 warning (str_of_thms lthy' defs); lthy' |
189 end *} |
194 end *} |
190 |
195 |
191 text {* |
196 text {* |
192 |
197 |
193 It prints out the two definitions |
198 \begin{isabelle} |
194 |
199 \isacommand{thm}~@{text "even_def odd_def"}\\ |
195 @{text [display] |
200 @{text [break] |
196 "even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
201 "> even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
197 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z, |
202 > \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z, |
198 odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
203 > odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) |
199 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"} |
204 > \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"} |
|
205 \end{isabelle} |
|
206 |
200 |
207 |
201 This completes the code concerning the definitions. Next comes the code for |
208 This completes the code concerning the definitions. Next comes the code for |
202 the induction principles. |
209 the induction principles. |
203 |
210 |
204 Recall the proof for the induction principle for @{term "even"}: |
211 Let us now turn to the induction principles. Recall that the proof of the |
|
212 induction principle for @{term "even"} was: |
205 *} |
213 *} |
206 |
214 |
207 lemma |
215 lemma |
208 assumes prems: "even n" |
216 assumes prems: "even n" |
209 shows "P 0 \<Longrightarrow> |
217 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n" |
210 (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n" |
|
211 apply(atomize (full)) |
218 apply(atomize (full)) |
212 apply(cut_tac prems) |
219 apply(cut_tac prems) |
213 apply(unfold even_def) |
220 apply(unfold even_def) |
214 apply(drule spec[where x=P]) |
221 apply(drule spec[where x=P]) |
215 apply(drule spec[where x=Q]) |
222 apply(drule spec[where x=Q]) |
216 apply(assumption) |
223 apply(assumption) |
217 done |
224 done |
218 |
225 |
219 text {* |
226 text {* |
220 To automate this proof we need to be able to instantiate universal |
227 We have to implement code that constructs the induction principle and then |
221 quantifiers. For this we use the following helper function. It |
228 a tactic that automatically proves it. |
222 instantiates the @{text "?x"} in @{thm spec} with a @{ML_type cterm}. |
229 |
|
230 The tactic will use the following helper function for instantiating universal |
|
231 quantifiers. This function instantiates the @{text "?x"} in the theorem |
|
232 @{thm spec} with a given @{ML_type cterm}. |
223 *} |
233 *} |
224 |
234 |
225 ML{*fun inst_spec ctrm = |
235 ML{*fun inst_spec ctrm = |
226 Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*} |
236 Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*} |
227 |
237 |
228 text {* |
238 text {* |
229 For example we can use it to instantiate an assumption: |
239 For example we can use it in the following proof to instantiate the |
230 *} |
240 three quantifiers in the assumption. We use the tactic |
|
241 *} |
|
242 |
|
243 ML{*fun inst_spec_tac ctrms = |
|
244 EVERY' (map (dtac o inst_spec) ctrms)*} |
|
245 |
|
246 text {* |
|
247 and then apply use it with the @{ML_type cterm}s @{text "y1\<dots>y3"}. |
|
248 *} |
231 |
249 |
232 lemma "\<forall>(x1::nat) (x2::nat) (x3::nat). P x1 x2 x3 \<Longrightarrow> True" |
250 lemma "\<forall>(x1::nat) (x2::nat) (x3::nat). P x1 x2 x3 \<Longrightarrow> True" |
233 apply (tactic {* |
251 apply (tactic {* |
234 let |
252 inst_spec_tac [@{cterm "y1::nat"},@{cterm "y2::nat"},@{cterm "y3::nat"}] 1 *}) |
235 val ctrms = [@{cterm "y1::nat"},@{cterm "y2::nat"},@{cterm "y3::nat"}] |
|
236 in |
|
237 EVERY1 (map (dtac o inst_spec) ctrms) |
|
238 end *}) |
|
239 txt {* |
253 txt {* |
240 where it produces the goal state |
254 We obtain the goal state |
241 |
255 |
242 \begin{minipage}{\textwidth} |
256 \begin{minipage}{\textwidth} |
243 @{subgoals} |
257 @{subgoals} |
244 \end{minipage}*} |
258 \end{minipage}*} |
245 (*<*)oops(*>*) |
259 (*<*)oops(*>*) |
246 |
260 |
247 text {* |
261 text {* |
248 Now the tactic for proving the induction rules can be implemented |
262 Now the complete tactic for proving the induction principles can |
249 as follows |
263 be implemented as follows: |
250 *} |
264 *} |
251 |
265 |
252 ML %linenosgray{*fun induction_tac defs prems insts = |
266 ML %linenosgray{*fun induction_tac defs prems insts = |
253 EVERY1 [ObjectLogic.full_atomize_tac, |
267 EVERY1 [ObjectLogic.full_atomize_tac, |
254 cut_facts_tac prems, |
268 cut_facts_tac prems, |
255 K (rewrite_goals_tac defs), |
269 K (rewrite_goals_tac defs), |
256 EVERY' (map (dtac o inst_spec) insts), |
270 inst_spec_tac insts, |
257 assume_tac]*} |
271 assume_tac]*} |
258 |
272 |
259 text {* |
273 text {* |
260 We only have to give it as arguments the premises and the instantiations. |
274 We only have to give it as arguments the premises and the instantiations. |
261 A testcase for the tactic is |
275 A testcase for the tactic is |
262 *} |
276 *} |
263 |
277 |
|
278 ML{*fun test_tac prems = |
|
279 let |
|
280 val defs = [@{thm even_def}, @{thm odd_def}] |
|
281 val insts = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] |
|
282 in |
|
283 induction_tac defs prems insts |
|
284 end*} |
|
285 |
|
286 text {* |
|
287 which indeed proves the induction principle. |
|
288 *} |
|
289 |
264 lemma |
290 lemma |
265 assumes prems: "even n" |
291 assumes prems: "even n" |
266 shows "P 0 \<Longrightarrow> |
292 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n" |
267 (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n" |
293 apply(tactic {* test_tac @{thms prems} *}) |
268 apply(tactic {* |
|
269 let |
|
270 val defs = [@{thm even_def}, @{thm odd_def}] |
|
271 val insts = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] |
|
272 in |
|
273 induction_tac defs @{thms prems} insts |
|
274 end *}) |
|
275 done |
294 done |
276 |
295 |
277 |
296 text {* |
278 text {* |
|
279 which indeed proves the lemma. |
|
280 |
|
281 While the generic proof for the induction principle is relatively simple, |
297 While the generic proof for the induction principle is relatively simple, |
282 it is a bit harder to set up the goals just from the given introduction |
298 it is a bit harder to construct the goals from just the introduction |
283 rules. For this we have to construct for each predicate @{text "pred"} |
299 rules the user states. In general we have to construct for each predicate |
|
300 @{text "pred"} a goal of the form |
284 |
301 |
285 @{text [display] |
302 @{text [display] |
286 "\<And>\<^raw:$zs$>. pred \<^raw:$zs$> \<Longrightarrow> rules[preds := \<^raw:$Ps$>] \<Longrightarrow> \<^raw:$P$>\<^raw:$zs$>"} |
303 "\<And>\<^raw:$zs$>. pred \<^raw:$zs$> \<Longrightarrow> rules[preds := \<^raw:$Ps$>] \<Longrightarrow> \<^raw:$P$>\<^raw:$zs$>"} |
287 |
304 |
288 where the given predicates @{text preds} are replaced by new distinct |
305 where the given predicates @{text preds} are replaced in the introduction |
289 ones written as @{text "\<^raw:$Ps$>"}, and also need to be applied to |
306 rule @{text "rules"} by new distinct variables written as @{text "\<^raw:$Ps$>"}. |
290 new variables @{text "\<^raw:$zs$>"}. |
307 We also need to generate fresh arguments for the predicate @{text "pred"} and |
|
308 the @{text "\<^raw:$P$>"} in the conclusion of the induction principle. |
291 |
309 |
292 The function below expects that the rules are already appropriately |
310 The function below expects that the rules are already appropriately |
293 replaced. The argument @{text "mrules"} stands for these modified |
311 substitued. The argument @{text "srules"} stands for these substituted |
294 introduction rules; @{text cnewpreds} are the certified terms coresponding |
312 introduction rules; @{text cnewpreds} are the certified terms coresponding |
295 to the variables @{text "\<^raw:$Ps$>"}; @{text "pred"} is the predicate for |
313 to the variables @{text "\<^raw:$Ps$>"}; @{text "pred"} is the predicate for |
296 which we prove the introduction principle; @{text "newpred"} is its |
314 which we prove the introduction principle; @{text "newpred"} is its |
297 replacement and @{text "tys"} are the types of its argument. |
315 replacement and @{text "tys"} are the argument types of this predicate. |
298 *} |
316 *} |
299 |
317 |
300 ML %linenosgray{* fun prove_induction lthy defs mrules cnewpreds ((pred, newpred), tys) = |
318 ML %linenosgray{*fun prove_induction lthy defs srules cnewpreds ((pred, newpred), tys) = |
301 let |
319 let |
302 val zs = replicate (length tys) "z" |
320 val zs = replicate (length tys) "z" |
303 val (newargnames, lthy') = Variable.variant_fixes zs lthy; |
321 val (newargnames, lthy') = Variable.variant_fixes zs lthy; |
304 val newargs = map Free (newargnames ~~ tys) |
322 val newargs = map Free (newargnames ~~ tys) |
305 |
323 |
306 val prem = HOLogic.mk_Trueprop (list_comb (pred, newargs)) |
324 val prem = HOLogic.mk_Trueprop (list_comb (pred, newargs)) |
307 val goal = Logic.list_implies |
325 val goal = Logic.list_implies |
308 (mrules, HOLogic.mk_Trueprop (list_comb (newpred, newargs))) |
326 (srules, HOLogic.mk_Trueprop (list_comb (newpred, newargs))) |
309 in |
327 in |
310 Goal.prove lthy' [] [prem] goal |
328 Goal.prove lthy' [] [prem] goal |
311 (fn {prems, ...} => induction_tac defs prems cnewpreds) |
329 (fn {prems, ...} => induction_tac defs prems cnewpreds) |
312 |> singleton (ProofContext.export lthy' lthy) |
330 |> singleton (ProofContext.export lthy' lthy) |
313 end *} |
331 end *} |
314 |
332 |
315 text {* |
333 text {* |
316 In Line 3 we produce a list of names @{text "\<^raw:$zs$>"} according to the type |
334 In Line 3 we produce a name @{text "\<^raw:$zs$>"} for each type in the |
317 list. Line 4 makes these names unique and declare them as \emph{free} (but fixed) |
335 argument type list. Line 4 makes these names unique and declares them as |
318 variables. These variables are free in the new theory @{text "lthy'"}. In Line 5 |
336 \emph{free} (but fixed) variables in the local theory @{text "lthy'"}. In |
319 we just construct the terms corresponding to the variables. The term variables are |
337 Line 5 we just construct the terms corresponding to these variables. |
320 applied to the predicate in Line 7 (this is the first premise |
338 The term variables are applied to the predicate in Line 7 (this corresponds |
321 @{text "pred \<^raw:$zs$>"} of the induction principle). In Line 8 and 9 |
339 to the first premise @{text "pred \<^raw:$zs$>"} of the induction principle). |
322 we first the term @{text "\<^raw:$P$>\<^raw:$zs$>"} and then add |
340 In Line 8 and 9, we first construct the term @{text "\<^raw:$P$>\<^raw:$zs$>"} |
323 the (modified) introduction rules as premises. |
341 and then add the (modified) introduction rules as premises. In case that |
324 |
342 no introduction rules are given, the conclusion of this implications needs |
325 In Line 11 we set up the goal to be proved; call the induction tactic in |
343 to be wrapped inside a @{term Trueprop}, otherwise the Isabelle's goal |
326 Line 13. This returns a theorem. However, it is a theorem proved inside |
344 mechanism will fail. |
327 the local theory @{text "lthy'"} where the variables @{text "\<^raw:$zs$>"} are |
345 |
328 fixed, but free. By exporting this theorem from @{text "lthy'"} (which does contain |
346 In Line 11 we set up the goal to be proved; then call the tactic for proving the |
329 the @{text "\<^raw:$zs$>"} as free) to @{text "lthy"} (which does not), we |
347 induction principle. This tactic expects the (certified) predicates with which |
330 obtain the desired quantifications @{text "\<And>\<^raw:$zs$>"}. |
348 the introduction rules have been substituted. This will return a theorem. |
331 |
349 However, it is a theorem proved inside the local theory @{text "lthy'"} where |
332 So it is left to produce the modified rules and |
350 the variables @{text "\<^raw:$zs$>"} are fixed, but free. By exporting this |
333 *} |
351 theorem from @{text "lthy'"} (which contains the @{text "\<^raw:$zs$>"} |
334 |
352 as free) to @{text "lthy"} (which does not), we obtain the desired quantifications |
335 ML %linenosgray{*fun inductions rules defs preds tyss lthy1 = |
353 @{text "\<And>\<^raw:$zs$>"}. |
|
354 |
|
355 Now it is left to produce the new predicated with which the introduction |
|
356 rules are substituted. |
|
357 *} |
|
358 |
|
359 ML %linenosgray{*fun inductions rules defs preds tyss lthy = |
336 let |
360 let |
337 val Ps = replicate (length preds) "P" |
361 val Ps = replicate (length preds) "P" |
338 val (newprednames, lthy2) = Variable.variant_fixes Ps lthy1 |
362 val (newprednames, lthy') = Variable.variant_fixes Ps lthy |
339 |
363 |
340 val thy = ProofContext.theory_of lthy2 |
364 val thy = ProofContext.theory_of lthy' |
341 |
365 |
342 val tyss' = map (fn tys => tys ---> HOLogic.boolT) tyss |
366 val tyss' = map (fn tys => tys ---> HOLogic.boolT) tyss |
343 val newpreds = map Free (newprednames ~~ tyss') |
367 val newpreds = map Free (newprednames ~~ tyss') |
344 val cnewpreds = map (cterm_of thy) newpreds |
368 val cnewpreds = map (cterm_of thy) newpreds |
345 val rules' = map (subst_free (preds ~~ newpreds)) rules |
369 val rules' = map (subst_free (preds ~~ newpreds)) rules |
346 |
370 |
347 in |
371 in |
348 map (prove_induction lthy2 defs rules' cnewpreds) |
372 map (prove_induction lthy' defs rules' cnewpreds) |
349 (preds ~~ newpreds ~~ tyss) |
373 (preds ~~ newpreds ~~ tyss) |
350 |> ProofContext.export lthy2 lthy1 |
374 |> ProofContext.export lthy' lthy |
351 end*} |
375 end*} |
352 |
376 |
353 ML {* |
377 ML {* |
354 let |
378 let |
355 val rules = [@{prop "even (0::nat)"}, |
379 val rules = [@{prop "even (0::nat)"}, |