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} |
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' |
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 |