ProgTutorial/Package/Ind_Code.thy
changeset 208 0634d42bb69f
parent 194 8cd51a25a7ca
child 209 17b1512f51af
equal deleted inserted replaced
207:d3cd633e8240 208:0634d42bb69f
    11   fresh :: "string \<Rightarrow> trm \<Rightarrow> bool" ("_ \<sharp> _" [100,100] 100)
    11   fresh :: "string \<Rightarrow> trm \<Rightarrow> bool" ("_ \<sharp> _" [100,100] 100)
    12 where
    12 where
    13   "a\<noteq>b \<Longrightarrow> a\<sharp>Var b"
    13   "a\<noteq>b \<Longrightarrow> a\<sharp>Var b"
    14 | "\<lbrakk>a\<sharp>t; a\<sharp>s\<rbrakk> \<Longrightarrow> a\<sharp>App t s"
    14 | "\<lbrakk>a\<sharp>t; a\<sharp>s\<rbrakk> \<Longrightarrow> a\<sharp>App t s"
    15 | "a\<sharp>Lam a t"
    15 | "a\<sharp>Lam a t"
    16 | "\<lbrakk>a\<noteq>b; a\<sharp>t\<rbrakk> \<Longrightarrow> a\<sharp>Lam b t"  
    16 | "\<lbrakk>a\<noteq>b; a\<sharp>t\<rbrakk> \<Longrightarrow> a\<sharp>Lam b t"
    17 
       
    18 
    17 
    19 section {* Code *}
    18 section {* Code *}
    20 
    19 
    21 text {*
    20 text {*
    22   
    21   
    58   
    57   
    59   So we apply the $i$th @{text "orule"}, but we have to show the @{text "As"} (by assumption)
    58   So we apply the $i$th @{text "orule"}, but we have to show the @{text "As"} (by assumption)
    60   and all @{text "(\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>*"}. For the latter we use the assumptions
    59   and all @{text "(\<forall>ys. Bs \<longrightarrow> pred ss)\<^isup>*"}. For the latter we use the assumptions
    61   @{text "(\<forall>ys. Bs \<longrightarrow> (\<forall>preds. orules \<longrightarrow> pred ss))\<^isup>*"} and @{text "orules"}.
    60   @{text "(\<forall>ys. Bs \<longrightarrow> (\<forall>preds. orules \<longrightarrow> pred ss))\<^isup>*"} and @{text "orules"}.
    62 
    61 
    63 *}
    62 
    64 
    63   \begin{center}
    65 
    64   ****************************
    66 text {*
    65   \end{center}
    67   First we have to produce for each predicate the definition of the form
    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 
       
   103 subsection {* Definitions *}
       
   104 
       
   105 text {*
       
   106   First we have to produce for each predicate the definition, whose general form is
    68 
   107 
    69   @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
   108   @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
    70 
   109 
    71   and then ``register'' the definitions with Isabelle. 
   110   and then ``register'' the definition inside a local theory. 
    72   To do the latter, we use the following wrapper for 
   111   To do the latter, we use the following wrapper for 
    73   @{ML LocalTheory.define}. The wrapper takes a predicate name, a syntax
   112   @{ML LocalTheory.define}. The wrapper takes a predicate name, a syntax
    74   annotation and a term representing the right-hand side of the definition.
   113   annotation and a term representing the right-hand side of the definition.
    75 *}
   114 *}
    76 
   115 
   100   warning (str_of_thm_no_vars lthy' def); lthy'
   139   warning (str_of_thm_no_vars lthy' def); lthy'
   101 end *}
   140 end *}
   102 
   141 
   103 text {*
   142 text {*
   104   which makes the definition @{prop "MyTrue \<equiv> True"} and then prints it out. 
   143   which makes the definition @{prop "MyTrue \<equiv> True"} and then prints it out. 
   105   Since we are testing the function inside \isacommand{local\_setup}, i.e.~make
   144   Since we are testing the function inside \isacommand{local\_setup}, i.e., make
   106   changes to the ambient theory, we can query the definition using the usual
   145   changes to the ambient theory, we can query the definition with the usual
   107   command \isacommand{thm}:
   146   command \isacommand{thm}:
   108 
   147 
   109   \begin{isabelle}
   148   \begin{isabelle}
   110   \isacommand{thm}~@{text "MyTrue_def"}\\
   149   \isacommand{thm}~@{text "MyTrue_def"}\\
   111   @{text "> MyTrue \<equiv> True"}
   150   @{text "> MyTrue \<equiv> True"}
   112   \end{isabelle}
   151   \end{isabelle}
   113 
   152 
   114   The next two functions construct the right-hand sides of the definitions, which
   153   The next two functions construct the right-hand sides of the definitions, 
   115   are of the form 
   154   which are terms of the form
   116 
   155 
   117   @{text [display] "\<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
   156   @{text [display] "\<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
   118 
   157 
   119   The variables @{text "zs"} need to be chosen so that they do not occur
   158   When constructing them, the variables @{text "zs"} need to be chosen so that
   120   in the @{text orules} and also be distinct from the @{text "preds"}. 
   159   they do not occur in the @{text orules} and also be distinct from the @{text
       
   160   "preds"}.
       
   161 
   121 
   162 
   122   The first function constructs the term for one particular predicate, say
   163   The first function constructs the term for one particular predicate, say
   123   @{text "pred"}; the number of arguments of this predicate is
   164   @{text "pred"}. The number of arguments of this predicate is
   124   determined by the number of argument types given in @{text "arg_tys"}. 
   165   determined by the number of argument types given in @{text "arg_tys"}. 
   125   The other arguments are all @{text "preds"} and the @{text "orules"}.
   166   The other arguments are all the @{text "preds"} and the @{text "orules"}.
   126 *}
   167 *}
   127 
   168 
   128 ML %linenosgray{*fun defs_aux lthy orules preds (pred, arg_tys) =
   169 ML %linenosgray{*fun defs_aux lthy orules preds (pred, arg_tys) =
   129 let 
   170 let 
   130   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
   171   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
   151   strings.
   192   strings.
   152 
   193 
   153   The unique free variables are applied to the predicate (Line 11) using the
   194   The unique free variables are applied to the predicate (Line 11) using the
   154   function @{ML list_comb}; then the @{text orules} are prefixed (Line 12); in
   195   function @{ML list_comb}; then the @{text orules} are prefixed (Line 12); in
   155   Line 13 we quantify over all predicates; and in line 14 we just abstract
   196   Line 13 we quantify over all predicates; and in line 14 we just abstract
   156   over all the @{text "zs"}, i.e.~the fresh arguments of the
   197   over all the @{text "zs"}, i.e., the fresh arguments of the
   157   predicate. A testcase for this function is
   198   predicate. A testcase for this function is
   158 *}
   199 *}
   159 
   200 
   160 local_setup %gray{* fn lthy =>
   201 local_setup %gray{* fn lthy =>
   161 let
   202 let
   162   val orules = [@{prop "even 0"},
       
   163                 @{prop "\<forall>n::nat. odd n \<longrightarrow> even (Suc n)"},
       
   164                 @{prop "\<forall>n::nat. even n \<longrightarrow> odd (Suc n)"}] 
       
   165   val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}]
       
   166   val pred = @{term "even::nat\<Rightarrow>bool"}
   203   val pred = @{term "even::nat\<Rightarrow>bool"}
   167   val arg_tys = [@{typ "nat"}]
   204   val arg_tys = [@{typ "nat"}]
   168   val def = defs_aux lthy orules preds (pred, arg_tys)
   205   val def = defs_aux lthy eo_orules eo_preds (pred, arg_tys)
   169 in
   206 in
   170   warning (Syntax.string_of_term lthy def); lthy
   207   warning (Syntax.string_of_term lthy def); lthy
   171 end *}
   208 end *}
   172 
   209 
   173 text {*
   210 text {*
   174   It calls @{ML defs_aux} for the definition of @{text "even"} and prints
   211   The testcase  calls @{ML defs_aux} for the predicate @{text "even"} and prints
   175   out the definition. So we obtain as printout 
   212   out the generated definition. So we obtain as printout 
   176 
   213 
   177   @{text [display] 
   214   @{text [display] 
   178 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   215 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   179                          \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
   216                          \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
   180 
   217 
   199   meta-quanti\-fications. In Line 4, we transform these introduction rules into
   236   meta-quanti\-fications. In Line 4, we transform these introduction rules into
   200   the object logic (since definitions cannot be stated with
   237   the object logic (since definitions cannot be stated with
   201   meta-connectives). To do this transformation we have to obtain the theory
   238   meta-connectives). To do this transformation we have to obtain the theory
   202   behind the local theory (Line 3); with this theory we can use the function
   239   behind the local theory (Line 3); with this theory we can use the function
   203   @{ML ObjectLogic.atomize_term} to make the transformation (Line 4). The call
   240   @{ML ObjectLogic.atomize_term} to make the transformation (Line 4). The call
   204   to @{ML defs_aux} in Line 5 produces all left-hand sides of the
   241   to @{ML defs_aux} in Line 5 produces all right-hand sides of the
   205   definitions. The actual definitions are then made in Line 7.  The result
   242   definitions. The actual definitions are then made in Line 7.  The result
   206   of the function is a list of theorems and a local theory. A testcase for 
   243   of the function is a list of theorems and a local theory. A testcase for 
   207   this function is 
   244   this function is 
   208 *}
   245 *}
   209 
   246 
   210 local_setup %gray {* fn lthy =>
   247 local_setup %gray {* fn lthy =>
   211 let
   248 let
   212   val rules = [@{prop "even 0"},
   249   val (defs, lthy') = 
   213                @{prop "\<And>n::nat. odd n \<Longrightarrow> even (Suc n)"},
   250     definitions eo_rules eo_preds eo_prednames eo_syns eo_arg_tyss lthy
   214                @{prop "\<And>n::nat. even n \<Longrightarrow> odd (Suc n)"}] 
   251 in
   215   val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}]
   252   warning (str_of_thms_no_vars lthy' defs); lthy
   216   val prednames = [@{binding "even"}, @{binding "odd"}] 
       
   217   val syns = [NoSyn, NoSyn] 
       
   218   val arg_tyss = [[@{typ "nat"}], [@{typ "nat"}]]
       
   219   val (defs, lthy') = definitions rules preds prednames syns arg_tyss lthy
       
   220 in
       
   221   warning (str_of_thms_no_vars lthy' defs); lthy'
       
   222 end *}
   253 end *}
   223 
   254 
   224 text {*
   255 text {*
   225   where we feed into the functions all parameters corresponding to
   256   where we feed into the functions all parameters corresponding to
   226   the @{text even}-@{text odd} example. The definitions we obtain
   257   the @{text even}-@{text odd} example. The definitions we obtain
   227   are:
   258   are:
   228 
   259 
   229   \begin{isabelle}
   260   \begin{isabelle}
   230   \isacommand{thm}~@{text "even_def odd_def"}\\
       
   231   @{text [break]
   261   @{text [break]
   232 "> even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   262 "> even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   233 >                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z,
   263 >                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z,
   234 > odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   264 > odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
   235 >                                \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
   265 >                                \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
   236   \end{isabelle}
   266   \end{isabelle}
   237 
   267 
       
   268   Note that in the testcase we return the local theory @{text lthy} 
       
   269   (not the modified @{text lthy'}). As a result the test case has no effect
       
   270   on the ambient theory. The reason is that if we make again the
       
   271   definition, we pollute the name space with two versions of @{text "even"} 
       
   272   and @{text "odd"}.
   238 
   273 
   239   This completes the code for making the definitions. Next we deal with
   274   This completes the code for making the definitions. Next we deal with
   240   the induction principles. Recall that the proof of the induction principle 
   275   the induction principles. 
       
   276 *}
       
   277 
       
   278 subsection {* Introduction Rules *}
       
   279 
       
   280 text {*
       
   281   Recall that the proof of the induction principle 
   241   for @{text "even"} was:
   282   for @{text "even"} was:
   242 *}
   283 *}
   243 
   284 
   244 lemma man_ind_principle: 
   285 lemma manual_ind_prin: 
   245 assumes prems: "even n"
   286 assumes prem: "even n"
   246 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   287 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   247 apply(atomize (full))
   288 apply(atomize (full))
   248 apply(cut_tac prems)
   289 apply(cut_tac prems)
   249 apply(unfold even_def)
   290 apply(unfold even_def)
   250 apply(drule spec[where x=P])
   291 apply(drule spec[where x=P])
   264 ML{*fun inst_spec ctrm = 
   305 ML{*fun inst_spec ctrm = 
   265  Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*}
   306  Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*}
   266 
   307 
   267 text {*
   308 text {*
   268   This helper function instantiates the @{text "?x"} in the theorem 
   309   This helper function instantiates the @{text "?x"} in the theorem 
   269   @{thm spec} with a given @{ML_type cterm}. Together with the tactic
   310   @{thm spec} with a given @{ML_type cterm}. We call this helper function
       
   311   in the tactic:
   270 *}
   312 *}
   271 
   313 
   272 ML{*fun inst_spec_tac ctrms = 
   314 ML{*fun inst_spec_tac ctrms = 
   273   EVERY' (map (dtac o inst_spec) ctrms)*}
   315   EVERY' (map (dtac o inst_spec) ctrms)*}
   274 
   316 
   275 text {*
   317 text {*
   276   we can use @{ML inst_spec_tac} in the following proof to instantiate the 
   318   This tactic allows us to instantiate in the following proof the 
   277   three quantifiers in the assumption. 
   319   three quantifiers in the assumption. 
   278 *}
   320 *}
   279 
   321 
   280 lemma 
   322 lemma 
   281   fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   323   fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   293 text {*
   335 text {*
   294   Now the complete tactic for proving the induction principles can 
   336   Now the complete tactic for proving the induction principles can 
   295   be implemented as follows:
   337   be implemented as follows:
   296 *}
   338 *}
   297 
   339 
   298 ML %linenosgray{*fun induction_tac defs prems insts =
   340 ML %linenosgray{*fun induction_tac defs prem insts =
   299   EVERY1 [ObjectLogic.full_atomize_tac,
   341   EVERY1 [ObjectLogic.full_atomize_tac,
   300           cut_facts_tac prems,
   342           cut_facts_tac prem,
   301           K (rewrite_goals_tac defs),
   343           K (rewrite_goals_tac defs),
   302           inst_spec_tac insts,
   344           inst_spec_tac insts,
   303           assume_tac]*}
   345           assume_tac]*}
   304 
   346 
   305 text {*
   347 text {*
   306   We only have to give it the definitions, the premise (like @{text "even n"})
   348   We have to give it as arguments the definitions, the premise 
   307   and the instantiations as arguments. Compare this with the manual proof
   349   (for example @{text "even n"}) and the instantiations. Compare this with the 
   308   given for the lemma @{thm [source] man_ind_principle}: there is almos a
   350   manual proof given for the lemma @{thm [source] manual_ind_prin}: 
   309   one-to-one correspondence between the \isacommand{apply}-script and the
   351   as you can see there is almost a one-to-one correspondence between the \isacommand{apply}-script 
   310   @{ML induction_tac}. A testcase for this tactic is the function
   352   and the @{ML induction_tac}. A testcase for this tactic is the function
   311 *}
   353 *}
   312 
   354 
   313 ML{*fun test_tac prems = 
   355 ML{*fun test_tac prem = 
   314 let
   356 let
   315   val defs = [@{thm even_def}, @{thm odd_def}]
       
   316   val insts = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
   357   val insts = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
   317 in 
   358 in 
   318   induction_tac defs prems insts 
   359   induction_tac eo_defs prem insts 
   319 end*}
   360 end*}
   320 
   361 
   321 text {*
   362 text {*
   322   which indeed proves the induction principle: 
   363   which indeed proves the induction principle: 
   323 *}
   364 *}
   324 
   365 
   325 lemma auto_ind_principle:
   366 lemma automatic_ind_prin:
   326 assumes prems: "even n"
   367 assumes prem: "even z"
   327 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   368 shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
   328 apply(tactic {* test_tac @{thms prems} *})
   369 apply(tactic {* test_tac @{thms prem} *})
   329 done
   370 done
   330 
   371 
   331 text {*
   372 text {*
   332   While the tactic for the induction principle is relatively simple, 
   373   While the tactic for the induction principle is relatively simple, 
   333   it is a bit harder to construct the goals from the introduction 
   374   it is a bit harder to construct the goals from the introduction 
   334   rules the user provides. In general we have to construct for each predicate 
   375   rules the user provides. In general we have to construct for each predicate 
   335   @{text "pred"} a goal of the form
   376   @{text "pred"} a goal of the form
   336 
   377 
   337   @{text [display] 
   378   @{text [display] 
   338   "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P$ ?zs"}
   379   "pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"}
   339 
   380 
   340   where the predicates @{text preds} are replaced in the introduction 
   381   where the predicates @{text preds} are replaced in the introduction 
   341   rules by new distinct variables written @{text "Ps"}.
   382   rules by new distinct variables @{text "?Ps"}.
   342   We also need to generate fresh arguments for the predicate @{text "pred"} in
   383   We also need to generate fresh arguments @{text "?zs"} for the predicate 
   343   the premise and the @{text "?P"} in the conclusion. Note 
   384   @{text "pred"} and the @{text "?P"} in the conclusion. Note 
   344   that the  @{text "?Ps"}  and @{text "?zs"} need to be
   385   that the  @{text "?Ps"}  and @{text "?zs"} need to be
   345   schematic variables that can be instantiated. This corresponds to what the
   386   schematic variables that can be instantiated by the user.
   346   @{thm [source] auto_ind_principle} looks like:
   387 
   347 
   388   We generate these goals in two steps. The first function expects that the
   348   \begin{isabelle}
   389   introduction rules are already appropriately substituted. The argument
   349   \isacommand{thm}~@{thm [source] auto_ind_principle}\\
   390   @{text "srules"} stands for these substituted rules; @{text cnewpreds} are
   350   @{text "> \<lbrakk>even ?n; ?P 0; \<And>m. ?Q m \<Longrightarrow> ?P (Suc m); \<And>m. ?P m \<Longrightarrow> ?Q (Suc m)\<rbrakk> \<Longrightarrow> ?P ?n"}
   391   the certified terms coresponding to the variables @{text "?Ps"}; @{text
   351   \end{isabelle}
   392   "pred"} is the predicate for which we prove the introduction principle;
   352 
   393   @{text "newpred"} is its replacement and @{text "arg_tys"} are the argument
   353   We achieve
   394   types of this predicate.
   354   that in two steps. 
   395 *}
   355 
   396 
   356   The function below expects that the introduction rules are already appropriately
   397 ML %linenosgray{*fun prove_induction lthy defs srules cnewpreds ((pred, newpred), arg_tys) =
   357   substituted. The argument @{text "srules"} stands for these substituted
       
   358    rules; @{text cnewpreds} are the certified terms coresponding
       
   359   to the variables @{text "Ps"}; @{text "pred"} is the predicate for
       
   360   which we prove the introduction principle; @{text "newpred"} is its
       
   361   replacement and @{text "tys"} are the argument types of this predicate.
       
   362 *}
       
   363 
       
   364 ML %linenosgray{*fun prove_induction lthy defs srules cnewpreds ((pred, newpred), arg_tys)  =
       
   365 let
   398 let
   366   val zs = replicate (length arg_tys) "z"
   399   val zs = replicate (length arg_tys) "z"
   367   val (newargnames, lthy') = Variable.variant_fixes zs lthy;
   400   val (newargnames, lthy') = Variable.variant_fixes zs lthy;
   368   val newargs = map Free (newargnames ~~ arg_tys)
   401   val newargs = map Free (newargnames ~~ arg_tys)
   369   
   402   
   378 
   411 
   379 text {* 
   412 text {* 
   380   In Line 3 we produce names @{text "zs"} for each type in the 
   413   In Line 3 we produce names @{text "zs"} for each type in the 
   381   argument type list. Line 4 makes these names unique and declares them as 
   414   argument type list. Line 4 makes these names unique and declares them as 
   382   \emph{free} (but fixed) variables in the local theory @{text "lthy'"}. In 
   415   \emph{free} (but fixed) variables in the local theory @{text "lthy'"}. In 
   383   Line 5 we just construct the terms corresponding to these variables. 
   416   Line 5 we construct the terms corresponding to these variables. 
   384   The term variables are applied to the predicate in Line 7 (this corresponds
   417   The variables are applied to the predicate in Line 7 (this corresponds
   385   to the first premise @{text "pred zs"} of the induction principle). 
   418   to the first premise @{text "pred zs"} of the induction principle). 
   386   In Line 8 and 9, we first construct the term  @{text "P zs"} 
   419   In Line 8 and 9, we first construct the term  @{text "P zs"} 
   387   and then add the (substituded) introduction rules as premises. In case that
   420   and then add the (substituded) introduction rules as premises. In case that
   388   no introduction rules are given, the conclusion of this implication needs
   421   no introduction rules are given, the conclusion of this implication needs
   389   to be wrapped inside a @{term Trueprop}, otherwise the Isabelle's goal
   422   to be wrapped inside a @{term Trueprop}, otherwise the Isabelle's goal
   390   mechanism will fail. 
   423   mechanism will fail. 
   391 
   424 
   392   In Line 11 we set up the goal to be proved; in the next line we call the tactic
   425   In Line 11 we set up the goal to be proved; in the next line we call the
   393   for proving the induction principle. This tactic expects the definitions, the
   426   tactic for proving the induction principle. As mentioned before, this tactic
   394   premise and the (certified) predicates with which the introduction rules
   427   expects the definitions, the premise and the (certified) predicates with
   395   have been substituted. The code in these two lines will return a theorem. 
   428   which the introduction rules have been substituted. The code in these two
   396   However, it is a theorem
   429   lines will return a theorem. However, it is a theorem
   397   proved inside the local theory @{text "lthy'"}, where the variables @{text
   430   proved inside the local theory @{text "lthy'"}, where the variables @{text
   398   "zs"} are fixed, but free. By exporting this theorem from @{text
   431   "zs"} are fixed, but free. By exporting this theorem from @{text
   399   "lthy'"} (which contains the @{text "zs"} as free) to @{text
   432   "lthy'"} (which contains the @{text "zs"} as free) to @{text
   400   "lthy"} (which does not), we obtain the desired schematic variables.
   433   "lthy"} (which does not), we obtain the desired schematic variables @{text "?zs"}.
       
   434   A testcase for this function is
   401 *}
   435 *}
   402 
   436 
   403 local_setup %gray{* fn lthy =>
   437 local_setup %gray{* fn lthy =>
   404 let
   438 let
   405   val defs = [@{thm even_def}, @{thm odd_def}]
       
   406   val srules = [@{prop "P (0::nat)"},
   439   val srules = [@{prop "P (0::nat)"},
   407                 @{prop "\<And>n::nat. Q n \<Longrightarrow> P (Suc n)"},
   440                 @{prop "\<And>n::nat. Q n \<Longrightarrow> P (Suc n)"},
   408                 @{prop "\<And>n::nat. P n \<Longrightarrow> Q (Suc n)"}] 
   441                 @{prop "\<And>n::nat. P n \<Longrightarrow> Q (Suc n)"}] 
   409   val cnewpreds = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
   442   val cnewpreds = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
   410   val pred = @{term "even::nat\<Rightarrow>bool"}
   443   val pred = @{term "even::nat\<Rightarrow>bool"}
   411   val newpred = @{term "P::nat\<Rightarrow>bool"}
   444   val newpred = @{term "P::nat\<Rightarrow>bool"}
   412   val arg_tys = [@{typ "nat"}]
   445   val arg_tys = [@{typ "nat"}]
   413   val intro = 
   446   val intro = 
   414     prove_induction lthy defs srules cnewpreds ((pred, newpred), arg_tys)
   447     prove_induction lthy eo_defs srules cnewpreds ((pred, newpred), arg_tys)
   415 in
   448 in
   416   warning (str_of_thm lthy intro); lthy
   449   warning (str_of_thm lthy intro); lthy
   417 end *} 
   450 end *} 
   418 
   451 
   419 text {*
   452 text {*
   422   @{text [display]
   455   @{text [display]
   423   " \<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"}
   456   " \<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"}
   424 
   457 
   425   Note that the export from @{text lthy'} to @{text lthy} in Line 13 above 
   458   Note that the export from @{text lthy'} to @{text lthy} in Line 13 above 
   426   has turned the free, but fixed, @{text "z"} into a schematic 
   459   has turned the free, but fixed, @{text "z"} into a schematic 
   427   variable @{text "?z"}.
   460   variable @{text "?z"}. The @{text "P"} and @{text "Q"} are not yet
       
   461   schematic. 
   428 
   462 
   429   We still have to produce the new predicates with which the introduction
   463   We still have to produce the new predicates with which the introduction
   430   rules are substituted and iterate @{ML prove_induction} over all
   464   rules are substituted and iterate @{ML prove_induction} over all
   431   predicates. This is what the next function does. 
   465   predicates. This is what the second function does: 
   432 *}
   466 *}
   433 
   467 
   434 ML %linenosgray{*fun inductions rules defs preds arg_tyss lthy  =
   468 ML %linenosgray{*fun inductions rules defs preds arg_tyss lthy  =
   435 let
   469 let
   436   val Ps = replicate (length preds) "P"
   470   val Ps = replicate (length preds) "P"
   448         (preds ~~ newpreds ~~ arg_tyss)
   482         (preds ~~ newpreds ~~ arg_tyss)
   449           |> ProofContext.export lthy' lthy
   483           |> ProofContext.export lthy' lthy
   450 end*}
   484 end*}
   451 
   485 
   452 text {*
   486 text {*
   453   In Line 3 we generate a string @{text [quotes] "P"} for each predicate. 
   487   In Line 3, we generate a string @{text [quotes] "P"} for each predicate. 
   454   In Line 4, we use the same trick as in the previous function, that is making the 
   488   In Line 4, we use the same trick as in the previous function, that is making the 
   455   @{text "Ps"} fresh and declaring them as fixed, but free, in
   489   @{text "Ps"} fresh and declaring them as fixed, but free, in
   456   the new local theory @{text "lthy'"}. From the local theory we extract
   490   the new local theory @{text "lthy'"}. From the local theory we extract
   457   the ambient theory in Line 6. We need this theory in order to certify 
   491   the ambient theory in Line 6. We need this theory in order to certify 
   458   the new predicates. In Line 8 we calculate the types of these new predicates
   492   the new predicates. In Line 8, we construct the types of these new predicates
   459   using the given argument types. Next we turn them into terms and subsequently
   493   using the given argument types. Next we turn them into terms and subsequently
   460   certify them (Line 9 and 10). We can now produce the substituted introduction rules 
   494   certify them (Line 9 and 10). We can now produce the substituted introduction rules 
   461   (Line 11) using the function @{ML subst_free}. Line 14 and 15 just iterate 
   495   (Line 11) using the function @{ML subst_free}. Line 14 and 15 just iterate 
   462   the proofs for all predicates.
   496   the proofs for all predicates.
   463   From this we obtain a list of theorems. Finally we need to export the 
   497   From this we obtain a list of theorems. Finally we need to export the 
   464   fixed variables @{text "Ps"} to obtain the schematic variables 
   498   fixed variables @{text "Ps"} to obtain the schematic variables @{text "?Ps"} 
   465   (Line 16).
   499   (Line 16).
   466 
   500 
   467   A testcase for this function is
   501   A testcase for this function is
   468 *}
   502 *}
   469 
   503 
   470 local_setup %gray {* fn lthy =>
   504 local_setup %gray {* fn lthy =>
   471 let 
   505 let 
   472   val rules = [@{prop "even (0::nat)"},
   506   val ind_thms = inductions eo_rules eo_defs eo_preds eo_arg_tyss lthy
   473                @{prop "\<And>n::nat. odd n \<Longrightarrow> even (Suc n)"},
       
   474                @{prop "\<And>n::nat. even n \<Longrightarrow> odd (Suc n)"}] 
       
   475   val defs = [@{thm even_def}, @{thm odd_def}]
       
   476   val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}]
       
   477   val tyss = [[@{typ "nat"}], [@{typ "nat"}]]
       
   478   val ind_thms = inductions rules defs preds tyss lthy
       
   479 in
   507 in
   480   warning (str_of_thms lthy ind_thms); lthy
   508   warning (str_of_thms lthy ind_thms); lthy
   481 end *}
   509 end *}
   482 
   510 
   483 
   511 
   488 "> even ?z \<Longrightarrow> ?P1 0 \<Longrightarrow> 
   516 "> even ?z \<Longrightarrow> ?P1 0 \<Longrightarrow> 
   489 > (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?P1 ?z,
   517 > (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?P1 ?z,
   490 > odd ?z \<Longrightarrow> ?P1 0 
   518 > odd ?z \<Longrightarrow> ?P1 0 
   491 > \<Longrightarrow> (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?Pa1 ?z"}
   519 > \<Longrightarrow> (\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?Pa1 ?z"}
   492 
   520 
   493 
   521   Note that now both, the @{text "?Ps"} and the @{text "?zs"}, are schematic
   494   Note that now both, the @{text "Ps"} and the @{text "zs"}, are schematic
       
   495   variables. The numbers have been introduced by the pretty-printer and are 
   522   variables. The numbers have been introduced by the pretty-printer and are 
   496   not significant.
   523   not significant.
   497 
   524 
   498   This completes the code for the induction principles.  Finally we can prove the 
   525   This completes the code for the induction principles.  
   499   introduction rules. Their proofs are quite a bit more involved. To ease them 
   526 *}
   500   somewhat we  use the following two helper function.
   527 
       
   528 subsection {* Introduction Rules *}
       
   529 
       
   530 text {*
       
   531   Finally we can prove the introduction rules. Their proofs are quite a bit
       
   532   more involved. To ease these proofs somewhat we use the following two helper
       
   533   functions.
       
   534 
   501 *}
   535 *}
   502 
   536 
   503 ML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct)
   537 ML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct)
   504 val imp_elims = fold (fn th => fn th' => [th', th] MRS @{thm mp})*}
   538 val imp_elims = fold (fn th => fn th' => [th', th] MRS @{thm mp})*}
   505 
   539 
   506 text {* 
   540 text {* 
   507   To see what they do, let us suppose whe have the follwoing three
   541   To see what these functions do, let us suppose whe have the following three
   508   theorems. 
   542   theorems. 
   509 *}
   543 *}
   510 
   544 
   511 lemma all_elims_test:
   545 lemma all_elims_test:
   512   fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   546   fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
   533   warning (str_of_thm_no_vars @{context} new_thm)
   567   warning (str_of_thm_no_vars @{context} new_thm)
   534 end"
   568 end"
   535   "P a b c"}
   569   "P a b c"}
   536 
   570 
   537   Similarly, the function @{ML imp_elims} eliminates preconditions from implications. 
   571   Similarly, the function @{ML imp_elims} eliminates preconditions from implications. 
   538   For example 
   572   For example: 
   539 
   573 
   540   @{ML_response_fake [display, gray]
   574   @{ML_response_fake [display, gray]
   541 "warning (str_of_thm_no_vars @{context} 
   575 "warning (str_of_thm_no_vars @{context} 
   542             (imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}))"
   576             (imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}))"
   543   "C"}
   577   "C"}
   546 ML {* prems_of *}
   580 ML {* prems_of *}
   547 ML {* Logic.strip_params *}
   581 ML {* Logic.strip_params *}
   548 ML {* Logic.strip_assums_hyp *}
   582 ML {* Logic.strip_assums_hyp *}
   549 
   583 
   550 ML {*
   584 ML {*
   551 fun chop_print_tac m n ctxt thm =
   585 fun chop_print (params1, params2) (prems1, prems2) ctxt =
   552 let
   586 let
   553   val [trm] = prems_of thm
       
   554   val params = map fst (Logic.strip_params trm)
       
   555   val prems  = Logic.strip_assums_hyp trm
       
   556   val (prems1, prems2) = chop (length prems - m) prems;
       
   557   val (params1, params2) = chop (length params - n) params;
       
   558   val _ = warning (Syntax.string_of_term ctxt trm)
       
   559   val _ = warning (commas params)
       
   560   val _ = warning (commas (map (Syntax.string_of_term ctxt) prems))
       
   561   val _ = warning ((commas params1) ^ " | " ^ (commas params2))
   587   val _ = warning ((commas params1) ^ " | " ^ (commas params2))
   562   val _ = warning ((commas (map (Syntax.string_of_term ctxt) prems1)) ^ " | " ^
   588   val _ = warning ((commas (map (Syntax.string_of_term ctxt) prems1)) ^ " | " ^
   563                    (commas (map (Syntax.string_of_term ctxt) prems2)))
   589                    (commas (map (Syntax.string_of_term ctxt) prems2)))
   564 in
   590 in
   565    Seq.single thm
   591    ()
   566 end
   592 end
   567 *}
   593 *}
   568 
   594 
   569 ML {* METAHYPS *}
   595 
   570 
       
   571 ML {*
       
   572 fun chop_print_tac2 ctxt prems =
       
   573 let
       
   574   val _ = warning (commas (map (str_of_thm_no_vars ctxt) prems))
       
   575 in
       
   576    all_tac
       
   577 end
       
   578 *}
       
   579 
   596 
   580 lemma intro1:
   597 lemma intro1:
   581   shows "\<And>m. odd m \<Longrightarrow> even (Suc m)"
   598   shows "\<And>m. odd m \<Longrightarrow> even (Suc m)"
   582 apply(tactic {* ObjectLogic.rulify_tac 1 *})
   599 apply(tactic {* ObjectLogic.rulify_tac 1 *})
   583 apply(tactic {* rewrite_goals_tac [@{thm even_def}, @{thm odd_def}] *})
   600 apply(tactic {* rewrite_goals_tac [@{thm even_def}, @{thm odd_def}] *})
   584 apply(tactic {* REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1) *})
   601 apply(tactic {* REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1) *})
   585 apply(tactic {* chop_print_tac 3 2 @{context} *})
       
   586 oops
   602 oops
   587 
   603 
   588 ML {*
   604 ML {* fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac *}
   589 fun SUBPROOF_test tac ctxt =
       
   590   SUBPROOF (fn {params, prems, context,...} =>
       
   591     let
       
   592       val thy = ProofContext.theory_of context
       
   593     in 
       
   594       tac (params, prems, context) 
       
   595       THEN  Method.insert_tac prems 1
       
   596       THEN  print_tac "SUBPROOF Test"
       
   597       THEN  SkipProof.cheat_tac thy
       
   598     end) ctxt 1
       
   599 *}
       
   600 
       
   601 
       
   602 
   605 
   603 
   606 
   604 lemma fresh_App:
   607 lemma fresh_App:
   605   shows "\<And>a t s. \<lbrakk>a\<sharp>t; a\<sharp>s\<rbrakk> \<Longrightarrow> a\<sharp>App t s"
   608   shows "\<And>a t s. \<lbrakk>a\<sharp>t; a\<sharp>s\<rbrakk> \<Longrightarrow> a\<sharp>App t s"
   606 apply(tactic {* ObjectLogic.rulify_tac 1 *})
   609 apply(tactic {* ObjectLogic.rulify_tac 1 *})
   607 apply(tactic {* rewrite_goals_tac [@{thm fresh_def}] *})
   610 apply(tactic {* rewrite_goals_tac [@{thm fresh_def}] *})
   608 apply(tactic {* REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1) *})
   611 apply(tactic {* REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1) *})
       
   612 apply(tactic {* print_tac "" *})
       
   613 apply(tactic {* SUBPROOF_test (fn {params, prems, ...} =>
       
   614    let
       
   615      val (prems1, prems2) = chop (length prems - length fresh_rules) prems
       
   616      val (params1, params2) = chop (length params - length fresh_preds) params
       
   617    in
       
   618      no_tac
       
   619    end) @{context} *})
   609 oops
   620 oops
   610 (*
   621 
   611 apply(tactic {* SUBPROOF_test 
       
   612   (fn (params, prems, ctxt) =>
       
   613    let 
       
   614      val (prems1, prems2) = chop (length prems - 4) prems;
       
   615      val (params1, params2) = chop (length params - 1) params;
       
   616    in
       
   617      rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 2))) 1
       
   618    end) @{context} *})
       
   619 *)
       
   620 
   622 
   621 ML{*fun subproof2 prem params2 prems2 =  
   623 ML{*fun subproof2 prem params2 prems2 =  
   622  SUBPROOF (fn {prems, ...} =>
   624  SUBPROOF (fn {prems, ...} =>
   623    let
   625    let
   624      val prem' = prems MRS prem;
   626      val prem' = prems MRS prem;
   638 
   640 
   639 
   641 
   640 ML %linenosgray{*fun subproof1 rules preds i = 
   642 ML %linenosgray{*fun subproof1 rules preds i = 
   641  SUBPROOF (fn {params, prems, context = ctxt', ...} =>
   643  SUBPROOF (fn {params, prems, context = ctxt', ...} =>
   642    let
   644    let
   643      val (prems1, prems2) = chop (length prems - length rules) prems;
   645      val (prems1, prems2) = chop (length prems - length rules) prems
   644      val (params1, params2) = chop (length params - length preds) params;
   646      val (params1, params2) = chop (length params - length preds) params
   645    in
   647    in
   646      rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 
   648      rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1 
   647      (* applicateion of the i-ith intro rule *)
   649      (* applicateion of the i-ith intro rule *)
   648      THEN
   650      THEN
   649      EVERY1 (map (fn prem => subproof2 prem params2 prems2 ctxt') prems1)
   651      EVERY1 (map (fn prem => subproof2 prem params2 prems2 ctxt') prems1)
   673 text {*
   675 text {*
   674   A test case
   676   A test case
   675 *}
   677 *}
   676 
   678 
   677 ML{*fun intros_tac_test ctxt i =
   679 ML{*fun intros_tac_test ctxt i =
   678 let
   680   intros_tac eo_defs eo_rules eo_preds i ctxt *}
   679   val rules = [@{prop "even (0::nat)"},
       
   680                @{prop "\<And>n::nat. odd n \<Longrightarrow> even (Suc n)"},
       
   681                @{prop "\<And>n::nat. even n \<Longrightarrow> odd (Suc n)"}] 
       
   682   val defs = [@{thm even_def}, @{thm odd_def}]
       
   683   val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}]
       
   684 in
       
   685   intros_tac defs rules preds i ctxt
       
   686 end*}
       
   687 
   681 
   688 lemma intro0:
   682 lemma intro0:
   689   shows "even 0"
   683   shows "even 0"
   690 apply(tactic {* intros_tac_test @{context} 0 *})
   684 apply(tactic {* intros_tac_test @{context} 0 *})
   691 done
   685 done