CookBook/Package/Ind_Code.thy
changeset 179 75381fa516cd
parent 178 fb8f22dd8ad0
child 180 9c25418db6f0
equal deleted inserted replaced
178:fb8f22dd8ad0 179:75381fa516cd
    40 text {*
    40 text {*
    41   First we have to produce for each predicate its definitions of the form
    41   First we have to produce for each predicate its definitions of the form
    42 
    42 
    43   @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
    43   @{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
    44 
    44 
    45   We use the following wrapper function to actually make the definition via
    45   We use the following wrapper function to make the definition via
    46   @{ML LocalTheory.define}. The function takes a predicate name, a syntax
    46   @{ML LocalTheory.define}. The function takes a predicate name, a syntax
    47   annotation and a term representing the right-hand side of the definition.
    47   annotation and a term representing the right-hand side of the definition.
    48 *}
    48 *}
    49 
    49 
    50 ML %linenosgray{*fun make_defs ((predname, syn), trm) lthy =
    50 ML %linenosgray{*fun make_defs ((predname, syn), trm) lthy =
    54 in 
    54 in 
    55   (thm, lthy') 
    55   (thm, lthy') 
    56 end*}
    56 end*}
    57 
    57 
    58 text {*
    58 text {*
    59   Returns the definition (as theorem) and the local theory in which this definition has 
    59   It returns the definition (as theorem) and the local theory in which this definition has 
    60   been made. The @{ML internalK in Thm} in Line 4 is just a flag attached to the 
    60   been made. In Line 4 @{ML internalK in Thm} is just a flag attached to the 
    61   theorem (others flags are @{ML definitionK in Thm} or @{ML axiomK in Thm}). 
    61   theorem (others possibilities are @{ML definitionK in Thm} or @{ML axiomK in Thm}). 
    62   These flags just classify theorems and have no significant meaning, except 
    62   These flags just classify theorems and have no significant meaning, except 
    63   for tools such as finding theorems in the theorem database. We also
    63   for tools such as finding theorems in the theorem database. We also
    64   use @{ML empty_binding in Attrib} in Line 3, since the definition does not need any
    64   use @{ML empty_binding in Attrib} in Line 3, since the definition does 
    65   theorem attributes. 
    65   not need any theorem attributes. Note the definition has not yet been 
       
    66   stored in the theorem database. So at the moment we can only refer to it
       
    67   via the return value. A testcase for this functions is
    66 *}
    68 *}
    67 
    69 
    68 local_setup %gray {* fn lthy =>
    70 local_setup %gray {* fn lthy =>
    69 let
    71 let
    70   val arg =  ((Binding.name "MyTrue", NoSyn), @{term True})
    72   val arg =  ((Binding.name "MyTrue", NoSyn), @{term True})
    71   val (def, lthy') = make_defs arg lthy 
    73   val (def, lthy') = make_defs arg lthy 
    72   val _ = warning (str_of_thm lthy' def)
    74 in
    73 in
    75   warning (str_of_thm lthy' def); lthy'
    74   lthy'
       
    75 end *}
    76 end *}
    76 
    77 
    77 text {*
    78 text {*
    78   Prints out the theorem @{prop "MyTrue \<equiv> True"}.
    79   which prints out the theorem @{prop "MyTrue \<equiv> True"}. Since we are
    79 *}
    80   testing the function inside \isacommand{local\_setup} we have also
    80 
    81   access to theorem associated with this definition.
    81 text {*
    82 
    82   Constructs the term for the definition: the main arguments are a predicate
    83   \begin{isabelle}
    83   and the types of the arguments, it also expects orules which are the 
    84   \isacommand{thm}~@{text "MyTrue_def"}\\
    84   intro rules in the object logic; preds which are all predicates. returns the
    85   @{text "> MyTrue \<equiv> True"}
    85   term.
    86   \end{isabelle}
       
    87 
       
    88   The next function constructs the term for the definition, namely 
       
    89 
       
    90   @{text [display] "\<lambda>\<^raw:$zs$>. \<forall>preds. orules \<longrightarrow> pred \<^raw:$zs$>"}
       
    91 
       
    92   The variables @{text "\<^raw:$zs$>"} need to be chosen so to not occur
       
    93   in the @{text orules} and also be distinct from @{text "pred"}. The function
       
    94   constructs the term for one particular predicate @{text "pred"}; the number
       
    95   of @{text "\<^raw:$zs$>"} is determined by the nunber of types. 
    86 *}
    96 *}
    87 
    97 
    88 ML %linenosgray{*fun defs_aux lthy orules preds (pred, arg_tys) =
    98 ML %linenosgray{*fun defs_aux lthy orules preds (pred, arg_tys) =
    89 let 
    99 let 
    90   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
   100   fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
    91 
   101 
    92   val fresh_args = 
   102   val fresh_args = 
    93         arg_tys 
   103         arg_tys 
    94         |> map (pair "z")
   104         |> map (pair "z")
    95         |> Variable.variant_frees lthy orules 
   105         |> Variable.variant_frees lthy (preds @ orules) 
    96         |> map Free
   106         |> map Free
    97 in
   107 in
    98   list_comb (pred, fresh_args)
   108   list_comb (pred, fresh_args)
    99   |> fold_rev (curry HOLogic.mk_imp) orules
   109   |> fold_rev (curry HOLogic.mk_imp) orules
   100   |> fold_rev mk_all preds
   110   |> fold_rev mk_all preds
   101   |> fold_rev lambda fresh_args 
   111   |> fold_rev lambda fresh_args 
   102 end*}
   112 end*}
   103 
   113 
   104 text {*
   114 text {*
   105   The lines 5-9 produce fresh arguments with which the predicate can be applied.
   115   The code in Lines 5 to 9 produce the fresh @{text "\<^raw:$zs$>"} with which the 
   106   For this it pairs every type with a string @{text [quotes] "z"} (Line 7); then 
   116   predicate is applied. For this it pairs every type with a string @{text [quotes] "z"} 
   107   generates variants for all these strings (names) so that they are unique w.r.t.~to 
   117   (Line 7); then generates variants for all these strings (names) so that they are 
   108   the intro rules; in Line 9 it generates the corresponding variable terms for these 
   118   unique w.r.t.~to the orules and predicates; in Line 9 it generates the corresponding 
   109   unique names.
   119   variable terms for the unique names.
   110 
   120 
   111   The unique free variables are applied to the predicate (Line 11); then
   121   The unique free variables are applied to the predicate (Line 11); then
   112   the intro rules are attached as preconditions (Line 12); in Line 13 we
   122   the @{text orules} are prefixed (Line 12); in Line 13 we
   113   quantify over all predicates; and in line 14 we just abstract over all
   123   quantify over all predicates; and in line 14 we just abstract over all
   114   the (fresh) arguments of the predicate.
   124   the (fresh)  @{text "\<^raw:$zs$>"}, i.e.~the arguments of the predicate.
   115 *}
   125 
   116 
   126   A testcase for this function is
   117 
   127 *}
   118 local_setup {*
   128 
   119 fn lthy =>
   129 local_setup %gray{* fn lthy =>
   120 let
   130 let
   121   val orules = [@{prop "even 0"},
   131   val orules = [@{prop "even 0"},
   122                 @{prop "\<forall>n::nat. odd n \<longrightarrow> even (Suc n)"},
   132                 @{prop "\<forall>n::nat. odd n \<longrightarrow> even (Suc n)"},
   123                 @{prop "\<forall>n::nat. even n \<longrightarrow> odd (Suc n)"}] 
   133                 @{prop "\<forall>n::nat. even n \<longrightarrow> odd (Suc n)"}] 
   124   val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}]
   134   val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}]
   125   val pred = @{term "even::nat\<Rightarrow>bool"}
   135   val pred = @{term "even::nat\<Rightarrow>bool"}
   126   val arg_tys = [@{typ "nat"}]
   136   val arg_tys = [@{typ "nat"}]
   127   val def = defs_aux lthy orules preds (pred, arg_tys)
   137   val def = defs_aux lthy orules preds (pred, arg_tys)
   128 in
   138 in
   129   warning (Syntax.string_of_term lthy def); lthy
   139   warning (Syntax.string_of_term lthy def); lthy
   130 end*}
   140 end *}
   131 
   141 
   132 text {*
   142 text {*
   133   The arguments of the main function for the definitions are 
   143   It constructs the term for the predicate @{term "even"}. So we obtain as printout
   134   the intro rules; the predicates and their names, their syntax 
   144   the term
   135   annotations and the argument types of each predicate. It  
   145 
   136   returns a theorem list (the definitions) and a local
   146   @{text [display] 
   137   theory where the definitions are made
   147 "\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
       
   148                          \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
       
   149 
       
   150   The main function for the definitions now has to just iterate
       
   151   the function @{ML defs_aux} over all predicates. THis is what the
       
   152   next function does. 
   138 *}
   153 *}
   139 
   154 
   140 ML %linenosgray{*fun definitions rules preds prednames syns arg_typss lthy =
   155 ML %linenosgray{*fun definitions rules preds prednames syns arg_typss lthy =
   141 let
   156 let
   142   val thy = ProofContext.theory_of lthy
   157   val thy = ProofContext.theory_of lthy
   145 in
   160 in
   146   fold_map make_defs (prednames ~~ syns ~~ defs) lthy
   161   fold_map make_defs (prednames ~~ syns ~~ defs) lthy
   147 end*}
   162 end*}
   148 
   163 
   149 text {*
   164 text {*
       
   165   The argument @{text "preds"} is the list of predicates as @{ML_type term}s;
       
   166   the argument @{text "prednames"} is the list of names of the predicates;
       
   167   @{text "arg_tyss"} is the list of argument-type-lists. 
       
   168   
   150   In line 4 we generate the intro rules in the object logic; for this we have to 
   169   In line 4 we generate the intro rules in the object logic; for this we have to 
   151   obtain the theory behind the local theory (Line 3); with this we can
   170   obtain the theory behind the local theory (Line 3); with this we can
   152   call @{ML defs_aux} to generate the terms for the left-hand sides.
   171   call @{ML defs_aux} to generate the terms for the left-hand sides.
   153   The actual definitions are made in Line 7.  
   172   The actual definitions are made in Line 7.
   154 *}
   173 
   155 
   174   A testcase for this function is 
   156 local_setup {*
   175 *}
   157 fn lthy =>
   176 
       
   177 local_setup %gray {* fn lthy =>
   158 let
   178 let
   159   val rules = [@{prop "even 0"},
   179   val rules = [@{prop "even 0"},
   160                 @{prop "\<And>n::nat. odd n \<Longrightarrow> even (Suc n)"},
   180                @{prop "\<And>n::nat. odd n \<Longrightarrow> even (Suc n)"},
   161                 @{prop "\<And>n::nat. even n \<Longrightarrow> odd (Suc n)"}] 
   181                @{prop "\<And>n::nat. even n \<Longrightarrow> odd (Suc n)"}] 
   162   val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}]
   182   val preds = [@{term "even::nat\<Rightarrow>bool"}, @{term "odd::nat\<Rightarrow>bool"}]
   163   val prednames = [Binding.name "even", Binding.name "odd"] 
   183   val prednames = [Binding.name "even", Binding.name "odd"] 
   164   val syns = [NoSyn, NoSyn] 
   184   val syns = [NoSyn, NoSyn] 
   165   val arg_tyss = [[@{typ "nat"}], [@{typ "nat"}]]
   185   val arg_tyss = [[@{typ "nat"}], [@{typ "nat"}]]
   166   val (defs, lthy') = definitions rules preds prednames syns arg_tyss lthy
   186   val (defs, lthy') = definitions rules preds prednames syns arg_tyss lthy
   167 in
   187 in
   168   warning (str_of_thms lthy' defs); lthy
   188   warning (str_of_thms lthy' defs); lthy
   169 end*}
   189 end *}
   170 
   190 
   171 
   191 text {*
   172 subsection {* Induction Principles *}
   192 
   173 
   193   It prints out the two definitions
   174 text {* Recall the proof for the induction principle for @{term "even"}: *}
   194 
       
   195   @{text [display] 
       
   196 "even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
       
   197                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z, 
       
   198  odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n)) 
       
   199                                 \<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
       
   200 
       
   201   This completes the code concerning the definitions. Next comes the code for
       
   202   the induction principles. 
       
   203 
       
   204   Recall the proof for the induction principle for @{term "even"}: 
       
   205 *}
   175 
   206 
   176 lemma 
   207 lemma 
   177   assumes prems: "even n"
   208   assumes prems: "even n"
   178   shows "P 0 \<Longrightarrow> 
   209   shows "P 0 \<Longrightarrow> 
   179              (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   210              (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   183 apply(drule spec[where x=P])
   214 apply(drule spec[where x=P])
   184 apply(drule spec[where x=Q])
   215 apply(drule spec[where x=Q])
   185 apply(assumption)
   216 apply(assumption)
   186 done
   217 done
   187 
   218 
   188 
   219 text {* 
   189 text {* We need to be able to instantiate universal quantifiers. *}
   220   To automate this proof we need to be able to instantiate universal 
   190 
   221   quantifiers. For this we use the following helper function. It
   191 ML{*fun inst_spec ct = 
   222   instantiates the @{text "?x"} in @{thm spec} with a @{ML_type cterm}.
   192  Drule.instantiate' [SOME (ctyp_of_term ct)] [NONE, SOME ct] @{thm spec}*}
   223 *}
   193 
   224 
   194 text {*
   225 ML{*fun inst_spec ctrm = 
   195   Instantiates the @{text "?x"} in @{thm spec} with a @{ML_type cterm}.
   226  Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*}
   196 *}
   227 
   197 
   228 text {*
   198 text {*
   229   For example we can use it to instantiate an assumption:
   199   Instantiates universal qantifications in the premises
   230 *}
   200 *}
   231 
   201 
   232 lemma "\<forall>x1 x2 x3. P (x1::nat) (x2::nat) (x3::nat) \<Longrightarrow> True"
   202 lemma "\<forall>x\<^isub>1 x\<^isub>2 x\<^isub>3. P (x\<^isub>1::nat) (x\<^isub>2::nat) (x\<^isub>3::nat) \<Longrightarrow> True"
       
   203 apply (tactic {* 
   233 apply (tactic {* 
   204   let 
   234   let 
   205     val ctrms = [@{cterm "y\<^isub>1::nat"},@{cterm "y\<^isub>2::nat"},@{cterm "y\<^isub>3::nat"}]
   235     val ctrms = [@{cterm "y1::nat"},@{cterm "y2::nat"},@{cterm "y3::nat"}]
   206   in 
   236   in 
   207     EVERY1 (map (dtac o inst_spec) ctrms)
   237     EVERY1 (map (dtac o inst_spec) ctrms)
   208   end *})
   238   end *})
   209 txt {* \begin{minipage}{\textwidth}
   239 txt {* 
   210        @{subgoals} 
   240   where it produces the goal state
   211        \end{minipage}*}
   241 
       
   242   \begin{minipage}{\textwidth}
       
   243   @{subgoals} 
       
   244   \end{minipage}*}
   212 (*<*)oops(*>*)
   245 (*<*)oops(*>*)
   213 
   246 
   214 text {*
   247 text {*
   215   Now the tactic for proving the induction rules: 
   248   Now the tactic for proving the induction rules can be implemented 
       
   249   as follows
   216 *}
   250 *}
   217 
   251 
   218 ML{*fun induction_tac defs prems insts =
   252 ML{*fun induction_tac defs prems insts =
   219   EVERY1 [ObjectLogic.full_atomize_tac,
   253   EVERY1 [ObjectLogic.full_atomize_tac,
   220           cut_facts_tac prems,
   254           cut_facts_tac prems,
   221           K (rewrite_goals_tac defs),
   255           K (rewrite_goals_tac defs),
   222           EVERY' (map (dtac o inst_spec) insts),
   256           EVERY' (map (dtac o inst_spec) insts),
   223           assume_tac]*}
   257           assume_tac]*}
       
   258 
       
   259 text {*
       
   260   We only have to give it as arguments the premises and the instantiations.
       
   261   A testcase for the tactic is
       
   262 *}
   224 
   263 
   225 lemma 
   264 lemma 
   226   assumes prems: "even n"
   265   assumes prems: "even n"
   227   shows "P 0 \<Longrightarrow> 
   266   shows "P 0 \<Longrightarrow> 
   228            (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   267            (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
   235   end *})
   274   end *})
   236 done
   275 done
   237 
   276 
   238 
   277 
   239 text {*
   278 text {*
   240   While the generic proof is relatively simple, it is a bit harder to
   279   which indeed proves the lemma. 
   241   set up the goals for the induction principles. 
   280 
   242 *}
   281   While the generic proof for the induction principle is relatively simple, 
   243 
   282   it is a bit harder to set up the goals just from the given introduction 
   244 ML {*
   283   rules. For this we have to construct
   245 fun prove_induction lthy2 defs rules cnewpreds ((pred, newpred), tys)  =
   284 
       
   285   @{text [display] 
       
   286   "\<And>\<^raw:$zs$>. pred \<^raw:$zs$> \<Longrightarrow> rules[preds := \<^raw:$Ps$>] \<Longrightarrow> \<^raw:$P$> \<^raw:$zs$>"}
       
   287 
       
   288   where the given predicates are replaced by new ones written
       
   289   as @{text "\<^raw:$Ps$>"}, and also generate new variables 
       
   290   @{text "\<^raw:$zs$>"}.
       
   291 *}
       
   292 
       
   293 ML %linenosgray{* fun prove_induction lthy defs rules cnewpreds ((pred, newpred), tys)  =
   246 let
   294 let
   247   val zs = replicate (length tys) "z"
   295   val zs = replicate (length tys) "z"
   248   val (newargnames, lthy3) = Variable.variant_fixes zs lthy2;
   296   val (newargnames, lthy') = Variable.variant_fixes zs lthy;
   249   val newargs = map Free (newargnames ~~ tys)
   297   val newargs = map Free (newargnames ~~ tys)
   250   
   298   
   251   val prem = HOLogic.mk_Trueprop (list_comb (pred, newargs))
   299   val prem = HOLogic.mk_Trueprop (list_comb (pred, newargs))
   252   val goal = Logic.list_implies 
   300   val goal = Logic.list_implies 
   253          (rules, HOLogic.mk_Trueprop (list_comb (newpred, newargs)))
   301          (rules, HOLogic.mk_Trueprop (list_comb (newpred, newargs)))
   254 in
   302 in
   255   Goal.prove lthy3 [] [prem] goal
   303   Goal.prove lthy' [] [prem] goal
   256   (fn {prems, ...} => induction_tac defs prems cnewpreds)
   304   (fn {prems, ...} => induction_tac defs prems cnewpreds)
   257   |> singleton (ProofContext.export lthy3 lthy2)
   305   |> singleton (ProofContext.export lthy' lthy)
   258 end 
   306 end *}
   259 *}
   307 
       
   308 text {* *}
   260 
   309 
   261 ML %linenosgray{*fun inductions rules defs preds tyss lthy1  =
   310 ML %linenosgray{*fun inductions rules defs preds tyss lthy1  =
   262 let
   311 let
   263   val Ps = replicate (length preds) "P"
   312   val Ps = replicate (length preds) "P"
   264   val (newprednames, lthy2) = Variable.variant_fixes Ps lthy1
   313   val (newprednames, lthy2) = Variable.variant_fixes Ps lthy1
   271   val rules' = map (subst_free (preds ~~ newpreds)) rules
   320   val rules' = map (subst_free (preds ~~ newpreds)) rules
   272 
   321 
   273 in
   322 in
   274   map (prove_induction lthy2 defs rules' cnewpreds) 
   323   map (prove_induction lthy2 defs rules' cnewpreds) 
   275         (preds ~~ newpreds ~~ tyss)
   324         (preds ~~ newpreds ~~ tyss)
   276   |> ProofContext.export lthy2 lthy1
   325           |> ProofContext.export lthy2 lthy1
   277 end*}
   326 end*}
   278 
   327 
   279 ML {*
   328 ML {*
   280   let 
   329   let 
   281     val rules = [@{prop "even (0::nat)"},
   330     val rules = [@{prop "even (0::nat)"},