ProgTutorial/Package/Ind_Code.thy
changeset 210 db8e302f44c8
parent 209 17b1512f51af
child 211 d5accbc67e1b
equal deleted inserted replaced
209:17b1512f51af 210:db8e302f44c8
     1 theory Ind_Code
     1 theory Ind_Code
     2 imports "../Base" "../FirstSteps" Simple_Inductive_Package Ind_Prelims
     2 imports "../Base" "../FirstSteps" Ind_General_Scheme 
     3 begin
     3 begin
     4 
     4 
     5 datatype trm =
     5 section {* The Gory Details *} 
     6   Var "string"
       
     7 | App "trm" "trm"
       
     8 | Lam "string" "trm"
       
     9 
       
    10 simple_inductive 
       
    11   fresh :: "string \<Rightarrow> trm \<Rightarrow> bool" ("_ \<sharp> _" [100,100] 100)
       
    12 where
       
    13   "a\<noteq>b \<Longrightarrow> a\<sharp>Var b"
       
    14 | "\<lbrakk>a\<sharp>t; a\<sharp>s\<rbrakk> \<Longrightarrow> a\<sharp>App t s"
       
    15 | "a\<sharp>Lam a t"
       
    16 | "\<lbrakk>a\<noteq>b; a\<sharp>t\<rbrakk> \<Longrightarrow> a\<sharp>Lam b t"
       
    17 
       
    18 section {* Code *}
       
    19 
       
    20 text {*
       
    21   
       
    22   @{text [display] "rule ::= \<And>xs. As \<Longrightarrow> (\<And>ys. Bs \<Longrightarrow> pred ss)\<^isup>* \<Longrightarrow> pred ts"}
       
    23 
       
    24   @{text [display] "orule ::= \<forall>xs. As \<longrightarrow> (\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>* \<longrightarrow> pred ts"}
       
    25 
       
    26   @{text [display] "def ::= pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
       
    27   
       
    28   @{text [display] "ind ::= \<And>zs. pred zs \<Longrightarrow> rules[preds::=Ps] \<Longrightarrow> P zs"}
       
    29 
       
    30   @{text [display] "oind ::= \<forall>zs. pred zs \<longrightarrow> orules[preds::=Ps] \<longrightarrow> P zs"}
       
    31 
       
    32   \underline{Induction proof}
       
    33   
       
    34   After ``objectivication'' we have 
       
    35    @{text "pred zs"} and @{text "orules[preds::=Ps]"}; and have to show
       
    36   @{text "P zs"}. Expanding @{text "pred zs"} gives @{text "\<forall>preds. orules \<longrightarrow> pred zs"}.
       
    37   Instantiating the @{text "preds"} with @{text "Ps"} gives
       
    38   @{text "orules[preds::=Ps] \<longrightarrow> P zs"}. So we can conclude with @{text "P zs"}.
       
    39 
       
    40   \underline{Intro proof}
       
    41 
       
    42   Assume we want to prove the $i$th intro rule. 
       
    43 
       
    44   We have to show @{text "\<forall>xs. As \<longrightarrow> (\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>* \<longrightarrow> pred ts"};
       
    45   expanding the defs, gives 
       
    46   
       
    47   @{text [display]
       
    48   "\<forall>xs. As \<longrightarrow> (\<forall>ys. Bs \<longrightarrow> (\<forall>preds. orules \<longrightarrow> pred ss))\<^isup>* \<longrightarrow>  (\<forall>preds. orules \<longrightarrow> pred ts"}
       
    49   
       
    50   By applying as many allI and impI as possible, we have
       
    51   
       
    52   @{text "As"}, @{text "(\<forall>ys. Bs \<longrightarrow> (\<forall>preds. orules \<longrightarrow> pred ss))\<^isup>*"},
       
    53   @{text "orules"}; and have to show @{text "pred ts"}
       
    54 
       
    55   the $i$th @{text "orule"} is of the 
       
    56   form @{text "\<forall>xs. As \<longrightarrow> (\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>* \<longrightarrow> pred ts"}.
       
    57   
       
    58   So we apply the $i$th @{text "orule"}, but we have to show the @{text "As"} (by assumption)
       
    59   and all @{text "(\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>*"}. For the latter we use the assumptions
       
    60   @{text "(\<forall>ys. Bs \<longrightarrow> (\<forall>preds. orules \<longrightarrow> pred ss))\<^isup>*"} and @{text "orules"}.
       
    61 
       
    62 
       
    63   \begin{center}
       
    64   ****************************
       
    65   \end{center}
       
    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 
     6 
   103 subsection {* Definitions *}
     7 subsection {* Definitions *}
   104 
     8 
   105 text {*
     9 text {*
   106   We first have to produce for each predicate the definition, whose general form is
    10   We first have to produce for each predicate the definition, whose general form is
   111   To do the latter, we use the following wrapper for 
    15   To do the latter, we use the following wrapper for 
   112   @{ML LocalTheory.define}. The wrapper takes a predicate name, a syntax
    16   @{ML LocalTheory.define}. The wrapper takes a predicate name, a syntax
   113   annotation and a term representing the right-hand side of the definition.
    17   annotation and a term representing the right-hand side of the definition.
   114 *}
    18 *}
   115 
    19 
   116 ML %linenosgray{*fun make_defs ((predname, syn), trm) lthy =
    20 ML %linenosgray{*fun make_defn ((predname, syn), trm) lthy =
   117 let 
    21 let 
   118   val arg = ((predname, syn), (Attrib.empty_binding, trm))
    22   val arg = ((predname, syn), (Attrib.empty_binding, trm))
   119   val ((_, (_ , thm)), lthy') = LocalTheory.define Thm.internalK arg lthy
    23   val ((_, (_ , thm)), lthy') = LocalTheory.define Thm.internalK arg lthy
   120 in 
    24 in 
   121   (thm, lthy') 
    25   (thm, lthy') 
   122 end*}
    26 end*}
   123 
    27 
   124 text {*
    28 text {*
   125   It returns the definition (as a theorem) and the local theory in which this definition has 
    29   It returns the definition (as a theorem) and the local theory in which this definition has 
   126   been made. In Line 4, @{ML internalK in Thm} is a flag attached to the 
    30   been made. In Line 4, @{ML internalK in Thm} is a flag attached to the 
   127   theorem (others possibilities are the flags @{ML definitionK in Thm} and @{ML axiomK in Thm}). 
    31   theorem (others possibile flags are @{ML definitionK in Thm} and @{ML axiomK in Thm}). 
   128   These flags just classify theorems and have no significant meaning, except 
    32   These flags just classify theorems and have no significant meaning, except 
   129   for tools that, for example, find theorems in the theorem database. We also
    33   for tools that, for example, find theorems in the theorem database. We also
   130   use @{ML empty_binding in Attrib} in Line 3, since the definition does 
    34   use @{ML empty_binding in Attrib} in Line 3, since for our inductive predicates 
   131   not need to have any theorem attributes. A testcase for this function is
    35   the definitions do not need to have any theorem attributes. A testcase for this 
       
    36   function is
   132 *}
    37 *}
   133 
    38 
   134 local_setup %gray {* fn lthy =>
    39 local_setup %gray {* fn lthy =>
   135 let
    40 let
   136   val arg = ((@{binding "MyTrue"}, NoSyn), @{term True})
    41   val arg = ((@{binding "MyTrue"}, NoSyn), @{term True})
   137   val (def, lthy') = make_defs arg lthy 
    42   val (def, lthy') = make_defn arg lthy 
   138 in
    43 in
   139   warning (str_of_thm_no_vars lthy' def); lthy'
    44   warning (str_of_thm_no_vars lthy' def); lthy'
   140 end *}
    45 end *}
   141 
    46 
   142 text {*
    47 text {*
   143   which makes the definition @{prop "MyTrue \<equiv> True"} and then prints it out. 
    48   which introduces the definition @{prop "MyTrue \<equiv> True"} and then prints it out. 
   144   Since we are testing the function inside \isacommand{local\_setup}, i.e., make
    49   Since we are testing the function inside \isacommand{local\_setup}, i.e., make
   145   changes to the ambient theory, we can query the definition with the usual
    50   changes to the ambient theory, we can query the definition with the usual
   146   command \isacommand{thm}:
    51   command \isacommand{thm}:
   147 
    52 
   148   \begin{isabelle}
    53   \begin{isabelle}
   158   When constructing them, the variables @{text "zs"} need to be chosen so that
    63   When constructing them, the variables @{text "zs"} need to be chosen so that
   159   they do not occur in the @{text orules} and also be distinct from the @{text
    64   they do not occur in the @{text orules} and also be distinct from the @{text
   160   "preds"}.
    65   "preds"}.
   161 
    66 
   162 
    67 
   163   The first function constructs the term for one particular predicate, say
    68   The first function constructs the term for one particular predicate (the
   164   @{text "pred"}. The number of arguments of this predicate is
    69   argument @{text "pred"} in the code belo). The number of arguments of this predicate is
   165   determined by the number of argument types given in @{text "arg_tys"}. 
    70   determined by the number of argument types given in @{text "arg_tys"}. 
   166   The other arguments are all the @{text "preds"} and the @{text "orules"}.
    71   The other arguments are all the @{text "preds"} and the @{text "orules"}.
   167 *}
    72 *}
   168 
    73 
   169 ML %linenosgray{*fun defs_aux lthy orules preds (pred, arg_tys) =
    74 ML %linenosgray{*fun defn_aux lthy orules preds (pred, arg_tys) =
   170 let 
    75 let 
   171   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
    76   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
   172 
    77 
   173   val fresh_args = 
    78   val fresh_args = 
   174         arg_tys 
    79         arg_tys 
   200 
   105 
   201 local_setup %gray{* fn lthy =>
   106 local_setup %gray{* fn lthy =>
   202 let
   107 let
   203   val pred = @{term "even::nat\<Rightarrow>bool"}
   108   val pred = @{term "even::nat\<Rightarrow>bool"}
   204   val arg_tys = [@{typ "nat"}]
   109   val arg_tys = [@{typ "nat"}]
   205   val def = defs_aux lthy eo_orules eo_preds (pred, arg_tys)
   110   val def = defn_aux lthy eo_orules eo_preds (pred, arg_tys)
   206 in
   111 in
   207   warning (Syntax.string_of_term lthy def); lthy
   112   warning (Syntax.string_of_term lthy def); lthy
   208 end *}
   113 end *}
   209 
   114 
   210 text {*
   115 text {*
   211   The testcase  calls @{ML defs_aux} for the predicate @{text "even"} and prints
   116   The testcase  calls @{ML defn_aux} for the predicate @{text "even"} and prints
   212   out the generated definition. So we obtain as printout 
   117   out the generated definition. So we obtain as printout 
   213 
   118 
   214   @{text [display] 
   119   @{text [display] 
   215 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   120 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   216                          \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
   121                          \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
   217 
   122 
       
   123   If we try out the function for the definition of freshness
       
   124 *}
       
   125 
       
   126 local_setup %gray{* fn lthy =>
       
   127  (warning (Syntax.string_of_term lthy
       
   128     (defn_aux lthy fresh_orules [fresh_pred] (fresh_pred, fresh_arg_tys)));
       
   129   lthy) *}
       
   130 
       
   131 text {*
       
   132   we obtain
       
   133 
       
   134   @{term [display] 
       
   135 "\<lambda>z za. \<forall>fresh. (\<forall>a b. \<not> a = b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
       
   136                (\<forall>a s t. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
       
   137                 (\<forall>a t. fresh a (Lam a t)) \<longrightarrow>
       
   138                 (\<forall>a b t. \<not> a = b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh z za"}
       
   139 
       
   140 
   218   The second function for the definitions has to just iterate the function
   141   The second function for the definitions has to just iterate the function
   219   @{ML defs_aux} over all predicates. The argument @{text "preds"} is again
   142   @{ML defn_aux} over all predicates. The argument @{text "preds"} is again
   220   the the list of predicates as @{ML_type term}s; the argument @{text
   143   the the list of predicates as @{ML_type term}s; the argument @{text
   221   "prednames"} is the list of names of the predicates; @{text syns} are the
   144   "prednames"} is the list of names of the predicates; @{text syns} are the
   222   syntax annotations for each predicate; @{text "arg_tyss"} is
   145   syntax annotations for each predicate; @{text "arg_tyss"} is
   223   the list of argument-type-lists for each predicate.
   146   the list of argument-type-lists for each predicate.
   224 *}
   147 *}
   225 
   148 
   226 ML %linenosgray{*fun definitions rules preds prednames syns arg_typss lthy =
   149 ML %linenosgray{*fun defns rules preds prednames syns arg_typss lthy =
   227 let
   150 let
   228   val thy = ProofContext.theory_of lthy
   151   val thy = ProofContext.theory_of lthy
   229   val orules = map (ObjectLogic.atomize_term thy) rules
   152   val orules = map (ObjectLogic.atomize_term thy) rules
   230   val defs = map (defs_aux lthy orules preds) (preds ~~ arg_typss) 
   153   val defs = map (defn_aux lthy orules preds) (preds ~~ arg_typss) 
   231 in
   154 in
   232   fold_map make_defs (prednames ~~ syns ~~ defs) lthy
   155   fold_map make_defn (prednames ~~ syns ~~ defs) lthy
   233 end*}
   156 end*}
   234 
   157 
   235 text {*
   158 text {*
   236   The user will state the introduction rules using meta-implications and
   159   The user will state the introduction rules using meta-implications and
   237   meta-quanti\-fications. In Line 4, we transform these introduction rules into
   160   meta-quanti\-fications. In Line 4, we transform these introduction rules into
   238   the object logic (since definitions cannot be stated with
   161   the object logic (since definitions cannot be stated with
   239   meta-connectives). To do this transformation we have to obtain the theory
   162   meta-connectives). To do this transformation we have to obtain the theory
   240   behind the local theory (Line 3); with this theory we can use the function
   163   behind the local theory (Line 3); with this theory we can use the function
   241   @{ML ObjectLogic.atomize_term} to make the transformation (Line 4). The call
   164   @{ML ObjectLogic.atomize_term} to make the transformation (Line 4). The call
   242   to @{ML defs_aux} in Line 5 produces all right-hand sides of the
   165   to @{ML defn_aux} in Line 5 produces all right-hand sides of the
   243   definitions. The actual definitions are then made in Line 7.  The result
   166   definitions. The actual definitions are then made in Line 7.  The result
   244   of the function is a list of theorems and a local theory. A testcase for 
   167   of the function is a list of theorems and a local theory. A testcase for 
   245   this function is 
   168   this function is 
   246 *}
   169 *}
   247 
   170 
   248 local_setup %gray {* fn lthy =>
   171 local_setup %gray {* fn lthy =>
   249 let
   172 let
   250   val (defs, lthy') = 
   173   val (defs, lthy') = 
   251     definitions eo_rules eo_preds eo_prednames eo_syns eo_arg_tyss lthy
   174     defns eo_rules eo_preds eo_prednames eo_syns eo_arg_tyss lthy
   252 in
   175 in
   253   warning (str_of_thms_no_vars lthy' defs); lthy
   176   warning (str_of_thms_no_vars lthy' defs); lthy
   254 end *}
   177 end *}
   255 
   178 
   256 text {*
   179 text {*
   257   where we feed into the functions all parameters corresponding to
   180   where we feed into the functions all parameters corresponding to
   258   the @{text even}-@{text odd} example. The definitions we obtain
   181   the @{text even}-@{text odd} example. The definitions we obtain
   259   are:
   182   are:
   260 
   183 
   261   \begin{isabelle}
   184   @{text [display, break]
   262   @{text [break]
   185 "even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n))  
   263 "> even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   186                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z,
   264 >                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z,
   187 odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   265 > odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   188                                \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
   266 >                                \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
       
   267   \end{isabelle}
       
   268 
   189 
   269   Note that in the testcase we return the local theory @{text lthy} 
   190   Note that in the testcase we return the local theory @{text lthy} 
   270   (not the modified @{text lthy'}). As a result the test case has no effect
   191   (not the modified @{text lthy'}). As a result the test case has no effect
   271   on the ambient theory. The reason is that if we make again the
   192   on the ambient theory. The reason is that if we introduce the
   272   definition, we pollute the name space with two versions of @{text "even"} 
   193   definition again, we pollute the name space with two versions of @{text "even"} 
   273   and @{text "odd"}.
   194   and @{text "odd"}.
   274 
   195 
   275   This completes the code for making the definitions. Next we deal with
   196   This completes the code for introducing the definitions. Next we deal with
   276   the induction principles. 
   197   the induction principles. 
   277 *}
   198 *}
   278 
   199 
   279 subsection {* Introduction Rules *}
   200 subsection {* Induction Principles *}
   280 
   201 
   281 text {*
   202 text {*
   282   Recall that the proof of the induction principle 
   203   Recall that the proof of the induction principle 
   283   for @{text "even"} was:
   204   for @{text "even"} was:
   284 *}
   205 *}
   285 
   206 
   286 lemma manual_ind_prin: 
   207 lemma manual_ind_prin_even: 
   287 assumes prem: "even z"
   208 assumes prem: "even z"
   288 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
   209 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
   289 apply(atomize (full))
   210 apply(atomize (full))
   290 apply(cut_tac prem)
   211 apply(cut_tac prem)
   291 apply(unfold even_def)
   212 apply(unfold even_def)
   336 text {*
   257 text {*
   337   Now the complete tactic for proving the induction principles can 
   258   Now the complete tactic for proving the induction principles can 
   338   be implemented as follows:
   259   be implemented as follows:
   339 *}
   260 *}
   340 
   261 
   341 ML %linenosgray{*fun induction_tac defs prem insts =
   262 ML %linenosgray{*fun ind_tac defs prem insts =
   342   EVERY1 [ObjectLogic.full_atomize_tac,
   263   EVERY1 [ObjectLogic.full_atomize_tac,
   343           cut_facts_tac prem,
   264           cut_facts_tac prem,
   344           K (rewrite_goals_tac defs),
   265           K (rewrite_goals_tac defs),
   345           inst_spec_tac insts,
   266           inst_spec_tac insts,
   346           assume_tac]*}
   267           assume_tac]*}
   347 
   268 
   348 text {*
   269 text {*
   349   We have to give it as arguments the definitions, the premise 
   270   We have to give it as arguments the definitions, the premise (this premise
   350   (for example @{text "even n"}) and the instantiations. Compare this with the 
   271   is @{text "even n"} in lemma @{thm [source] manual_ind_prin_even}) and the
   351   manual proof given for the lemma @{thm [source] manual_ind_prin}: 
   272   instantiations. Compare this tactic with the manual for the lemma @{thm
   352   as you can see there is almost a one-to-one correspondence between the \isacommand{apply}-script 
   273   [source] manual_ind_prin_even}: as you can see there is almost a one-to-one
   353   and the @{ML induction_tac}. A testcase for this tactic is the function
   274   correspondence between the \isacommand{apply}-script and the @{ML
   354 *}
   275   ind_tac}. Two testcases for this tactic are:
   355 
   276 *}
   356 ML{*fun test_tac prem = 
   277 
   357 let
   278 lemma automatic_ind_prin_even:
   358   val insts = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
       
   359 in 
       
   360   induction_tac eo_defs prem insts 
       
   361 end*}
       
   362 
       
   363 text {*
       
   364   which indeed proves the induction principle: 
       
   365 *}
       
   366 
       
   367 lemma automatic_ind_prin:
       
   368 assumes prem: "even z"
   279 assumes prem: "even z"
   369 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
   280 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
   370 apply(tactic {* test_tac @{thms prem} *})
   281 by (tactic {* ind_tac eo_defs @{thms prem} 
   371 done
   282                     [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] *})
   372 
   283 
   373 text {*
   284 lemma automatic_ind_prin_fresh:
   374   This gives the theorem:
   285 assumes prem: "fresh z za" 
       
   286 shows "(\<And>a b. a \<noteq> b \<Longrightarrow> P a (Var b)) \<Longrightarrow> 
       
   287         (\<And>a t s. \<lbrakk>P a t; P a s\<rbrakk> \<Longrightarrow> P a (App t s)) \<Longrightarrow>
       
   288         (\<And>a t. P a (Lam a t)) \<Longrightarrow> 
       
   289         (\<And>a b t. \<lbrakk>a \<noteq> b; P a t\<rbrakk> \<Longrightarrow> P a (Lam b t)) \<Longrightarrow> P z za"
       
   290 by (tactic {* ind_tac @{thms fresh_def} @{thms prem} 
       
   291                     [@{cterm "P::string\<Rightarrow>trm\<Rightarrow>bool"}] *})
       
   292 
       
   293 
       
   294 text {*
       
   295   Let us have a closer look at the first proved theorem:
   375 
   296 
   376   \begin{isabelle}
   297   \begin{isabelle}
   377   \isacommand{thm}~@{thm [source] automatic_ind_prin}\\
   298   \isacommand{thm}~@{thm [source] automatic_ind_prin_even}\\
   378   @{text "> "}~@{thm automatic_ind_prin}
   299   @{text "> "}~@{thm automatic_ind_prin_even}
   379   \end{isabelle}
   300   \end{isabelle}
   380 
   301 
   381   While the tactic for the induction principle is relatively simple, 
   302   The variables @{text "z"}, @{text "P"} and @{text "Q"} are schematic
   382   it is a bit harder to construct the goals from the introduction 
   303   variables (since they are not quantified in the lemma). These schematic
   383   rules the user provides. In general we have to construct for each predicate 
   304   variables are needed so that they can be instantiated by the user later
   384   @{text "pred"} a goal of the form
   305   on. We have to take care to also generate these schematic variables when
       
   306   generating the goals for the induction principles. While the tactic for
       
   307   proving the induction principles is relatively simple, it will be a bit
       
   308   of work to construct the goals from the introduction rules the user
       
   309   provides. In general we have to construct for each predicate @{text "pred"}
       
   310   a goal of the form
   385 
   311 
   386   @{text [display] 
   312   @{text [display] 
   387   "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"}
   313   "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"}
   388 
   314 
   389   where the predicates @{text preds} are replaced in the introduction 
   315   where the predicates @{text preds} are replaced in the introduction 
   395 
   321 
   396   We generate these goals in two steps. The first function expects that the
   322   We generate these goals in two steps. The first function expects that the
   397   introduction rules are already appropriately substituted. The argument
   323   introduction rules are already appropriately substituted. The argument
   398   @{text "srules"} stands for these substituted rules; @{text cnewpreds} are
   324   @{text "srules"} stands for these substituted rules; @{text cnewpreds} are
   399   the certified terms coresponding to the variables @{text "?Ps"}; @{text
   325   the certified terms coresponding to the variables @{text "?Ps"}; @{text
   400   "pred"} is the predicate for which we prove the introduction principle;
   326   "pred"} is the predicate for which we prove the induction principle;
   401   @{text "newpred"} is its replacement and @{text "arg_tys"} are the argument
   327   @{text "newpred"} is its replacement and @{text "arg_tys"} are the argument
   402   types of this predicate.
   328   types of this predicate.
   403 *}
   329 *}
   404 
   330 
   405 ML %linenosgray{*fun prove_induction lthy defs srules cnewpreds ((pred, newpred), arg_tys) =
   331 ML %linenosgray{*fun prove_ind lthy defs srules cnewpreds ((pred, newpred), arg_tys) =
   406 let
   332 let
   407   val zs = replicate (length arg_tys) "z"
   333   val zs = replicate (length arg_tys) "z"
   408   val (newargnames, lthy') = Variable.variant_fixes zs lthy;
   334   val (newargnames, lthy') = Variable.variant_fixes zs lthy;
   409   val newargs = map Free (newargnames ~~ arg_tys)
   335   val newargs = map Free (newargnames ~~ arg_tys)
   410   
   336   
   411   val prem = HOLogic.mk_Trueprop (list_comb (pred, newargs))
   337   val prem = HOLogic.mk_Trueprop (list_comb (pred, newargs))
   412   val goal = Logic.list_implies 
   338   val goal = Logic.list_implies 
   413          (srules, HOLogic.mk_Trueprop (list_comb (newpred, newargs)))
   339          (srules, HOLogic.mk_Trueprop (list_comb (newpred, newargs)))
   414 in
   340 in
   415   Goal.prove lthy' [] [prem] goal
   341   Goal.prove lthy' [] [prem] goal
   416   (fn {prems, ...} => induction_tac defs prems cnewpreds)
   342       (fn {prems, ...} => ind_tac defs prems cnewpreds)
   417   |> singleton (ProofContext.export lthy' lthy)
   343   |> singleton (ProofContext.export lthy' lthy)
   418 end *}
   344 end *}
   419 
   345 
   420 text {* 
   346 text {* 
   421   In Line 3 we produce names @{text "zs"} for each type in the 
   347   In Line 3 we produce names @{text "zs"} for each type in the 
   422   argument type list. Line 4 makes these names unique and declares them as 
   348   argument type list. Line 4 makes these names unique and declares them as 
   423   \emph{free} (but fixed) variables in the local theory @{text "lthy'"}. In 
   349   \emph{free} (but fixed) variables in the local theory @{text "lthy'"}. 
   424   Line 5 we construct the terms corresponding to these variables. 
   350   That means they are not (yet) schematic variables.
       
   351   In Line 5 we construct the terms corresponding to these variables. 
   425   The variables are applied to the predicate in Line 7 (this corresponds
   352   The variables are applied to the predicate in Line 7 (this corresponds
   426   to the first premise @{text "pred zs"} of the induction principle). 
   353   to the first premise @{text "pred zs"} of the induction principle). 
   427   In Line 8 and 9, we first construct the term  @{text "P zs"} 
   354   In Line 8 and 9, we first construct the term  @{text "P zs"} 
   428   and then add the (substituted) introduction rules as premises. In case that
   355   and then add the (substituted) introduction rules as premises. In case that
   429   no introduction rules are given, the conclusion of this implication needs
   356   no introduction rules are given, the conclusion of this implication needs
   435   expects the definitions, the premise and the (certified) predicates with
   362   expects the definitions, the premise and the (certified) predicates with
   436   which the introduction rules have been substituted. The code in these two
   363   which the introduction rules have been substituted. The code in these two
   437   lines will return a theorem. However, it is a theorem
   364   lines will return a theorem. However, it is a theorem
   438   proved inside the local theory @{text "lthy'"}, where the variables @{text
   365   proved inside the local theory @{text "lthy'"}, where the variables @{text
   439   "zs"} are fixed, but free (see Line 4). By exporting this theorem from @{text
   366   "zs"} are fixed, but free (see Line 4). By exporting this theorem from @{text
   440   "lthy'"} (which contains the @{text "zs"} as free) to @{text
   367   "lthy'"} (which contains the @{text "zs"} as free variables) to @{text
   441   "lthy"} (which does not), we obtain the desired schematic variables @{text "?zs"}.
   368   "lthy"} (which does not), we obtain the desired schematic variables @{text "?zs"}.
   442   A testcase for this function is
   369   A testcase for this function is
   443 *}
   370 *}
   444 
   371 
   445 local_setup %gray{* fn lthy =>
   372 local_setup %gray{* fn lthy =>
   446 let
   373 let
   447   val srules = [@{prop "P (0::nat)"},
   374   val newpreds = [@{term "P::nat\<Rightarrow>bool"}, @{term "Q::nat\<Rightarrow>bool"}]
   448                 @{prop "\<And>n::nat. Q n \<Longrightarrow> P (Suc n)"},
       
   449                 @{prop "\<And>n::nat. P n \<Longrightarrow> Q (Suc n)"}] 
       
   450   val cnewpreds = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
   375   val cnewpreds = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
   451   val pred = @{term "even::nat\<Rightarrow>bool"}
   376   val srules =  map (subst_free (eo_preds ~~ newpreds)) eo_rules
   452   val newpred = @{term "P::nat\<Rightarrow>bool"}
   377   val newpred = @{term "P::nat\<Rightarrow>bool"}
   453   val arg_tys = [@{typ "nat"}]
       
   454   val intro = 
   378   val intro = 
   455     prove_induction lthy eo_defs srules cnewpreds ((pred, newpred), arg_tys)
   379        prove_ind lthy eo_defs srules cnewpreds ((e_pred, newpred), e_arg_tys)
   456 in
   380 in
   457   warning (str_of_thm lthy intro); lthy
   381   warning (str_of_thm lthy intro); lthy
   458 end *} 
   382 end *}
   459 
   383 
   460 text {*
   384 text {*
   461   This prints out:
   385   This prints out the theorem:
   462 
   386 
   463   @{text [display]
   387   @{text [display]
   464   " \<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"}
   388   " \<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"}
   465 
   389 
   466   Note that the export from @{text lthy'} to @{text lthy} in Line 13 above 
   390   The export from @{text lthy'} to @{text lthy} in Line 13 above 
   467   has turned the free, but fixed, @{text "z"} into a schematic 
   391   has correctly turned the free, but fixed, @{text "z"} into a schematic 
   468   variable @{text "?z"}; the variables @{text "P"} and @{text "Q"} are not yet
   392   variable @{text "?z"}; the variables @{text "P"} and @{text "Q"} are not yet
   469   schematic. 
   393   schematic. 
   470 
   394 
   471   We still have to produce the new predicates with which the introduction
   395   We still have to produce the new predicates with which the introduction
   472   rules are substituted and iterate @{ML prove_induction} over all
   396   rules are substituted and iterate @{ML prove_ind} over all
   473   predicates. This is what the second function does: 
   397   predicates. This is what the second function does: 
   474 *}
   398 *}
   475 
   399 
   476 ML %linenosgray{*fun inductions rules defs preds arg_tyss lthy  =
   400 ML %linenosgray{*fun inds rules defs preds arg_tyss lthy  =
   477 let
   401 let
   478   val Ps = replicate (length preds) "P"
   402   val Ps = replicate (length preds) "P"
   479   val (newprednames, lthy') = Variable.variant_fixes Ps lthy
   403   val (newprednames, lthy') = Variable.variant_fixes Ps lthy
   480   
   404   
   481   val thy = ProofContext.theory_of lthy'
   405   val thy = ProofContext.theory_of lthy'
   484   val newpreds = map Free (newprednames ~~ tyss')
   408   val newpreds = map Free (newprednames ~~ tyss')
   485   val cnewpreds = map (cterm_of thy) newpreds
   409   val cnewpreds = map (cterm_of thy) newpreds
   486   val srules = map (subst_free (preds ~~ newpreds)) rules
   410   val srules = map (subst_free (preds ~~ newpreds)) rules
   487 
   411 
   488 in
   412 in
   489   map (prove_induction lthy' defs srules cnewpreds) 
   413   map (prove_ind lthy' defs srules cnewpreds) 
   490         (preds ~~ newpreds ~~ arg_tyss)
   414         (preds ~~ newpreds ~~ arg_tyss)
   491           |> ProofContext.export lthy' lthy
   415           |> ProofContext.export lthy' lthy
   492 end*}
   416 end*}
   493 
   417 
   494 text {*
   418 text {*
   509   A testcase for this function is
   433   A testcase for this function is
   510 *}
   434 *}
   511 
   435 
   512 local_setup %gray {* fn lthy =>
   436 local_setup %gray {* fn lthy =>
   513 let 
   437 let 
   514   val ind_thms = inductions eo_rules eo_defs eo_preds eo_arg_tyss lthy
   438   val ind_thms = inds eo_rules eo_defs eo_preds eo_arg_tyss lthy
   515 in
   439 in
   516   warning (str_of_thms lthy ind_thms); lthy
   440   warning (str_of_thms lthy ind_thms); lthy
   517 end *}
   441 end *}
   518 
   442 
   519 
   443 
   520 text {*
   444 text {*
   521   which prints out
   445   which prints out
   522 
   446 
   523 @{text [display]
   447 @{text [display]
   524 "> even ?z \<Longrightarrow> ?P1 0 \<Longrightarrow> 
   448 "even ?z \<Longrightarrow> ?P1 0 \<Longrightarrow> 
   525 > (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?P1 ?z,
   449  (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?P1 ?z,
   526 > odd ?z \<Longrightarrow> ?P1 0 \<Longrightarrow>
   450 odd ?z \<Longrightarrow> ?P1 0 \<Longrightarrow>
   527 > (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?Pa1 ?z"}
   451  (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?Pa1 ?z"}
   528 
   452 
   529   Note that now both, the @{text "?Ps"} and the @{text "?zs"}, are schematic
   453   Note that now both, the @{text "?Ps"} and the @{text "?zs"}, are schematic
   530   variables. The numbers have been introduced by the pretty-printer and are 
   454   variables. The numbers attached to these variables have been introduced by 
   531   not significant.
   455   the pretty-printer and are \emph{not} important for the user. 
   532 
   456 
   533   This completes the code for the induction principles.  
   457   This completes the code for the induction principles. The final peice
       
   458   of reasoning infrastructure we need are the introduction rules. 
   534 *}
   459 *}
   535 
   460 
   536 subsection {* Introduction Rules *}
   461 subsection {* Introduction Rules *}
   537 
   462 
   538 text {*
   463 text {*
   539   Finally we can prove the introduction rules. Their proofs are quite a bit
   464   The proofs of the introduction rules are quite a bit
   540   more involved. To ease these proofs somewhat we use the following two helper
   465   more involved than the ones for the induction principles. 
       
   466   To ease somewhat our work here, we use the following two helper
   541   functions.
   467   functions.
   542 
   468 
   543 *}
   469 *}
   544 
   470 
   545 ML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct)
   471 ML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct)
   553 lemma all_elims_test:
   479 lemma all_elims_test:
   554   fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   480   fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   555   shows "\<forall>x y z. P x y z" sorry
   481   shows "\<forall>x y z. P x y z" sorry
   556 
   482 
   557 lemma imp_elims_test:
   483 lemma imp_elims_test:
   558   fixes A B C::"bool"
       
   559   shows "A \<longrightarrow> B \<longrightarrow> C" sorry
   484   shows "A \<longrightarrow> B \<longrightarrow> C" sorry
   560 
   485 
   561 lemma imp_elims_test':
   486 lemma imp_elims_test':
   562   fixes A::"bool"
       
   563   shows "A" "B" sorry
   487   shows "A" "B" sorry
   564 
   488 
   565 text {*
   489 text {*
   566   The function @{ML all_elims} takes a list of (certified) terms and instantiates
   490   The function @{ML all_elims} takes a list of (certified) terms and instantiates
   567   theorems of the form @{thm [source] all_elims_test}. For example we can instantiate
   491   theorems of the form @{thm [source] all_elims_test}. For example we can instantiate
   568   the quantifiers in this theorem with @{term a}, @{term b} and @{term c} as follows
   492   the quantifiers in this theorem with @{term a}, @{term b} and @{term c} as follows:
   569 
   493 
   570   @{ML_response_fake [display, gray]
   494   @{ML_response_fake [display, gray]
   571 "let
   495 "let
   572   val ctrms = [@{cterm \"a::nat\"}, @{cterm \"b::nat\"}, @{cterm \"c::nat\"}]
   496   val ctrms = [@{cterm \"a::nat\"}, @{cterm \"b::nat\"}, @{cterm \"c::nat\"}]
   573   val new_thm = all_elims ctrms @{thm all_elims_test}
   497   val new_thm = all_elims ctrms @{thm all_elims_test}
   575   warning (str_of_thm_no_vars @{context} new_thm)
   499   warning (str_of_thm_no_vars @{context} new_thm)
   576 end"
   500 end"
   577   "P a b c"}
   501   "P a b c"}
   578 
   502 
   579   Similarly, the function @{ML imp_elims} eliminates preconditions from implications. 
   503   Similarly, the function @{ML imp_elims} eliminates preconditions from implications. 
   580   For example: 
   504   For example we can eliminate the preconditions @{text "A"} and @{text "B"} from
       
   505   @{thm [source] imp_elims_test}:
   581 
   506 
   582   @{ML_response_fake [display, gray]
   507   @{ML_response_fake [display, gray]
   583 "warning (str_of_thm_no_vars @{context} 
   508 "warning (str_of_thm_no_vars @{context} 
   584             (imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}))"
   509             (imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}))"
   585   "C"}
   510   "C"}
   586 
   511 
   587   We now look closely at the proof for the introduction rule
   512   To explain the proof for the introduction rule, our running example will be
       
   513   the rule:
   588 
   514 
   589   \begin{isabelle}
   515   \begin{isabelle}
   590   @{term "\<lbrakk>a\<sharp>t; a\<sharp>s\<rbrakk> \<Longrightarrow> a\<sharp>App t s"}
   516   @{prop "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"}
   591   \end{isabelle}
   517   \end{isabelle}
   592   
   518   
   593 *}
   519   for freshness of applications. We set up the proof as follows:
   594 
   520 *}
   595 
   521 
   596 lemma fresh_App:
   522 lemma fresh_App:
   597   shows "\<lbrakk>a\<sharp>t; a\<sharp>s\<rbrakk> \<Longrightarrow> a\<sharp>App t s"
   523   shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   598 apply(tactic {* ObjectLogic.rulify_tac 1 *})
   524 (*<*)oops(*>*)
   599 apply(tactic {* rewrite_goals_tac [@{thm fresh_def}] *})
   525 
   600 apply(tactic {* REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1) *})
   526 text {*
   601 apply(tactic {* print_tac "" *})
   527   The first step will be to expand the definitions of freshness
       
   528   and then introduce quantifiers and implications. For this we
       
   529   will use the tactic
       
   530 *}
       
   531 
       
   532 ML{*fun expand_tac defs =
       
   533   ObjectLogic.rulify_tac 1
       
   534   THEN rewrite_goals_tac defs
       
   535   THEN (REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1)) *}
       
   536 
       
   537 text {*
       
   538   The first step of ``rulifying'' the lemma will turn out important
       
   539   later on. Applying this tactic 
       
   540 *}
       
   541 
       
   542 (*<*)
       
   543 lemma fresh_App:
       
   544   shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
       
   545 (*>*)
       
   546 apply(tactic {* expand_tac @{thms fresh_def} *})
   602 
   547 
   603 txt {*
   548 txt {*
       
   549   we end up in the goal state
       
   550 
   604   \begin{isabelle}
   551   \begin{isabelle}
   605   @{subgoals}
   552   @{subgoals [display]}
   606   \end{isabelle}
   553   \end{isabelle}
   607 *}
   554 
   608 
   555   As you can see, there are parameters (namely @{text "a"}, @{text "b"} 
   609 ML_prf {* fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac *}
   556   and @{text "t"}) which come from the introduction rule and parameters
   610 
   557   (in the case above only @{text "fresh"}) which come from the universal
   611 apply(tactic {* SUBPROOF_test (fn {params, prems, ...} =>
   558   quantification in the definition @{term "fresh a (App t s)"}.
   612    let
   559   Similarly, there are preconditions
   613      val (prems1, prems2) = chop (length prems - length fresh_rules) prems
   560   that come from the premises of the rule and premises from the
   614      val (params1, params2) = chop (length params - length fresh_preds) params
   561   definition. We need to treat these 
   615    in
   562   parameters and preconditions differently. In the code below
   616      no_tac
   563   we will therefore separate them into @{text "params1"} and @{text params2},
   617    end) @{context} *})
   564   respectively @{text "prems1"} and @{text "prems2"}. To do this 
   618 oops
   565   separation, it is best to open a subproof with the tactic 
   619 
   566   @{ML SUBPROOF}, since this tactic provides us
   620 
   567   with the parameters (as list of @{ML_type cterm}s) and the premises
   621 ML{*fun subproof2 prem params2 prems2 =  
   568   (as list of @{ML_type thm}s). The problem we have to overcome 
   622  SUBPROOF (fn {prems, ...} =>
   569   with @{ML SUBPROOF} is that this tactic always expects us to completely 
   623    let
   570   discharge with the goal (see Section ???). This is inconvenient for
   624      val prem' = prems MRS prem;
   571   our gradual explanation of the proof. To circumvent this inconvenience
   625      val prem'' = 
   572   we use the following modified tactic: 
   626        case prop_of prem' of
   573 *}
       
   574 (*<*)oops(*>*)
       
   575 ML{*fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac*}
       
   576 
       
   577 text {*
       
   578   If the tactic inside @{ML SUBPROOF} fails, then the overall tactic will
       
   579   still succeed. With this testing tactic, we can gradually implement
       
   580   all necessary proof steps.
       
   581 *}
       
   582 
       
   583 text_raw {*
       
   584 \begin{figure}[t]
       
   585 \begin{minipage}{\textwidth}
       
   586 \begin{isabelle}
       
   587 *}
       
   588 ML{*fun chop_print params1 params2 prems1 prems2 ctxt =
       
   589 let 
       
   590   val s = ["Params1 from the rule:", str_of_cterms ctxt params1] 
       
   591         @ ["Params2 from the predicate:", str_of_cterms ctxt params2] 
       
   592         @ ["Prems1 from the rule:"] @ (map (str_of_thm ctxt) prems1) 
       
   593         @ ["Prems2 from the predicate:"] @ (map (str_of_thm ctxt) prems2) 
       
   594 in 
       
   595   s |> separate "\n"
       
   596     |> implode
       
   597     |> warning
       
   598 end*}
       
   599 text_raw{*
       
   600 \end{isabelle}
       
   601 \end{minipage}
       
   602 \caption{FIXME\label{fig:chopprint}}
       
   603 \end{figure}
       
   604 *}
       
   605 
       
   606 text {*
       
   607   First we calculate the values for @{text "params1/2"} and @{text "prems1/2"}
       
   608   from @{text "params"} and @{text "prems"}, respectively. To see what is
       
   609   going in our example, we will print out the values using the printing
       
   610   function in Figure~\ref{fig:chopprint}. Since the tactic @{ML SUBPROOF} will
       
   611   supply us the @{text "params"} and @{text "prems"} as lists, we can 
       
   612   separate them using the function @{ML chop}. 
       
   613 *}
       
   614 
       
   615 ML{*fun chop_test_tac preds rules =
       
   616   SUBPROOF_test (fn {params, prems, context, ...} =>
       
   617   let
       
   618     val (params1, params2) = chop (length params - length preds) params
       
   619     val (prems1, prems2) = chop (length prems - length rules) prems
       
   620   in
       
   621     chop_print params1 params2 prems1 prems2 context; no_tac
       
   622   end) *}
       
   623 
       
   624 text {* 
       
   625   For the separation we can rely on that Isabelle deterministically 
       
   626   produces parameter and premises in a goal state. The last parameters
       
   627   that were introduced, come from the quantifications in the definitions.
       
   628   Therefore we only have to subtract the number of predicates (in this
       
   629   case only @{text "1"} from the lenghts of all parameters. Similarly
       
   630   with the @{text "prems"}. The last premises in the goal state must
       
   631   come from unfolding of the conclusion. So we can just subtract
       
   632   the number of rules from the number of all premises. Applying
       
   633   this tactic in our example 
       
   634 *}
       
   635 
       
   636 (*<*)
       
   637 lemma fresh_App:
       
   638   shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
       
   639 apply(tactic {* expand_tac @{thms fresh_def} *})
       
   640 (*>*)
       
   641 apply(tactic {* chop_test_tac [fresh_pred] fresh_rules @{context} *})
       
   642 (*<*)oops(*>*)
       
   643 
       
   644 text {*
       
   645   gives
       
   646 
       
   647   \begin{isabelle}
       
   648   @{text "Params1 from the rule:"}\\
       
   649   @{text "a, b, t"}\\
       
   650   @{text "Params2 from the predicate:"}\\
       
   651   @{text "fresh"}\\
       
   652   @{text "Prems1 from the rule:"}\\
       
   653   @{term "a \<noteq> b"}\\
       
   654   @{text [break]
       
   655 "\<forall>fresh.
       
   656       (\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
       
   657       (\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
       
   658       (\<forall>a t. fresh a (Lam a t)) \<longrightarrow> 
       
   659       (\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh a t"}\\
       
   660    @{text "Prems2 from the predicate:"}\\
       
   661    @{term "\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)"}\\
       
   662    @{term "\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)"}\\
       
   663    @{term "\<forall>a t. fresh a (Lam a t)"}\\
       
   664    @{term "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)"}
       
   665   \end{isabelle}
       
   666 
       
   667 
       
   668   We now have to select from @{text prems2} the premise 
       
   669   that corresponds to the introduction rule we prove, namely:
       
   670 
       
   671   @{term [display] "\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)"}
       
   672 
       
   673   To use this premise with @{ML rtac}, we need to instantiate its 
       
   674   quantifiers (with @{text params1}) and transform it into a 
       
   675   introduction rule (using @{ML "ObjectLogic.rulify"}. 
       
   676   So we can modify the subproof as follows:
       
   677 *}
       
   678 
       
   679 ML{*fun apply_prem_tac i preds rules =
       
   680   SUBPROOF_test (fn {params, prems, context, ...} =>
       
   681   let
       
   682     val (params1, params2) = chop (length params - length preds) params
       
   683     val (prems1, prems2) = chop (length prems - length rules) prems
       
   684   in
       
   685     rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1
       
   686     THEN print_tac ""
       
   687     THEN no_tac
       
   688   end) *}
       
   689 
       
   690 text {* and apply it with *}
       
   691 
       
   692 (*<*)
       
   693 lemma fresh_App:
       
   694   shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
       
   695 apply(tactic {* expand_tac @{thms fresh_def} *})
       
   696 (*>*)
       
   697 apply(tactic {* apply_prem_tac 3 [fresh_pred] fresh_rules @{context} *})
       
   698 (*<*)oops(*>*)
       
   699 
       
   700 text {*
       
   701   Since we print out the goal state after the @{ML rtac} we can see
       
   702   the goal state has the two subgoals
       
   703 
       
   704   \begin{isabelle}
       
   705   @{text "1."}~@{prop "a \<noteq> b"}\\
       
   706   @{text "2."}~@{prop "fresh a t"}
       
   707   \end{isabelle}
       
   708 
       
   709   where the first comes from a non-recursive precondition of the rule
       
   710   and the second comes from a recursive precondition. The first kind
       
   711   can be solved immediately by @{text "prems1"}. The second kind
       
   712   needs more work. It can be solved with the other premise in @{text "prems1"},
       
   713   namely
       
   714 
       
   715   @{term [break,display]
       
   716   "\<forall>fresh.
       
   717       (\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
       
   718       (\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
       
   719       (\<forall>a t. fresh a (Lam a t)) \<longrightarrow> 
       
   720       (\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh a t"}
       
   721 
       
   722   but we have to instantiate it appropriately. These instantiations
       
   723   come from @{text "params1"} and @{text "prems2"}. We can determine
       
   724   whether we are in the simple or complicated case by checking whether
       
   725   the topmost connective is @{text "\<forall>"}. The premises in the simple
       
   726   case cannot have such a quantification, since in the first step 
       
   727   of @{ML "expand_tac"} was the ``rulification'' of the lemma. So 
       
   728   we can implement the following function
       
   729 *}
       
   730 
       
   731 ML{*fun prepare_prem params2 prems2 prem =  
       
   732   rtac (case prop_of prem of
   627            _ $ (Const (@{const_name All}, _) $ _) =>
   733            _ $ (Const (@{const_name All}, _) $ _) =>
   628              prem' |> all_elims params2 
   734                  prem |> all_elims params2 
   629                    |> imp_elims prems2
   735                       |> imp_elims prems2
   630          | _ => prem';
   736          | _ => prem) *}
   631    in 
   737 
   632      rtac prem'' 1 
   738 text {* 
   633    end)*}
   739   which either applies the premise outright or if it had an
   634 
   740   outermost universial quantification, instantiates it first with 
   635 text {*
   741   @{text "params1"} and then @{text "prems1"}. The following tactic 
   636 
   742   will therefore prove the lemma.
   637 *}
   743 *}
   638 
   744 
   639 
   745 ML{*fun prove_intro_tac i preds rules =
   640 ML %linenosgray{*fun subproof1 rules preds i = 
   746   SUBPROOF (fn {params, prems, context, ...} =>
   641  SUBPROOF (fn {params, prems, context = ctxt', ...} =>
   747   let
   642    let
   748     val (params1, params2) = chop (length params - length preds) params
   643      val (prems1, prems2) = chop (length prems - length rules) prems
   749     val (prems1, prems2) = chop (length prems - length rules) prems
   644      val (params1, params2) = chop (length params - length preds) params
   750   in
   645    in
   751     rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1
   646      rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 
   752     THEN EVERY1 (map (prepare_prem params2 prems2) prems1)
   647      (* applicateion of the i-ith intro rule *)
   753   end) *}
   648      THEN
   754 
   649      EVERY1 (map (fn prem => subproof2 prem params2 prems2 ctxt') prems1)
   755 text {*
   650    end)*}
   756   We can complete the proof of the introduction rule now as follows:
   651 
   757 *}
   652 text {*
   758 
   653   @{text "params1"} are the variables of the rules; @{text "params2"} is
   759 (*<*)
   654   the variables corresponding to the @{text "preds"}.
   760 lemma fresh_App:
   655 
   761   shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
   656   @{text "prems1"} are the assumption corresponding to the rules;
   762 apply(tactic {* expand_tac @{thms fresh_def} *})
   657   @{text "prems2"} are the assumptions coming from the allIs/impIs
   763 (*>*)
   658 
   764 apply(tactic {* prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1 *})
   659   you instantiate the parameters i-th introduction rule with the parameters
   765 done
   660   that come from the rule; and you apply it to the goal
   766 
   661 
   767 text {* 
   662   this now generates subgoals corresponding to the premisses of this
   768   Unfortunately, not everything is done yet.
   663   intro rule 
   769 *}
       
   770 
       
   771 lemma accpartI:
       
   772   shows "\<And>x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
       
   773 apply(tactic {* expand_tac @{thms accpart_def} *})
       
   774 apply(tactic {* chop_test_tac [acc_pred] acc_rules @{context} *})
       
   775 apply(tactic {* apply_prem_tac 0 [acc_pred] acc_rules @{context} *})
       
   776 
       
   777 txt {*
       
   778   
       
   779   @{subgoals [display]}
       
   780 
       
   781   \begin{isabelle}
       
   782   @{text "Params1 from the rule:"}\\
       
   783   @{text "x"}\\
       
   784   @{text "Params2 from the predicate:"}\\
       
   785   @{text "P"}\\
       
   786   @{text "Prems1 from the rule:"}\\
       
   787   @{text "R ?y x \<Longrightarrow> \<forall>P. (\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x) \<longrightarrow> P ?y"}\\
       
   788   @{text "Prems2 from the predicate:"}\\
       
   789   @{term "\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x"}\\
       
   790   \end{isabelle}
       
   791 
       
   792 *}
       
   793 (*<*)oops(*>*)
       
   794 
       
   795 
       
   796 ML{*fun prepare_prem params2 prems2 ctxt prem =  
       
   797   SUBPROOF (fn {prems, ...} =>
       
   798   let
       
   799     val prem' = prems MRS prem
       
   800   in 
       
   801     rtac (case prop_of prem' of
       
   802            _ $ (Const (@{const_name All}, _) $ _) =>
       
   803                  prem' |> all_elims params2 
       
   804                        |> imp_elims prems2
       
   805          | _ => prem') 1
       
   806   end) ctxt *}
       
   807 
       
   808 ML{*fun prove_intro_tac i preds rules =
       
   809   SUBPROOF (fn {params, prems, context, ...} =>
       
   810   let
       
   811     val (params1, params2) = chop (length params - length preds) params
       
   812     val (prems1, prems2) = chop (length prems - length rules) prems
       
   813   in
       
   814     rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1
       
   815     THEN EVERY1 (map (prepare_prem params2 prems2 context) prems1)
       
   816   end) *}
       
   817 
       
   818 lemma accpartI:
       
   819   shows "\<And>x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
       
   820 apply(tactic {* expand_tac @{thms accpart_def} *})
       
   821 apply(tactic {* prove_intro_tac 0 [acc_pred] acc_rules @{context} 1 *})
       
   822 done
       
   823 
       
   824 
       
   825 
       
   826 text {*
       
   827 
   664 *}
   828 *}
   665 
   829 
   666 ML{*
   830 ML{*
   667 fun intros_tac defs rules preds i ctxt =
   831 fun intros_tac defs rules preds i ctxt =
   668   EVERY1 [ObjectLogic.rulify_tac,
   832   EVERY1 [ObjectLogic.rulify_tac,
   669           K (rewrite_goals_tac defs),
   833           K (rewrite_goals_tac defs),
   670           REPEAT o (resolve_tac [@{thm allI}, @{thm impI}]),
   834           REPEAT o (resolve_tac [@{thm allI}, @{thm impI}]),
   671           subproof1 rules preds i ctxt]*}
   835           prove_intro_tac i preds rules ctxt]*}
   672 
   836 
   673 text {*
   837 text {*
   674   A test case
   838   A test case
   675 *}
   839 *}
   676 
   840 
   690 lemma intro2:
   854 lemma intro2:
   691   shows "\<And>m. even m \<Longrightarrow> odd (Suc m)"
   855   shows "\<And>m. even m \<Longrightarrow> odd (Suc m)"
   692 apply(tactic {* intros_tac_test @{context} 2 *})
   856 apply(tactic {* intros_tac_test @{context} 2 *})
   693 done
   857 done
   694 
   858 
   695 ML{*fun introductions rules preds defs lthy = 
   859 ML{*fun intros rules preds defs lthy = 
   696 let
   860 let
   697   fun prove_intro (i, goal) =
   861   fun prove_intro (i, goal) =
   698     Goal.prove lthy [] [] goal
   862     Goal.prove lthy [] [] goal
   699       (fn {context, ...} => intros_tac defs rules preds i context)
   863       (fn {context, ...} => intros_tac defs rules preds i context)
   700 in
   864 in
   711   val preds = map (fn (p, ty) => Free (Binding.name_of p, ty)) pred_specs'
   875   val preds = map (fn (p, ty) => Free (Binding.name_of p, ty)) pred_specs'
   712 
   876 
   713   val tyss = map (binder_types o fastype_of) preds   
   877   val tyss = map (binder_types o fastype_of) preds   
   714   val (attrs, rules) = split_list rule_specs    
   878   val (attrs, rules) = split_list rule_specs    
   715 
   879 
   716   val (defs, lthy') = definitions rules preds prednames syns tyss lthy      
   880   val (defs, lthy') = defns rules preds prednames syns tyss lthy      
   717   val ind_rules = inductions rules defs preds tyss lthy' 	
   881   val ind_rules = inds rules defs preds tyss lthy' 	
   718   val intro_rules = introductions rules preds defs lthy'
   882   val intro_rules = intros rules preds defs lthy'
   719 
   883 
   720   val mut_name = space_implode "_" (map Binding.name_of prednames)
   884   val mut_name = space_implode "_" (map Binding.name_of prednames)
   721   val case_names = map (Binding.name_of o fst) attrs
   885   val case_names = map (Binding.name_of o fst) attrs
   722 in
   886 in
   723     lthy' 
   887     lthy' 
   766   \item say something about add-inductive-i to return
   930   \item say something about add-inductive-i to return
   767   the rules
   931   the rules
   768   \item say that the induction principle is weaker (weaker than
   932   \item say that the induction principle is weaker (weaker than
   769   what the standard inductive package generates)
   933   what the standard inductive package generates)
   770   \item say that no conformity test is done
   934   \item say that no conformity test is done
       
   935   \item exercise about strong induction principles
       
   936   \item exercise about the test for the intro rules
   771   \end{itemize}
   937   \end{itemize}
   772   
   938   
   773 *}
   939 *}
   774 
   940 
   775 simple_inductive
   941 simple_inductive