3 begin |
3 begin |
4 |
4 |
5 section {* The Gory Details\label{sec:code} *} |
5 section {* The Gory Details\label{sec:code} *} |
6 |
6 |
7 text {* |
7 text {* |
8 As mentioned before the code falls roughly into three parts: the definitions, |
8 As mentioned before the code falls roughly into three parts: code that deals |
9 the induction principles and the introduction rules. In addition there is an |
9 with the definitions, the induction principles and the introduction rules, respectively. |
10 administrative function that strings everything together. |
10 In addition there are some administrative functions that string everything together. |
11 *} |
11 *} |
12 |
12 |
13 subsection {* Definitions *} |
13 subsection {* Definitions *} |
14 |
14 |
15 text {* |
15 text {* |
234 Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*} |
234 Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*} |
235 |
235 |
236 text {* |
236 text {* |
237 This helper function instantiates the @{text "?x"} in the theorem |
237 This helper function instantiates the @{text "?x"} in the theorem |
238 @{thm spec} with a given @{ML_type cterm}. We call this helper function |
238 @{thm spec} with a given @{ML_type cterm}. We call this helper function |
239 in the next tactic, called @{text inst_spec_tac}. |
239 in the following tactic, called @{text inst_spec_tac}. |
240 *} |
240 *} |
241 |
241 |
242 ML{*fun inst_spec_tac ctrms = |
242 ML{*fun inst_spec_tac ctrms = |
243 EVERY' (map (dtac o inst_spec) ctrms)*} |
243 EVERY' (map (dtac o inst_spec) ctrms)*} |
244 |
244 |
245 text {* |
245 text {* |
246 This tactic expects a list of @{ML_type cterm}s. It allows us in the following |
246 This tactic expects a list of @{ML_type cterm}s. It allows us in the |
247 proof to instantiate the three quantifiers in the assumption. |
247 proof below to instantiate the three quantifiers in the assumption. |
248 *} |
248 *} |
249 |
249 |
250 lemma |
250 lemma |
251 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" |
251 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" |
252 shows "\<forall>x y z. P x y z \<Longrightarrow> True" |
252 shows "\<forall>x y z. P x y z \<Longrightarrow> True" |
253 apply (tactic {* |
253 apply (tactic {* |
254 inst_spec_tac [@{cterm "a::nat"},@{cterm "b::nat"},@{cterm "c::nat"}] 1 *}) |
254 inst_spec_tac [@{cterm "a::nat"},@{cterm "b::nat"},@{cterm "c::nat"}] 1 *}) |
255 txt {* |
255 txt {* |
256 We obtain the goal state |
256 We obtain the goal state |
257 |
257 |
258 \begin{minipage}{\textwidth} |
258 \begin{minipage}{\textwidth} |
259 @{subgoals} |
259 @{subgoals} |
309 \end{isabelle} |
309 \end{isabelle} |
310 |
310 |
311 The variables @{text "z"}, @{text "P"} and @{text "Q"} are schematic |
311 The variables @{text "z"}, @{text "P"} and @{text "Q"} are schematic |
312 variables (since they are not quantified in the lemma). These schematic |
312 variables (since they are not quantified in the lemma). These schematic |
313 variables are needed so that they can be instantiated by the user. |
313 variables are needed so that they can be instantiated by the user. |
314 We have to take care to also generate these schematic variables when |
314 It will take a bit of work to generate these schematic variables when |
315 generating the goals for the induction principles. In general we have |
315 constructing the goals for the induction principles. In general we have |
316 to construct for each predicate @{text "pred"} a goal of the form |
316 to construct for each predicate @{text "pred"} a goal of the form |
317 |
317 |
318 @{text [display] |
318 @{text [display] |
319 "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"} |
319 "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"} |
320 |
320 |
321 where the predicates @{text preds} are replaced in @{text rules} by new |
321 where the predicates @{text preds} are replaced in @{text rules} by new |
322 distinct variables @{text "?Ps"}. We also need to generate fresh arguments |
322 distinct variables @{text "?Ps"}. We also need to generate fresh arguments |
323 @{text "?zs"} for the predicate @{text "pred"} and the @{text "?P"} in |
323 @{text "?zs"} for the predicate @{text "pred"} and the @{text "?P"} in |
324 the conclusion. The crucial point is that the @{text "?Ps"} and |
324 the conclusion. As just mentioned, the crucial point is that the |
325 @{text "?zs"} need to be schematic variables that can be instantiated |
325 @{text "?Ps"} and @{text "?zs"} need to be schematic variables that can |
326 by the user. |
326 be instantiated by the user. |
327 |
327 |
328 We generate these goals in two steps. The first function, named @{text prove_ind}, |
328 We generate these goals in two steps. The first function, named @{text prove_ind}, |
329 expects that the introduction rules are already appropriately substituted. The argument |
329 expects that the introduction rules are already appropriately substituted. The argument |
330 @{text "srules"} stands for these substituted rules; @{text cnewpreds} are |
330 @{text "srules"} stands for these substituted rules; @{text cnewpreds} are |
331 the certified terms coresponding to the variables @{text "?Ps"}; @{text |
331 the certified terms coresponding to the variables @{text "?Ps"}; @{text |
350 end *} |
350 end *} |
351 |
351 |
352 text {* |
352 text {* |
353 In Line 3 we produce names @{text "zs"} for each type in the |
353 In Line 3 we produce names @{text "zs"} for each type in the |
354 argument type list. Line 4 makes these names unique and declares them as |
354 argument type list. Line 4 makes these names unique and declares them as |
355 \emph{free} (but fixed) variables in the local theory @{text "lthy'"}. |
355 \emph{free but fixed} variables in the local theory @{text "lthy'"}. |
356 That means they are not (yet) schematic variables. |
356 That means they are not schematic variables (yet). |
357 In Line 5 we construct the terms corresponding to these variables. |
357 In Line 5 we construct the terms corresponding to these variables. |
358 The variables are applied to the predicate in Line 7 (this corresponds |
358 The variables are applied to the predicate in Line 7 (this corresponds |
359 to the first premise @{text "pred zs"} of the induction principle). |
359 to the first premise @{text "pred zs"} of the induction principle). |
360 In Line 8 and 9, we first construct the term @{text "P zs"} |
360 In Line 8 and 9, we first construct the term @{text "P zs"} |
361 and then add the (substituted) introduction rules as premises. In case that |
361 and then add the (substituted) introduction rules as preconditions. In |
362 no introduction rules are given, the conclusion of this implication needs |
362 case that no introduction rules are given, the conclusion of this |
363 to be wrapped inside a @{term Trueprop}, otherwise the Isabelle's goal |
363 implication needs to be wrapped inside a @{term Trueprop}, otherwise |
364 mechanism will fail. |
364 the Isabelle's goal mechanism will fail.\footnote{FIXME: check with |
|
365 Stefan...is this so?} |
365 |
366 |
366 In Line 11 we set up the goal to be proved; in the next line we call the |
367 In Line 11 we set up the goal to be proved; in the next line we call the |
367 tactic for proving the induction principle. As mentioned before, this tactic |
368 tactic for proving the induction principle. As mentioned before, this tactic |
368 expects the definitions, the premise and the (certified) predicates with |
369 expects the definitions, the premise and the (certified) predicates with |
369 which the introduction rules have been substituted. The code in these two |
370 which the introduction rules have been substituted. The code in these two |
465 *} |
466 *} |
466 |
467 |
467 subsection {* Introduction Rules *} |
468 subsection {* Introduction Rules *} |
468 |
469 |
469 text {* |
470 text {* |
470 The proofs of the introduction rules are quite a bit |
471 Constructing the goals for the introduction rules is easy: they |
471 more involved than the ones for the induction principles. |
472 are just the rules given by the user. However, their proofs are |
472 To ease somewhat our work here, we use the following two helper |
473 quite a bit more involved than the ones for the induction principles. |
473 functions. |
474 To explain the general method, our running example will be |
474 |
475 the introduction rule |
|
476 |
|
477 \begin{isabelle} |
|
478 @{prop "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"} |
|
479 \end{isabelle} |
|
480 |
|
481 about freshness for lambdas. In order to ease somewhat |
|
482 our work here, we use the following two helper functions. |
475 *} |
483 *} |
476 |
484 |
477 ML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct) |
485 ML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct) |
478 val imp_elims = fold (fn th => fn th' => [th', th] MRS @{thm mp})*} |
486 val imp_elims = fold (fn th => fn th' => [th', th] MRS @{thm mp})*} |
479 |
487 |
480 text {* |
488 text {* |
481 To see what these functions do, let us suppose whe have the following three |
489 To see what these functions do, let us suppose we have the following three |
482 theorems. |
490 theorems. |
483 *} |
491 *} |
484 |
492 |
485 lemma all_elims_test: |
493 lemma all_elims_test: |
486 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" |
494 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" |
513 @{ML_response_fake [display, gray] |
521 @{ML_response_fake [display, gray] |
514 "warning (str_of_thm_no_vars @{context} |
522 "warning (str_of_thm_no_vars @{context} |
515 (imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}))" |
523 (imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}))" |
516 "C"} |
524 "C"} |
517 |
525 |
518 To explain the proof for the introduction rule, our running example will be |
526 Now we set up the proof for the introduction rule as follows: |
519 the rule: |
|
520 |
|
521 \begin{isabelle} |
|
522 @{prop "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"} |
|
523 \end{isabelle} |
|
524 |
|
525 for freshness of applications. We set up the proof as follows: |
|
526 *} |
527 *} |
527 |
528 |
528 lemma fresh_Lam: |
529 lemma fresh_Lam: |
529 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
530 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
530 (*<*)oops(*>*) |
531 (*<*)oops(*>*) |
531 |
532 |
532 text {* |
533 text {* |
533 The first step will be to expand the definitions of freshness |
534 The first step in the proof will be to expand the definitions of freshness |
534 and then introduce quantifiers and implications. For this we |
535 and then introduce quantifiers and implications. For this we |
535 will use the tactic |
536 will use the tactic |
536 *} |
537 *} |
537 |
538 |
538 ML{*fun expand_tac defs = |
539 ML %linenosgray{*fun expand_tac defs = |
539 ObjectLogic.rulify_tac 1 |
540 ObjectLogic.rulify_tac 1 |
540 THEN rewrite_goals_tac defs |
541 THEN rewrite_goals_tac defs |
541 THEN (REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1)) *} |
542 THEN (REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1)) *} |
542 |
543 |
543 text {* |
544 text {* |
544 The first step of ``rulifying'' the lemma will turn out to be important |
545 The function in Line 2 ``rulifies'' the lemma. This will turn out to |
545 later on. Applying this tactic |
546 be important later on. Applying this tactic |
546 *} |
547 *} |
547 |
548 |
548 (*<*) |
549 (*<*) |
549 lemma fresh_Lam: |
550 lemma fresh_Lam: |
550 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
551 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
560 |
561 |
561 As you can see, there are parameters (namely @{text "a"}, @{text "b"} |
562 As you can see, there are parameters (namely @{text "a"}, @{text "b"} |
562 and @{text "t"}) which come from the introduction rule and parameters |
563 and @{text "t"}) which come from the introduction rule and parameters |
563 (in the case above only @{text "fresh"}) which come from the universal |
564 (in the case above only @{text "fresh"}) which come from the universal |
564 quantification in the definition @{term "fresh a (App t s)"}. |
565 quantification in the definition @{term "fresh a (App t s)"}. |
565 Similarly, there are preconditions |
566 Similarly, there are assumptions |
566 that come from the premises of the rule and premises from the |
567 that come from the premises of the rule and assumptions from the |
567 definition. We need to treat these |
568 definition of the predicate. We need to treat these |
568 parameters and preconditions differently. In the code below |
569 parameters and assumptions differently. In the code below |
569 we will therefore separate them into @{text "params1"} and @{text params2}, |
570 we will therefore separate them into @{text "params1"} and @{text params2}, |
570 respectively @{text "prems1"} and @{text "prems2"}. To do this |
571 respectively @{text "prems1"} and @{text "prems2"}. To do this |
571 separation, it is best to open a subproof with the tactic |
572 separation, it is best to open a subproof with the tactic |
572 @{ML SUBPROOF}, since this tactic provides us |
573 @{ML SUBPROOF}, since this tactic provides us |
573 with the parameters (as list of @{ML_type cterm}s) and the premises |
574 with the parameters (as list of @{ML_type cterm}s) and the assumptions |
574 (as list of @{ML_type thm}s). The problem we have to overcome |
575 (as list of @{ML_type thm}s called @{text prems}). The problem we have |
575 with @{ML SUBPROOF} is, however, that this tactic always expects us to completely |
576 to overcome with @{ML SUBPROOF} is, however, that this tactic always |
576 discharge the goal (see Section~\ref{sec:simpletacs}). This is inconvenient for |
577 expects us to completely discharge the goal (see Section~\ref{sec:simpletacs}). |
577 our gradual explanation of the proof here. To circumvent this inconvenience |
578 This is inconvenient for our gradual explanation of the proof here. To |
578 we use the following modified tactic: |
579 circumvent this inconvenience we use the following modified tactic: |
579 *} |
580 *} |
580 (*<*)oops(*>*) |
581 (*<*)oops(*>*) |
581 ML{*fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac*} |
582 ML{*fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac*} |
582 |
583 |
583 text {* |
584 text {* |
584 If the tactic inside @{ML SUBPROOF} fails, then the overall tactic will |
585 If the tactic inside @{ML SUBPROOF} fails, then the overall tactic will |
585 still succeed. With this testing tactic, we can gradually implement |
586 still succeed. With this testing tactic, we can gradually implement |
586 all necessary proof steps inside a subproof. |
587 all necessary proof steps inside a subproof. Once we are finished, we |
|
588 just have to replace it with @{ML SUBPROOF}. |
587 *} |
589 *} |
588 |
590 |
589 text_raw {* |
591 text_raw {* |
590 \begin{figure}[t] |
592 \begin{figure}[t] |
591 \begin{minipage}{\textwidth} |
593 \begin{minipage}{\textwidth} |
610 \end{figure} |
612 \end{figure} |
611 *} |
613 *} |
612 |
614 |
613 text {* |
615 text {* |
614 First we calculate the values for @{text "params1/2"} and @{text "prems1/2"} |
616 First we calculate the values for @{text "params1/2"} and @{text "prems1/2"} |
615 from @{text "params"} and @{text "prems"}, respectively. To see what is |
617 from @{text "params"} and @{text "prems"}, respectively. To better see what is |
616 going in our example, we will print out the values using the printing |
618 going in our example, we will print out these values using the printing |
617 function in Figure~\ref{fig:chopprint}. Since the tactic @{ML SUBPROOF} will |
619 function in Figure~\ref{fig:chopprint}. Since the tactic @{ML SUBPROOF} will |
618 supply us the @{text "params"} and @{text "prems"} as lists, we can |
620 supply us the @{text "params"} and @{text "prems"} as lists, we can |
619 separate them using the function @{ML chop}. |
621 separate them using the function @{ML chop}. |
620 *} |
622 *} |
621 |
623 |
627 in |
629 in |
628 chop_print params1 params2 prems1 prems2 context; no_tac |
630 chop_print params1 params2 prems1 prems2 context; no_tac |
629 end) *} |
631 end) *} |
630 |
632 |
631 text {* |
633 text {* |
632 For the separation we can rely on that Isabelle deterministically |
634 For the separation we can rely on the fact that Isabelle deterministically |
633 produces parameter and premises in a goal state. The last parameters |
635 produces parameters and premises in a goal state. The last parameters |
634 that were introduced come from the quantifications in the definitions. |
636 that were introduced come from the quantifications in the definitions |
|
637 (see the tactic @{ML expand_tac}). |
635 Therefore we only have to subtract the number of predicates (in this |
638 Therefore we only have to subtract the number of predicates (in this |
636 case only @{text "1"}) from the lenghts of all parameters. Similarly |
639 case only @{text "1"}) from the lenghts of all parameters. Similarly |
637 with the @{text "prems"}: the last premises in the goal state come from |
640 with the @{text "prems"}: the last premises in the goal state come from |
638 unfolding the definition of the predicate in the conclusion. So we can |
641 unfolding the definition of the predicate in the conclusion. So we can |
639 just subtract the number of rules from the number of all premises. |
642 just subtract the number of rules from the number of all premises. |
673 |
676 |
674 |
677 |
675 We now have to select from @{text prems2} the premise |
678 We now have to select from @{text prems2} the premise |
676 that corresponds to the introduction rule we prove, namely: |
679 that corresponds to the introduction rule we prove, namely: |
677 |
680 |
678 @{term [display] "\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)"} |
681 @{term [display] "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam a t)"} |
679 |
682 |
680 To use this premise with @{ML rtac}, we need to instantiate its |
683 To use this premise with @{ML rtac}, we need to instantiate its |
681 quantifiers (with @{text params1}) and transform it into rule |
684 quantifiers (with @{text params1}) and transform it into rule |
682 format (using @{ML "ObjectLogic.rulify"}. So we can modify the |
685 format (using @{ML "ObjectLogic.rulify"}. So we can modify the |
683 subproof as follows: |
686 subproof as follows: |
684 *} |
687 *} |
685 |
688 |
686 ML{*fun apply_prem_tac i preds rules = |
689 ML %linenosgray{*fun apply_prem_tac i preds rules = |
687 SUBPROOF_test (fn {params, prems, context, ...} => |
690 SUBPROOF_test (fn {params, prems, context, ...} => |
688 let |
691 let |
689 val (params1, params2) = chop (length params - length preds) params |
692 val (params1, params2) = chop (length params - length preds) params |
690 val (prems1, prems2) = chop (length prems - length rules) prems |
693 val (prems1, prems2) = chop (length prems - length rules) prems |
691 in |
694 in |
710 apply(tactic {* apply_prem_tac 3 [fresh_pred] fresh_rules @{context} *}) |
713 apply(tactic {* apply_prem_tac 3 [fresh_pred] fresh_rules @{context} *}) |
711 (*<*)oops(*>*) |
714 (*<*)oops(*>*) |
712 |
715 |
713 text {* |
716 text {* |
714 Since we print out the goal state just after the application of |
717 Since we print out the goal state just after the application of |
715 @{ML rtac}, we can see the goal state we obtain: as expected it has |
718 @{ML rtac} (Line 8), we can see the goal state we obtain: |
716 the two subgoals |
|
717 |
719 |
718 \begin{isabelle} |
720 \begin{isabelle} |
719 @{text "1."}~@{prop "a \<noteq> b"}\\ |
721 @{text "1."}~@{prop "a \<noteq> b"}\\ |
720 @{text "2."}~@{prop "fresh a t"} |
722 @{text "2."}~@{prop "fresh a t"} |
721 \end{isabelle} |
723 \end{isabelle} |
722 |
724 |
723 where the first comes from a non-recursive premise of the rule |
725 As expected there are two subgoals, where the first comes from a |
724 and the second comes from a recursive premise. The first goal |
726 non-recursive premise of the introduction rule and the second comes |
725 can be solved immediately by @{text "prems1"}. The second |
727 from a recursive premise. The first goal can be solved immediately |
726 needs more work. It can be solved with the other premise |
728 by @{text "prems1"}. The second needs more work. It can be solved |
727 in @{text "prems1"}, namely |
729 with the other premise in @{text "prems1"}, namely |
|
730 |
728 |
731 |
729 @{term [break,display] |
732 @{term [break,display] |
730 "\<forall>fresh. |
733 "\<forall>fresh. |
731 (\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow> |
734 (\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow> |
732 (\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow> |
735 (\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow> |
735 |
738 |
736 but we have to instantiate it appropriately. These instantiations |
739 but we have to instantiate it appropriately. These instantiations |
737 come from @{text "params1"} and @{text "prems2"}. We can determine |
740 come from @{text "params1"} and @{text "prems2"}. We can determine |
738 whether we are in the simple or complicated case by checking whether |
741 whether we are in the simple or complicated case by checking whether |
739 the topmost connective is an @{text "\<forall>"}. The premises in the simple |
742 the topmost connective is an @{text "\<forall>"}. The premises in the simple |
740 case cannot have such a quantification, since in the first step |
743 case cannot have such a quantification, since the first step |
741 of @{ML "expand_tac"} was the ``rulification'' of the lemma. |
744 of @{ML "expand_tac"} was to ``rulify'' the lemma. |
742 The premise of the complicated case must have at least one @{text "\<forall>"} |
745 The premise of the complicated case must have at least one @{text "\<forall>"} |
743 coming from the quantification over the @{text preds}. So |
746 coming from the quantification over the @{text preds}. So |
744 we can implement the following function |
747 we can implement the following function |
745 *} |
748 *} |
746 |
749 |
767 rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 |
770 rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 |
768 THEN EVERY1 (map (prepare_prem params2 prems2) prems1) |
771 THEN EVERY1 (map (prepare_prem params2 prems2) prems1) |
769 end) *} |
772 end) *} |
770 |
773 |
771 text {* |
774 text {* |
|
775 Note that the tactic is now @{ML SUBPROOF}, not @{ML SUBPROOF_test}. |
772 The full proof of the introduction rule now as follows: |
776 The full proof of the introduction rule now as follows: |
773 *} |
777 *} |
774 |
778 |
775 lemma fresh_Lam: |
779 lemma fresh_Lam: |
776 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
780 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
777 apply(tactic {* expand_tac @{thms fresh_def} *}) |
781 apply(tactic {* expand_tac @{thms fresh_def} *}) |
778 apply(tactic {* prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1 *}) |
782 apply(tactic {* prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1 *}) |
779 done |
783 done |
780 |
784 |
781 text {* |
785 text {* |
782 Unfortunately, not everything is done yet. If you look closely |
786 Phew! Unfortunately, not everything is done yet. If you look closely |
783 at the general principle outlined in Section~\ref{sec:nutshell}, |
787 at the general principle outlined for the introduction rules in |
784 we have not yet dealt with the case when recursive premises |
788 Section~\ref{sec:nutshell}, we have not yet dealt with the case where |
785 in a rule have preconditions @{text Bs}. The introduction rule |
789 recursive premises have preconditions. The introduction rule |
786 of the accessible part is such a rule. |
790 of the accessible part is such a rule. |
787 *} |
791 *} |
788 |
792 |
789 lemma accpartI: |
793 lemma accpartI: |
790 shows "\<And>x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x" |
794 shows "\<And>x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x" |
816 |
820 |
817 |
821 |
818 *}(*<*)oops(*>*) |
822 *}(*<*)oops(*>*) |
819 |
823 |
820 text {* |
824 text {* |
821 In order to make progress as before, we have to use the precondition |
825 In order to make progress, we have to use the precondition |
822 @{text "R y x"} (in general there can be many of them). The best way |
826 @{text "R y x"} (in general there can be many of them). The best way |
823 to get a handle on these preconditions is to open up another subproof, |
827 to get a handle on these preconditions is to open up another subproof, |
824 since the preconditions will be bound to @{text prems}. Therfore we |
828 since the preconditions will then be bound to @{text prems}. Therfore we |
825 modify the function @{ML prepare_prem} as follows |
829 modify the function @{ML prepare_prem} as follows |
826 *} |
830 *} |
827 |
831 |
828 ML %linenosgray{*fun prepare_prem params2 prems2 ctxt prem = |
832 ML %linenosgray{*fun prepare_prem params2 prems2 ctxt prem = |
829 SUBPROOF (fn {prems, ...} => |
833 SUBPROOF (fn {prems, ...} => |
837 | _ => prem') 1 |
841 | _ => prem') 1 |
838 end) ctxt *} |
842 end) ctxt *} |
839 |
843 |
840 text {* |
844 text {* |
841 In Line 4 we use the @{text prems} from the @{ML SUBPROOF} and resolve |
845 In Line 4 we use the @{text prems} from the @{ML SUBPROOF} and resolve |
842 them with @{text prem}. In the simple case, that is where the @{text prem} |
846 them with @{text prem}. In the simple cases, that is where the @{text prem} |
843 comes from a non-recursive premise of the rule, @{text prems} will be |
847 comes from a non-recursive premise of the rule, @{text prems} will be |
844 just the empty list and the @{ML MRS} does nothing. Similarly, in the |
848 just the empty list and the function @{ML MRS} does nothing. Similarly, in the |
845 cases where the recursive premises of the rule do not have preconditions. |
849 cases where the recursive premises of the rule do not have preconditions. |
|
850 In case there are preconditions, then Line 4 discharges them. After |
|
851 that we can proceed as before, i.e., check whether the outermost |
|
852 connective is @{text "\<forall>"}. |
846 |
853 |
847 The function @{ML prove_intro_tac} only needs to give the context to |
854 The function @{ML prove_intro_tac} only needs to be changed so that it |
848 @{ML prepare_prem} (Line 8) and is as follows. |
855 gives the context to @{ML prepare_prem} (Line 8). The modified version |
|
856 is below. |
849 *} |
857 *} |
850 |
858 |
851 ML %linenosgray{*fun prove_intro_tac i preds rules = |
859 ML %linenosgray{*fun prove_intro_tac i preds rules = |
852 SUBPROOF (fn {params, prems, context, ...} => |
860 SUBPROOF (fn {params, prems, context, ...} => |
853 let |
861 let |
880 REPEAT o (resolve_tac [@{thm allI}, @{thm impI}]), |
888 REPEAT o (resolve_tac [@{thm allI}, @{thm impI}]), |
881 prove_intro_tac i preds rules ctxt]*} |
889 prove_intro_tac i preds rules ctxt]*} |
882 |
890 |
883 text {* |
891 text {* |
884 Lines 2 to 4 correspond to the function @{ML expand_tac}. Some testcases |
892 Lines 2 to 4 correspond to the function @{ML expand_tac}. Some testcases |
885 dor this tactic are: |
893 for this tactic are: |
886 *} |
894 *} |
887 |
895 |
888 lemma even0_intro: |
896 lemma even0_intro: |
889 shows "even 0" |
897 shows "even 0" |
890 by (tactic {* intro_tac eo_defs eo_rules eo_preds 0 @{context} *}) |
898 by (tactic {* intro_tac eo_defs eo_rules eo_preds 0 @{context} *}) |
891 |
|
892 |
899 |
893 lemma evenS_intro: |
900 lemma evenS_intro: |
894 shows "\<And>m. odd m \<Longrightarrow> even (Suc m)" |
901 shows "\<And>m. odd m \<Longrightarrow> even (Suc m)" |
895 by (tactic {* intro_tac eo_defs eo_rules eo_preds 1 @{context} *}) |
902 by (tactic {* intro_tac eo_defs eo_rules eo_preds 1 @{context} *}) |
896 |
903 |
898 shows "\<And>a t s. \<lbrakk>fresh a t; fresh a s\<rbrakk> \<Longrightarrow> fresh a (App t s)" |
905 shows "\<And>a t s. \<lbrakk>fresh a t; fresh a s\<rbrakk> \<Longrightarrow> fresh a (App t s)" |
899 by (tactic {* |
906 by (tactic {* |
900 intro_tac @{thms fresh_def} fresh_rules [fresh_pred] 1 @{context} *}) |
907 intro_tac @{thms fresh_def} fresh_rules [fresh_pred] 1 @{context} *}) |
901 |
908 |
902 text {* |
909 text {* |
903 The second function sets up in Line 4 the goals (in this case this is easy |
910 The second function sets up in Line 4 the goals (this is easy |
904 since they are exactly the introduction rules the user gives) |
911 for the introduction rules since they are exactly the rules |
905 and iterates @{ML intro_tac} over all introduction rules. |
912 given by the user) and iterates @{ML intro_tac} over all |
|
913 introduction rules. |
906 *} |
914 *} |
907 |
915 |
908 ML %linenosgray{*fun intros rules preds defs lthy = |
916 ML %linenosgray{*fun intros rules preds defs lthy = |
909 let |
917 let |
910 fun intros_aux (i, goal) = |
918 fun intros_aux (i, goal) = |
911 Goal.prove lthy [] [] goal |
919 Goal.prove lthy [] [] goal |
912 (fn {context, ...} => intro_tac defs rules preds i context) |
920 (fn {context, ...} => intro_tac defs rules preds i context) |
913 in |
921 in |
914 map_index intros_aux rules |
922 map_index intros_aux rules |
915 end*} |
923 end*} |
|
924 |
|
925 text {* |
|
926 The iteration is done with the function @{ML map_index} since we |
|
927 need the introduction rule together with its number (counted from |
|
928 @{text 0}). This completes the code for the functions deriving the |
|
929 reasoning infrastructure. It remains to implement some administrative |
|
930 code that strings everything together. |
|
931 *} |
916 |
932 |
917 subsection {* Main Function *} |
933 subsection {* Main Function *} |
918 |
934 |
919 text {* main internal function *} |
935 text {* main internal function *} |
920 |
936 |