ProgTutorial/Package/Ind_Code.thy
changeset 224 647cab4a72c2
parent 219 98d43270024f
child 237 0a8981f52045
equal deleted inserted replaced
223:1aaa15ef731b 224:647cab4a72c2
     1 theory Ind_Code
     1 theory Ind_Code
     2 imports "../Base" "../FirstSteps" Ind_Interface Ind_General_Scheme
     2 imports "../Base" "../FirstSteps" Ind_General_Scheme
     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 {*
   247   This tactic expects a list of @{ML_type cterm}s. It allows us in the 
   247   This tactic expects a list of @{ML_type cterm}s. It allows us in the 
   248   proof below to instantiate the three quantifiers in the assumption. 
   248   proof below to instantiate the three quantifiers in the assumption. 
   249 *}
   249 *}
   250 
   250 
   251 lemma 
   251 lemma 
   252   fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   252 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   253   shows "\<forall>x y z. P x y z \<Longrightarrow> True"
   253 shows "\<forall>x y z. P x y z \<Longrightarrow> True"
   254 apply (tactic {* 
   254 apply (tactic {* 
   255   inst_spec_tac [@{cterm "a::nat"},@{cterm "b::nat"},@{cterm "c::nat"}] 1 *})
   255   inst_spec_tac [@{cterm "a::nat"},@{cterm "b::nat"},@{cterm "c::nat"}] 1 *})
   256 txt {* 
   256 txt {* 
   257   We obtain the goal state
   257   We obtain the goal state
   258 
   258 
   493   To see what these functions do, let us suppose we have the following three
   493   To see what these functions do, let us suppose we have the following three
   494   theorems. 
   494   theorems. 
   495 *}
   495 *}
   496 
   496 
   497 lemma all_elims_test:
   497 lemma all_elims_test:
   498   fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   498 fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   499   shows "\<forall>x y z. P x y z" sorry
   499 shows "\<forall>x y z. P x y z" sorry
   500 
   500 
   501 lemma imp_elims_test:
   501 lemma imp_elims_test:
   502   shows "A \<longrightarrow> B \<longrightarrow> C" sorry
   502 shows "A \<longrightarrow> B \<longrightarrow> C" sorry
   503 
   503 
   504 lemma imp_elims_test':
   504 lemma imp_elims_test':
   505   shows "A" "B" sorry
   505 shows "A" "B" sorry
   506 
   506 
   507 text {*
   507 text {*
   508   The function @{ML all_elims} takes a list of (certified) terms and instantiates
   508   The function @{ML all_elims} takes a list of (certified) terms and instantiates
   509   theorems of the form @{thm [source] all_elims_test}. For example we can instantiate
   509   theorems of the form @{thm [source] all_elims_test}. For example we can instantiate
   510   the quantifiers in this theorem with @{term a}, @{term b} and @{term c} as follows:
   510   the quantifiers in this theorem with @{term a}, @{term b} and @{term c} as follows:
   533 
   533 
   534   Now we set up the proof for the introduction rule as follows:
   534   Now we set up the proof for the introduction rule as follows:
   535 *}
   535 *}
   536 
   536 
   537 lemma fresh_Lam:
   537 lemma fresh_Lam:
   538   shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   538 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   539 (*<*)oops(*>*)
   539 (*<*)oops(*>*)
   540 
   540 
   541 text {*
   541 text {*
   542   The first step in the proof will be to expand the definitions of freshness
   542   The first step in the proof will be to expand the definitions of freshness
   543   and then introduce quantifiers and implications. For this we
   543   and then introduce quantifiers and implications. For this we
   554   be important later on. Applying this tactic in our proof of @{text "fresh_Lem"}
   554   be important later on. Applying this tactic in our proof of @{text "fresh_Lem"}
   555 *}
   555 *}
   556 
   556 
   557 (*<*)
   557 (*<*)
   558 lemma fresh_Lam:
   558 lemma fresh_Lam:
   559   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)"
   560 (*>*)
   560 (*>*)
   561 apply(tactic {* expand_tac @{thms fresh_def} *})
   561 apply(tactic {* expand_tac @{thms fresh_def} *})
   562 
   562 
   563 txt {*
   563 txt {*
   564   gives us the goal state
   564   gives us the goal state
   650   Applying this tactic in our example 
   650   Applying this tactic in our example 
   651 *}
   651 *}
   652 
   652 
   653 (*<*)
   653 (*<*)
   654 lemma fresh_Lam:
   654 lemma fresh_Lam:
   655   shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   655 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   656 apply(tactic {* expand_tac @{thms fresh_def} *})
   656 apply(tactic {* expand_tac @{thms fresh_def} *})
   657 (*>*)
   657 (*>*)
   658 apply(tactic {* chop_test_tac [fresh_pred] fresh_rules @{context} *})
   658 apply(tactic {* chop_test_tac [fresh_pred] fresh_rules @{context} *})
   659 (*<*)oops(*>*)
   659 (*<*)oops(*>*)
   660 
   660 
   712   we are proving the fourth introduction rule. 
   712   we are proving the fourth introduction rule. 
   713 *}
   713 *}
   714 
   714 
   715 (*<*)
   715 (*<*)
   716 lemma fresh_Lam:
   716 lemma fresh_Lam:
   717   shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   717 shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   718 apply(tactic {* expand_tac @{thms fresh_def} *})
   718 apply(tactic {* expand_tac @{thms fresh_def} *})
   719 (*>*)
   719 (*>*)
   720 apply(tactic {* apply_prem_tac 3 [fresh_pred] fresh_rules @{context} *})
   720 apply(tactic {* apply_prem_tac 3 [fresh_pred] fresh_rules @{context} *})
   721 (*<*)oops(*>*)
   721 (*<*)oops(*>*)
   722 
   722 
   782   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}. 
   783   The full proof of the introduction rule is as follows:
   783   The full proof of the introduction rule is as follows:
   784 *}
   784 *}
   785 
   785 
   786 lemma fresh_Lam:
   786 lemma fresh_Lam:
   787   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)"
   788 apply(tactic {* expand_tac @{thms fresh_def} *})
   788 apply(tactic {* expand_tac @{thms fresh_def} *})
   789 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 *})
   790 done
   790 done
   791 
   791 
   792 text {* 
   792 text {* 
   796   recursive premises have preconditions. The introduction rule
   796   recursive premises have preconditions. The introduction rule
   797   of the accessible part is such a rule. 
   797   of the accessible part is such a rule. 
   798 *}
   798 *}
   799 
   799 
   800 lemma accpartI:
   800 lemma accpartI:
   801   shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
   801 shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
   802 apply(tactic {* expand_tac @{thms accpart_def} *})
   802 apply(tactic {* expand_tac @{thms accpart_def} *})
   803 apply(tactic {* chop_test_tac [acc_pred] acc_rules @{context} *})
   803 apply(tactic {* chop_test_tac [acc_pred] acc_rules @{context} *})
   804 apply(tactic {* apply_prem_tac 0 [acc_pred] acc_rules @{context} *})
   804 apply(tactic {* apply_prem_tac 0 [acc_pred] acc_rules @{context} *})
   805 
   805 
   806 txt {*
   806 txt {*
   877   With these two functions we can now also prove the introduction
   877   With these two functions we can now also prove the introduction
   878   rule for the accessible part. 
   878   rule for the accessible part. 
   879 *}
   879 *}
   880 
   880 
   881 lemma accpartI:
   881 lemma accpartI:
   882   shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
   882 shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
   883 apply(tactic {* expand_tac @{thms accpart_def} *})
   883 apply(tactic {* expand_tac @{thms accpart_def} *})
   884 apply(tactic {* prove_intro_tac 0 [acc_pred] acc_rules @{context} 1 *})
   884 apply(tactic {* prove_intro_tac 0 [acc_pred] acc_rules @{context} 1 *})
   885 done
   885 done
   886 
   886 
   887 text {*
   887 text {*
   899   Lines 2 to 4 in this tactic correspond to the function @{ML expand_tac}. 
   899   Lines 2 to 4 in this tactic correspond to the function @{ML expand_tac}. 
   900   Some testcases for this tactic are:
   900   Some testcases for this tactic are:
   901 *}
   901 *}
   902 
   902 
   903 lemma even0_intro:
   903 lemma even0_intro:
   904   shows "even 0"
   904 shows "even 0"
   905 by (tactic {* intro_tac eo_defs eo_rules eo_preds 0 @{context} *})
   905 by (tactic {* intro_tac eo_defs eo_rules eo_preds 0 @{context} *})
   906 
   906 
   907 lemma evenS_intro:
   907 lemma evenS_intro:
   908   shows "\<And>m. odd m \<Longrightarrow> even (Suc m)"
   908 shows "\<And>m. odd m \<Longrightarrow> even (Suc m)"
   909 by (tactic {* intro_tac eo_defs eo_rules eo_preds 1 @{context} *})
   909 by (tactic {* intro_tac eo_defs eo_rules eo_preds 1 @{context} *})
   910 
   910 
   911 lemma fresh_App:
   911 lemma fresh_App:
   912   shows "\<And>a t s. \<lbrakk>fresh a t; fresh a s\<rbrakk> \<Longrightarrow> fresh a (App t s)"
   912 shows "\<And>a t s. \<lbrakk>fresh a t; fresh a s\<rbrakk> \<Longrightarrow> fresh a (App t s)"
   913 by (tactic {* 
   913 by (tactic {* 
   914   intro_tac @{thms fresh_def} fresh_rules [fresh_pred] 1 @{context} *})
   914   intro_tac @{thms fresh_def} fresh_rules [fresh_pred] 1 @{context} *})
   915 
   915 
   916 text {*
   916 text {*
   917   The second function sets up in Line 4 the goals to be proved (this is easy
   917   The second function sets up in Line 4 the goals to be proved (this is easy
  1026   corresponds to the case names that are used by Isar to reference the proof
  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}
  1027   obligations in the induction. The second @{ML "consumes 1" in RuleCases}
  1028   indicates that the first premise of the induction principle (namely
  1028   indicates that the first premise of the induction principle (namely
  1029   the predicate over which the induction proceeds) is eliminated. 
  1029   the predicate over which the induction proceeds) is eliminated. 
  1030 
  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
  1031   This completes all the code and fits in with the ``front end'' described
  1039   in Section \ref{sec:interface}
  1032   in Section~\ref{sec:interface}.\footnote{FIXME: Describe @{ML Induct.induct_pred}. Why the mut-name? 
  1040 *}
  1033   What does @{ML Binding.qualify} do?}
  1041 
  1034 *}
  1042 
       
  1043 ML{*fun add_inductive_cmd pred_specs rule_specs lthy =
       
  1044 let
       
  1045   val ((pred_specs', rule_specs'), _) = 
       
  1046          Specification.read_spec pred_specs rule_specs lthy
       
  1047 in
       
  1048   add_inductive pred_specs' rule_specs' lthy
       
  1049 end*} 
       
  1050 
       
  1051 ML{*val spec_parser = 
       
  1052    OuterParse.fixes -- 
       
  1053    Scan.optional 
       
  1054      (OuterParse.$$$ "where" |--
       
  1055         OuterParse.!!! 
       
  1056           (OuterParse.enum1 "|" 
       
  1057              (SpecParse.opt_thm_name ":" -- OuterParse.prop))) []*}
       
  1058 
       
  1059 ML{*val specification =
       
  1060   spec_parser >>
       
  1061     (fn (pred_specs, rule_specs) => add_inductive_cmd pred_specs rule_specs)*}
       
  1062 
       
  1063 ML{*val _ = OuterSyntax.local_theory "simple_inductive" 
       
  1064               "define inductive predicates"
       
  1065                  OuterKeyword.thy_decl specification*}
       
  1066 
       
  1067 
       
  1068 section {* Extensions (TBD) *}
       
  1069 
       
  1070 text {*
       
  1071   Things to include at the end:
       
  1072 
       
  1073   \begin{itemize}
       
  1074   \item include the code for the parameters
       
  1075   \item say something about add-inductive-i to return
       
  1076   the rules
       
  1077   \item say that the induction principle is weaker (weaker than
       
  1078   what the standard inductive package generates)
       
  1079   \item say that no conformity test is done
       
  1080   \item exercise about strong induction principles
       
  1081   \item exercise about the test for the intro rules
       
  1082   \end{itemize}
       
  1083   
       
  1084 *}
       
  1085 
       
  1086 (*
       
  1087 simple_inductive
       
  1088   Even and Odd
       
  1089 where
       
  1090   Even0: "Even 0"
       
  1091 | EvenS: "Odd n \<Longrightarrow> Even (Suc n)"
       
  1092 | OddS: "Even n \<Longrightarrow> Odd (Suc n)"
       
  1093 
       
  1094 thm Even0
       
  1095 thm EvenS
       
  1096 thm OddS
       
  1097 
       
  1098 thm Even_Odd.intros
       
  1099 thm Even.induct
       
  1100 thm Odd.induct
       
  1101 
       
  1102 thm Even_def
       
  1103 thm Odd_def
       
  1104 *)
       
  1105 
       
  1106 (*
       
  1107 text {* 
       
  1108   Second, we want that the user can specify fixed parameters.
       
  1109   Remember in the previous section we stated that the user can give the 
       
  1110   specification for the transitive closure of a relation @{text R} as 
       
  1111 *}
       
  1112 *)
       
  1113 
       
  1114 (*
       
  1115 simple_inductive
       
  1116   trcl\<iota>\<iota> :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool"
       
  1117 where
       
  1118   base: "trcl\<iota>\<iota> R x x"
       
  1119 | step: "trcl\<iota>\<iota> R x y \<Longrightarrow> R y z \<Longrightarrow> trcl\<iota>\<iota> R x z"
       
  1120 *)
       
  1121 
       
  1122 (*
       
  1123 text {*
       
  1124   Note that there is no locale given in this specification---the parameter
       
  1125   @{text "R"} therefore needs to be included explicitly in @{term trcl\<iota>\<iota>}, but
       
  1126   stays fixed throughout the specification. The problem with this way of
       
  1127   stating the specification for the transitive closure is that it derives the
       
  1128   following induction principle.
       
  1129 
       
  1130   \begin{center}\small
       
  1131   \mprset{flushleft}
       
  1132   \mbox{\inferrule{
       
  1133              @{thm_style prem1  trcl\<iota>\<iota>.induct[where P=P, where z=R, where za=x, where zb=y]}\\\\
       
  1134              @{thm_style prem2  trcl\<iota>\<iota>.induct[where P=P, where z=R, where za=x, where zb=y]}\\\\
       
  1135              @{thm_style prem3  trcl\<iota>\<iota>.induct[where P=P, where z=R, where za=x, where zb=y]}}
       
  1136             {@{thm_style concl  trcl\<iota>\<iota>.induct[where P=P, where z=R, where za=x, where zb=y]}}}  
       
  1137   \end{center}
       
  1138 
       
  1139   But this does not correspond to the induction principle we derived by hand, which
       
  1140   was
       
  1141   
       
  1142   
       
  1143   %\begin{center}\small
       
  1144   %\mprset{flushleft}
       
  1145   %\mbox{\inferrule{
       
  1146   %           @ { thm_style prem1  trcl_induct[no_vars]}\\\\
       
  1147   %           @ { thm_style prem2  trcl_induct[no_vars]}\\\\
       
  1148   %           @ { thm_style prem3  trcl_induct[no_vars]}}
       
  1149   %          {@ { thm_style concl  trcl_induct[no_vars]}}}  
       
  1150   %\end{center}
       
  1151 
       
  1152   The difference is that in the one derived by hand the relation @{term R} is not
       
  1153   a parameter of the proposition @{term P} to be proved and it is also not universally
       
  1154   qunatified in the second and third premise. The point is that the parameter @{term R}
       
  1155   stays fixed thoughout the definition and we do not want to regard it as an ``ordinary''
       
  1156   argument of the transitive closure, but one that can be freely instantiated. 
       
  1157   In order to recognise such parameters, we have to extend the specification
       
  1158   to include a mechanism to state fixed parameters. The user should be able
       
  1159   to write 
       
  1160 
       
  1161 *}
       
  1162 *)
       
  1163 (*
       
  1164 simple_inductive
       
  1165   trcl'' for R :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
       
  1166 where
       
  1167   base: "trcl'' R x x"
       
  1168 | step: "trcl'' R x y \<Longrightarrow> R y z \<Longrightarrow> trcl'' R x z"
       
  1169 
       
  1170 simple_inductive
       
  1171   accpart'' for R :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
       
  1172 where
       
  1173   accpartI: "(\<And>y. R y x \<Longrightarrow> accpart'' R y) \<Longrightarrow> accpart'' R x"
       
  1174 *)
       
  1175 (*<*)end(*>*)
  1035 (*<*)end(*>*)