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 |