307 \isacommand{thm}~@{thm [source] automatic_ind_prin_even}\\ |
309 \isacommand{thm}~@{thm [source] automatic_ind_prin_even}\\ |
308 @{text "> "}~@{thm automatic_ind_prin_even} |
310 @{text "> "}~@{thm automatic_ind_prin_even} |
309 \end{isabelle} |
311 \end{isabelle} |
310 |
312 |
311 The variables @{text "z"}, @{text "P"} and @{text "Q"} are schematic |
313 The variables @{text "z"}, @{text "P"} and @{text "Q"} are schematic |
312 variables (since they are not quantified in the lemma). These schematic |
314 variables (since they are not quantified in the lemma). These |
313 variables are needed so that they can be instantiated by the user. |
315 variables must be schematic, otherwise they cannot be instantiated |
314 It will take a bit of work to generate these schematic variables when |
316 by the user. To generate these schematic variables we use a common trick |
315 constructing the goals for the induction principles. In general we have |
317 in Isabelle programming: we first declare them as \emph{free}, |
316 to construct for each predicate @{text "pred"} a goal of the form |
318 \emph{but fixed}, and then use the infrastructure to turn them into |
|
319 schematic variables. |
|
320 |
|
321 In general we have to construct for each predicate @{text "pred"} a goal |
|
322 of the form |
317 |
323 |
318 @{text [display] |
324 @{text [display] |
319 "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"} |
325 "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"} |
320 |
326 |
321 where the predicates @{text preds} are replaced in @{text rules} by new |
327 where the predicates @{text preds} are replaced in @{text rules} by new |
322 distinct variables @{text "?Ps"}. We also need to generate fresh arguments |
328 distinct variables @{text "?Ps"}. We also need to generate fresh arguments |
323 @{text "?zs"} for the predicate @{text "pred"} and the @{text "?P"} in |
329 @{text "?zs"} for the predicate @{text "pred"} and the @{text "?P"} in |
324 the conclusion. As just mentioned, the crucial point is that the |
330 the conclusion. |
325 @{text "?Ps"} and @{text "?zs"} need to be schematic variables that can |
|
326 be instantiated by the user. |
|
327 |
331 |
328 We generate these goals in two steps. The first function, named @{text prove_ind}, |
332 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 |
333 expects that the introduction rules are already appropriately substituted. The argument |
330 @{text "srules"} stands for these substituted rules; @{text cnewpreds} are |
334 @{text "srules"} stands for these substituted rules; @{text cnewpreds} are |
331 the certified terms coresponding to the variables @{text "?Ps"}; @{text |
335 the certified terms coresponding to the variables @{text "?Ps"}; @{text |
541 THEN rewrite_goals_tac defs |
549 THEN rewrite_goals_tac defs |
542 THEN (REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1)) *} |
550 THEN (REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1)) *} |
543 |
551 |
544 text {* |
552 text {* |
545 The function in Line 2 ``rulifies'' the lemma. This will turn out to |
553 The function in Line 2 ``rulifies'' the lemma. This will turn out to |
546 be important later on. Applying this tactic |
554 be important later on. Applying this tactic in our proof of @{text "fresh_Lem"} |
547 *} |
555 *} |
548 |
556 |
549 (*<*) |
557 (*<*) |
550 lemma fresh_Lam: |
558 lemma fresh_Lam: |
551 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
559 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
552 (*>*) |
560 (*>*) |
553 apply(tactic {* expand_tac @{thms fresh_def} *}) |
561 apply(tactic {* expand_tac @{thms fresh_def} *}) |
554 |
562 |
555 txt {* |
563 txt {* |
556 we end up in the goal state |
564 gives us the goal state |
557 |
565 |
558 \begin{isabelle} |
566 \begin{isabelle} |
559 @{subgoals [display]} |
567 @{subgoals [display]} |
560 \end{isabelle} |
568 \end{isabelle} |
561 |
569 |
562 As you can see, there are parameters (namely @{text "a"}, @{text "b"} |
570 As you can see, there are parameters (namely @{text "a"}, @{text "b"} and |
563 and @{text "t"}) which come from the introduction rule and parameters |
571 @{text "t"}) which come from the introduction rule and parameters (in the |
564 (in the case above only @{text "fresh"}) which come from the universal |
572 case above only @{text "fresh"}) which come from the universal |
565 quantification in the definition @{term "fresh a (App t s)"}. |
573 quantification in the definition @{term "fresh a (App t s)"}. Similarly, |
566 Similarly, there are assumptions |
574 there are assumptions that come from the premises of the rule (namely the |
567 that come from the premises of the rule and assumptions from the |
575 first two) and assumptions from the definition of the predicate (assumption |
568 definition of the predicate. We need to treat these |
576 three to six). We need to treat these parameters and assumptions |
569 parameters and assumptions differently. In the code below |
577 differently. In the code below we will therefore separate them into @{text |
570 we will therefore separate them into @{text "params1"} and @{text params2}, |
578 "params1"} and @{text params2}, respectively @{text "prems1"} and @{text |
571 respectively @{text "prems1"} and @{text "prems2"}. To do this |
579 "prems2"}. To do this separation, it is best to open a subproof with the |
572 separation, it is best to open a subproof with the tactic |
580 tactic @{ML SUBPROOF}, since this tactic provides us with the parameters (as |
573 @{ML SUBPROOF}, since this tactic provides us |
581 list of @{ML_type cterm}s) and the assumptions (as list of @{ML_type thm}s). |
574 with the parameters (as list of @{ML_type cterm}s) and the assumptions |
582 The problem we have to overcome with @{ML SUBPROOF} |
575 (as list of @{ML_type thm}s called @{text prems}). The problem we have |
583 is, however, that this tactic always expects us to completely discharge the |
576 to overcome with @{ML SUBPROOF} is, however, that this tactic always |
584 goal (see Section~\ref{sec:simpletacs}). This is inconvenient for our |
577 expects us to completely discharge the goal (see Section~\ref{sec:simpletacs}). |
585 gradual explanation of the proof here. To circumvent this inconvenience we |
578 This is inconvenient for our gradual explanation of the proof here. To |
586 use the following modified tactic: |
579 circumvent this inconvenience we use the following modified tactic: |
|
580 *} |
587 *} |
581 (*<*)oops(*>*) |
588 (*<*)oops(*>*) |
582 ML{*fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac*} |
589 ML{*fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac*} |
583 |
590 |
584 text {* |
591 text {* |
771 THEN EVERY1 (map (prepare_prem params2 prems2) prems1) |
778 THEN EVERY1 (map (prepare_prem params2 prems2) prems1) |
772 end) *} |
779 end) *} |
773 |
780 |
774 text {* |
781 text {* |
775 Note that the tactic is now @{ML SUBPROOF}, not @{ML SUBPROOF_test}. |
782 Note that the tactic is now @{ML SUBPROOF}, not @{ML SUBPROOF_test}. |
776 The full proof of the introduction rule now as follows: |
783 The full proof of the introduction rule is as follows: |
777 *} |
784 *} |
778 |
785 |
779 lemma fresh_Lam: |
786 lemma fresh_Lam: |
780 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
787 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)" |
781 apply(tactic {* expand_tac @{thms fresh_def} *}) |
788 apply(tactic {* expand_tac @{thms fresh_def} *}) |
782 apply(tactic {* prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1 *}) |
789 apply(tactic {* prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1 *}) |
783 done |
790 done |
784 |
791 |
785 text {* |
792 text {* |
786 Phew! Unfortunately, not everything is done yet. If you look closely |
793 Phew! ...Unfortunately, not everything is done yet. If you look closely |
787 at the general principle outlined for the introduction rules in |
794 at the general principle outlined for the introduction rules in |
788 Section~\ref{sec:nutshell}, we have not yet dealt with the case where |
795 Section~\ref{sec:nutshell}, we have not yet dealt with the case where |
789 recursive premises have preconditions. The introduction rule |
796 recursive premises have preconditions. The introduction rule |
790 of the accessible part is such a rule. |
797 of the accessible part is such a rule. |
791 *} |
798 *} |
928 @{text 0}). This completes the code for the functions deriving the |
935 @{text 0}). This completes the code for the functions deriving the |
929 reasoning infrastructure. It remains to implement some administrative |
936 reasoning infrastructure. It remains to implement some administrative |
930 code that strings everything together. |
937 code that strings everything together. |
931 *} |
938 *} |
932 |
939 |
933 subsection {* Main Function *} |
940 subsection {* Administrative Functions *} |
934 |
941 |
935 text {* main internal function *} |
942 text {* |
936 |
943 We have produced various theorems (definitions, induction principles and |
937 ML {* LocalTheory.notes *} |
944 introduction rules), but apart from the definitions, we have not yet |
938 |
945 registered them with the theorem database. This is what the functions |
|
946 @{ML LocalTheory.note} does. |
|
947 |
|
948 |
|
949 For convenience, we use the following |
|
950 three wrappers this function: |
|
951 *} |
|
952 |
|
953 ML{*fun reg_many qname ((name, attrs), thms) = |
|
954 LocalTheory.note Thm.theoremK |
|
955 ((Binding.qualify false qname name, attrs), thms) |
|
956 |
|
957 fun reg_single1 qname ((name, attrs), thm) = |
|
958 reg_many qname ((name, attrs), [thm]) |
|
959 |
|
960 fun reg_single2 name attrs (qname, thm) = |
|
961 reg_many (Binding.name_of qname) ((name, attrs), [thm]) *} |
|
962 |
|
963 text {* |
|
964 The function that ``holds everything together'' is @{text "add_inductive"}. |
|
965 Its arguments are the specification of the predicates @{text "pred_specs"} |
|
966 and the introduction rules @{text "rule_spec"}. |
|
967 *} |
939 |
968 |
940 ML %linenosgray{*fun add_inductive pred_specs rule_specs lthy = |
969 ML %linenosgray{*fun add_inductive pred_specs rule_specs lthy = |
941 let |
970 let |
942 val syns = map snd pred_specs |
971 val syns = map snd pred_specs |
943 val pred_specs' = map fst pred_specs |
972 val pred_specs' = map fst pred_specs |
944 val prednames = map fst pred_specs' |
973 val prednames = map fst pred_specs' |
945 val preds = map (fn (p, ty) => Free (Binding.name_of p, ty)) pred_specs' |
974 val preds = map (fn (p, ty) => Free (Binding.name_of p, ty)) pred_specs' |
946 |
|
947 val tyss = map (binder_types o fastype_of) preds |
975 val tyss = map (binder_types o fastype_of) preds |
948 val (attrs, rules) = split_list rule_specs |
976 |
|
977 val (namesattrs, rules) = split_list rule_specs |
949 |
978 |
950 val (defs, lthy') = defns rules preds prednames syns tyss lthy |
979 val (defs, lthy') = defns rules preds prednames syns tyss lthy |
951 val ind_rules = inds rules defs preds tyss lthy' |
980 val ind_prin = inds rules defs preds tyss lthy' |
952 val intro_rules = intros rules preds defs lthy' |
981 val intro_rules = intros rules preds defs lthy' |
953 |
982 |
954 val mut_name = space_implode "_" (map Binding.name_of prednames) |
983 val mut_name = space_implode "_" (map Binding.name_of prednames) |
955 val case_names = map (Binding.name_of o fst) attrs |
984 val case_names = map (Binding.name_of o fst) namesattrs |
956 in |
985 in |
957 lthy' |
986 lthy' |> reg_many mut_name ((@{binding "intros"}, []), intro_rules) |
958 |> LocalTheory.notes Thm.theoremK (map (fn (((a, atts), _), th) => |
987 ||>> fold_map (reg_single1 mut_name) (namesattrs ~~ intro_rules) |
959 ((Binding.qualify false mut_name a, atts), [([th], [])])) (rule_specs ~~ intro_rules)) |
988 ||>> fold_map (reg_single2 @{binding "induct"} |
960 |-> (fn intross => LocalTheory.note Thm.theoremK |
989 [Attrib.internal (K (RuleCases.case_names case_names)), |
961 ((Binding.qualify false mut_name (@{binding "intros"}), []), maps snd intross)) |
990 Attrib.internal (K (RuleCases.consumes 1)), |
962 |>> snd |
991 Attrib.internal (K (Induct.induct_pred ""))]) |
963 ||>> (LocalTheory.notes Thm.theoremK (map (fn (((R, _), _), th) => |
992 (prednames ~~ ind_prin) |
964 ((Binding.qualify false (Binding.name_of R) (@{binding "induct"}), |
993 |> snd |
965 [Attrib.internal (K (RuleCases.case_names case_names)), |
|
966 Attrib.internal (K (RuleCases.consumes 1)), |
|
967 Attrib.internal (K (Induct.induct_pred ""))]), [([th], [])])) |
|
968 (pred_specs ~~ ind_rules)) #>> maps snd) |
|
969 |> snd |
|
970 end*} |
994 end*} |
|
995 |
|
996 text {* |
|
997 In Line 3 the function extracts the syntax annotations from the predicates. |
|
998 Lines 4 to 6 extract the names of the predicates and generate |
|
999 the variables terms (with types) corresponding to the predicates. |
|
1000 Line 7 produces the argument types for each predicate. |
|
1001 |
|
1002 Line 9 extracts the introduction rules from the specifications |
|
1003 and stores also in @{text namesattrs} the names and attributes the |
|
1004 user may have attached to these rules. |
|
1005 |
|
1006 Line 11 produces the definitions and also registers the definitions |
|
1007 in the local theory @{text "lthy'"}. The next two lines produce |
|
1008 the induction principles and the introduction rules (all of them |
|
1009 as theorems). Both need the local theory @{text lthy'} in which |
|
1010 the definitions have been registered. |
|
1011 |
|
1012 Lines 15 produces the name that is used to register the introduction |
|
1013 rules. It is costum to collect all introduction rules under |
|
1014 @{text "string.intros"}, whereby @{text "string"} stands for the |
|
1015 @{text [quotes] "_"}-separated list of predicate names (for example |
|
1016 @{text "even_odd"}. Also by custom, the case names in intuction |
|
1017 proofs correspond to the names of the introduction rules. These |
|
1018 are generated in Line 16. |
|
1019 |
|
1020 Line 18 now adds to @{text "lthy'"} all the introduction rules |
|
1021 under the name @{text "mut_name.intros"} (see previous paragraph). |
|
1022 Line 19 add further every introduction rule under its own name |
|
1023 (given by the user).\footnote{FIXME: what happens if the user did not give |
|
1024 any name.} Line 20 registers the induction principles. For this we have |
|
1025 to use some specific attributes. The first @{ML "case_names" in RuleCases} |
|
1026 corresponds to the case names that are used by Isar to reference the proof |
|
1027 obligations in the induction. The second @{ML "consumes 1" in RuleCases} |
|
1028 indicates that the first premise of the induction principle (namely |
|
1029 the predicate over which the induction proceeds) is eliminated. |
|
1030 |
|
1031 (FIXME: What does @{ML Induct.induct_pred} do?) |
|
1032 |
|
1033 (FIXME: why the mut-name?) |
|
1034 |
|
1035 (FIXME: What does @{ML Binding.qualify} do?) |
|
1036 |
|
1037 |
|
1038 This completes all the code and fits in with the ``front end'' described |
|
1039 in Section \ref{sec:interface} |
|
1040 *} |
|
1041 |
971 |
1042 |
972 ML{*fun add_inductive_cmd pred_specs rule_specs lthy = |
1043 ML{*fun add_inductive_cmd pred_specs rule_specs lthy = |
973 let |
1044 let |
974 val ((pred_specs', rule_specs'), _) = |
1045 val ((pred_specs', rule_specs'), _) = |
975 Specification.read_spec pred_specs rule_specs lthy |
1046 Specification.read_spec pred_specs rule_specs lthy |