1 (*<*)theory Advanced imports Even begin |
1 (*<*)theory Advanced imports Even begin |
2 ML_file "../../antiquote_setup.ML" |
2 ML_file "../../antiquote_setup.ML" |
3 (*>*) |
3 (*>*) |
4 |
4 |
5 text {* |
5 text \<open> |
6 The premises of introduction rules may contain universal quantifiers and |
6 The premises of introduction rules may contain universal quantifiers and |
7 monotone functions. A universal quantifier lets the rule |
7 monotone functions. A universal quantifier lets the rule |
8 refer to any number of instances of |
8 refer to any number of instances of |
9 the inductively defined set. A monotone function lets the rule refer |
9 the inductively defined set. A monotone function lets the rule refer |
10 to existing constructions (such as ``list of'') over the inductively defined |
10 to existing constructions (such as ``list of'') over the inductively defined |
11 set. The examples below show how to use the additional expressiveness |
11 set. The examples below show how to use the additional expressiveness |
12 and how to reason from the resulting definitions. |
12 and how to reason from the resulting definitions. |
13 *} |
13 \<close> |
14 |
14 |
15 subsection{* Universal Quantifiers in Introduction Rules \label{sec:gterm-datatype} *} |
15 subsection\<open>Universal Quantifiers in Introduction Rules \label{sec:gterm-datatype}\<close> |
16 |
16 |
17 text {* |
17 text \<open> |
18 \index{ground terms example|(}% |
18 \index{ground terms example|(}% |
19 \index{quantifiers!and inductive definitions|(}% |
19 \index{quantifiers!and inductive definitions|(}% |
20 As a running example, this section develops the theory of \textbf{ground |
20 As a running example, this section develops the theory of \textbf{ground |
21 terms}: terms constructed from constant and function |
21 terms}: terms constructed from constant and function |
22 symbols but not variables. To simplify matters further, we regard a |
22 symbols but not variables. To simplify matters further, we regard a |
23 constant as a function applied to the null argument list. Let us declare a |
23 constant as a function applied to the null argument list. Let us declare a |
24 datatype @{text gterm} for the type of ground terms. It is a type constructor |
24 datatype @{text gterm} for the type of ground terms. It is a type constructor |
25 whose argument is a type of function symbols. |
25 whose argument is a type of function symbols. |
26 *} |
26 \<close> |
27 |
27 |
28 datatype 'f gterm = Apply 'f "'f gterm list" |
28 datatype 'f gterm = Apply 'f "'f gterm list" |
29 |
29 |
30 text {* |
30 text \<open> |
31 To try it out, we declare a datatype of some integer operations: |
31 To try it out, we declare a datatype of some integer operations: |
32 integer constants, the unary minus operator and the addition |
32 integer constants, the unary minus operator and the addition |
33 operator. |
33 operator. |
34 *} |
34 \<close> |
35 |
35 |
36 datatype integer_op = Number int | UnaryMinus | Plus |
36 datatype integer_op = Number int | UnaryMinus | Plus |
37 |
37 |
38 text {* |
38 text \<open> |
39 Now the type @{typ "integer_op gterm"} denotes the ground |
39 Now the type @{typ "integer_op gterm"} denotes the ground |
40 terms built over those symbols. |
40 terms built over those symbols. |
41 |
41 |
42 The type constructor @{text gterm} can be generalized to a function |
42 The type constructor @{text gterm} can be generalized to a function |
43 over sets. It returns |
43 over sets. It returns |
54 A universal quantifier in the premise of the introduction rule |
54 A universal quantifier in the premise of the introduction rule |
55 expresses that every element of @{text args} belongs |
55 expresses that every element of @{text args} belongs |
56 to our inductively defined set: is a ground term |
56 to our inductively defined set: is a ground term |
57 over~@{text F}. The function @{term set} denotes the set of elements in a given |
57 over~@{text F}. The function @{term set} denotes the set of elements in a given |
58 list. |
58 list. |
59 *} |
59 \<close> |
60 |
60 |
61 inductive_set |
61 inductive_set |
62 gterms :: "'f set \<Rightarrow> 'f gterm set" |
62 gterms :: "'f set \<Rightarrow> 'f gterm set" |
63 for F :: "'f set" |
63 for F :: "'f set" |
64 where |
64 where |
65 step[intro!]: "\<lbrakk>\<forall>t \<in> set args. t \<in> gterms F; f \<in> F\<rbrakk> |
65 step[intro!]: "\<lbrakk>\<forall>t \<in> set args. t \<in> gterms F; f \<in> F\<rbrakk> |
66 \<Longrightarrow> (Apply f args) \<in> gterms F" |
66 \<Longrightarrow> (Apply f args) \<in> gterms F" |
67 |
67 |
68 text {* |
68 text \<open> |
69 To demonstrate a proof from this definition, let us |
69 To demonstrate a proof from this definition, let us |
70 show that the function @{term gterms} |
70 show that the function @{term gterms} |
71 is \textbf{monotone}. We shall need this concept shortly. |
71 is \textbf{monotone}. We shall need this concept shortly. |
72 *} |
72 \<close> |
73 |
73 |
74 lemma gterms_mono: "F\<subseteq>G \<Longrightarrow> gterms F \<subseteq> gterms G" |
74 lemma gterms_mono: "F\<subseteq>G \<Longrightarrow> gterms F \<subseteq> gterms G" |
75 apply clarify |
75 apply clarify |
76 apply (erule gterms.induct) |
76 apply (erule gterms.induct) |
77 apply blast |
77 apply blast |
79 (*<*) |
79 (*<*) |
80 lemma gterms_mono: "F\<subseteq>G \<Longrightarrow> gterms F \<subseteq> gterms G" |
80 lemma gterms_mono: "F\<subseteq>G \<Longrightarrow> gterms F \<subseteq> gterms G" |
81 apply clarify |
81 apply clarify |
82 apply (erule gterms.induct) |
82 apply (erule gterms.induct) |
83 (*>*) |
83 (*>*) |
84 txt{* |
84 txt\<open> |
85 Intuitively, this theorem says that |
85 Intuitively, this theorem says that |
86 enlarging the set of function symbols enlarges the set of ground |
86 enlarging the set of function symbols enlarges the set of ground |
87 terms. The proof is a trivial rule induction. |
87 terms. The proof is a trivial rule induction. |
88 First we use the @{text clarify} method to assume the existence of an element of |
88 First we use the @{text clarify} method to assume the existence of an element of |
89 @{term "gterms F"}. (We could have used @{text "intro subsetI"}.) We then |
89 @{term "gterms F"}. (We could have used @{text "intro subsetI"}.) We then |
90 apply rule induction. Here is the resulting subgoal: |
90 apply rule induction. Here is the resulting subgoal: |
91 @{subgoals[display,indent=0]} |
91 @{subgoals[display,indent=0]} |
92 The assumptions state that @{text f} belongs |
92 The assumptions state that @{text f} belongs |
93 to~@{text F}, which is included in~@{text G}, and that every element of the list @{text args} is |
93 to~@{text F}, which is included in~@{text G}, and that every element of the list @{text args} is |
94 a ground term over~@{text G}. The @{text blast} method finds this chain of reasoning easily. |
94 a ground term over~@{text G}. The @{text blast} method finds this chain of reasoning easily. |
95 *} |
95 \<close> |
96 (*<*)oops(*>*) |
96 (*<*)oops(*>*) |
97 text {* |
97 text \<open> |
98 \begin{warn} |
98 \begin{warn} |
99 Why do we call this function @{text gterms} instead |
99 Why do we call this function @{text gterms} instead |
100 of @{text gterm}? A constant may have the same name as a type. However, |
100 of @{text gterm}? A constant may have the same name as a type. However, |
101 name clashes could arise in the theorems that Isabelle generates. |
101 name clashes could arise in the theorems that Isabelle generates. |
102 Our choice of names keeps @{text gterms.induct} separate from |
102 Our choice of names keeps @{text gterms.induct} separate from |
111 Suppose we are given a function called @{text arity}, specifying the arities |
111 Suppose we are given a function called @{text arity}, specifying the arities |
112 of all symbols. In the inductive step, we have a list @{text args} of such |
112 of all symbols. In the inductive step, we have a list @{text args} of such |
113 terms and a function symbol~@{text f}. If the length of the list matches the |
113 terms and a function symbol~@{text f}. If the length of the list matches the |
114 function's arity then applying @{text f} to @{text args} yields a well-formed |
114 function's arity then applying @{text f} to @{text args} yields a well-formed |
115 term. |
115 term. |
116 *} |
116 \<close> |
117 |
117 |
118 inductive_set |
118 inductive_set |
119 well_formed_gterm :: "('f \<Rightarrow> nat) \<Rightarrow> 'f gterm set" |
119 well_formed_gterm :: "('f \<Rightarrow> nat) \<Rightarrow> 'f gterm set" |
120 for arity :: "'f \<Rightarrow> nat" |
120 for arity :: "'f \<Rightarrow> nat" |
121 where |
121 where |
122 step[intro!]: "\<lbrakk>\<forall>t \<in> set args. t \<in> well_formed_gterm arity; |
122 step[intro!]: "\<lbrakk>\<forall>t \<in> set args. t \<in> well_formed_gterm arity; |
123 length args = arity f\<rbrakk> |
123 length args = arity f\<rbrakk> |
124 \<Longrightarrow> (Apply f args) \<in> well_formed_gterm arity" |
124 \<Longrightarrow> (Apply f args) \<in> well_formed_gterm arity" |
125 |
125 |
126 text {* |
126 text \<open> |
127 The inductive definition neatly captures the reasoning above. |
127 The inductive definition neatly captures the reasoning above. |
128 The universal quantification over the |
128 The universal quantification over the |
129 @{text set} of arguments expresses that all of them are well-formed.% |
129 @{text set} of arguments expresses that all of them are well-formed.% |
130 \index{quantifiers!and inductive definitions|)} |
130 \index{quantifiers!and inductive definitions|)} |
131 *} |
131 \<close> |
132 |
132 |
133 subsection{* Alternative Definition Using a Monotone Function *} |
133 subsection\<open>Alternative Definition Using a Monotone Function\<close> |
134 |
134 |
135 text {* |
135 text \<open> |
136 \index{monotone functions!and inductive definitions|(}% |
136 \index{monotone functions!and inductive definitions|(}% |
137 An inductive definition may refer to the |
137 An inductive definition may refer to the |
138 inductively defined set through an arbitrary monotone function. To |
138 inductively defined set through an arbitrary monotone function. To |
139 demonstrate this powerful feature, let us |
139 demonstrate this powerful feature, let us |
140 change the inductive definition above, replacing the |
140 change the inductive definition above, replacing the |
146 |
146 |
147 In the inductive definition of well-formed terms, examine the one |
147 In the inductive definition of well-formed terms, examine the one |
148 introduction rule. The first premise states that @{text args} belongs to |
148 introduction rule. The first premise states that @{text args} belongs to |
149 the @{text lists} of well-formed terms. This formulation is more |
149 the @{text lists} of well-formed terms. This formulation is more |
150 direct, if more obscure, than using a universal quantifier. |
150 direct, if more obscure, than using a universal quantifier. |
151 *} |
151 \<close> |
152 |
152 |
153 inductive_set |
153 inductive_set |
154 well_formed_gterm' :: "('f \<Rightarrow> nat) \<Rightarrow> 'f gterm set" |
154 well_formed_gterm' :: "('f \<Rightarrow> nat) \<Rightarrow> 'f gterm set" |
155 for arity :: "'f \<Rightarrow> nat" |
155 for arity :: "'f \<Rightarrow> nat" |
156 where |
156 where |
157 step[intro!]: "\<lbrakk>args \<in> lists (well_formed_gterm' arity); |
157 step[intro!]: "\<lbrakk>args \<in> lists (well_formed_gterm' arity); |
158 length args = arity f\<rbrakk> |
158 length args = arity f\<rbrakk> |
159 \<Longrightarrow> (Apply f args) \<in> well_formed_gterm' arity" |
159 \<Longrightarrow> (Apply f args) \<in> well_formed_gterm' arity" |
160 monos lists_mono |
160 monos lists_mono |
161 |
161 |
162 text {* |
162 text \<open> |
163 We cite the theorem @{text lists_mono} to justify |
163 We cite the theorem @{text lists_mono} to justify |
164 using the function @{term lists}.% |
164 using the function @{term lists}.% |
165 \footnote{This particular theorem is installed by default already, but we |
165 \footnote{This particular theorem is installed by default already, but we |
166 include the \isakeyword{monos} declaration in order to illustrate its syntax.} |
166 include the \isakeyword{monos} declaration in order to illustrate its syntax.} |
167 @{named_thms [display,indent=0] lists_mono [no_vars] (lists_mono)} |
167 @{named_thms [display,indent=0] lists_mono [no_vars] (lists_mono)} |
192 new term, @{term "Apply f args"}. Because @{term lists} is monotone, |
192 new term, @{term "Apply f args"}. Because @{term lists} is monotone, |
193 applications of the rule remain valid as new terms are constructed. |
193 applications of the rule remain valid as new terms are constructed. |
194 Further lists of well-formed |
194 Further lists of well-formed |
195 terms become available and none are taken away.% |
195 terms become available and none are taken away.% |
196 \index{monotone functions!and inductive definitions|)} |
196 \index{monotone functions!and inductive definitions|)} |
197 *} |
197 \<close> |
198 |
198 |
199 subsection{* A Proof of Equivalence *} |
199 subsection\<open>A Proof of Equivalence\<close> |
200 |
200 |
201 text {* |
201 text \<open> |
202 We naturally hope that these two inductive definitions of ``well-formed'' |
202 We naturally hope that these two inductive definitions of ``well-formed'' |
203 coincide. The equality can be proved by separate inclusions in |
203 coincide. The equality can be proved by separate inclusions in |
204 each direction. Each is a trivial rule induction. |
204 each direction. Each is a trivial rule induction. |
205 *} |
205 \<close> |
206 |
206 |
207 lemma "well_formed_gterm arity \<subseteq> well_formed_gterm' arity" |
207 lemma "well_formed_gterm arity \<subseteq> well_formed_gterm' arity" |
208 apply clarify |
208 apply clarify |
209 apply (erule well_formed_gterm.induct) |
209 apply (erule well_formed_gterm.induct) |
210 apply auto |
210 apply auto |
212 (*<*) |
212 (*<*) |
213 lemma "well_formed_gterm arity \<subseteq> well_formed_gterm' arity" |
213 lemma "well_formed_gterm arity \<subseteq> well_formed_gterm' arity" |
214 apply clarify |
214 apply clarify |
215 apply (erule well_formed_gterm.induct) |
215 apply (erule well_formed_gterm.induct) |
216 (*>*) |
216 (*>*) |
217 txt {* |
217 txt \<open> |
218 The @{text clarify} method gives |
218 The @{text clarify} method gives |
219 us an element of @{term "well_formed_gterm arity"} on which to perform |
219 us an element of @{term "well_formed_gterm arity"} on which to perform |
220 induction. The resulting subgoal can be proved automatically: |
220 induction. The resulting subgoal can be proved automatically: |
221 @{subgoals[display,indent=0]} |
221 @{subgoals[display,indent=0]} |
222 This proof resembles the one given in |
222 This proof resembles the one given in |
223 {\S}\ref{sec:gterm-datatype} above, especially in the form of the |
223 {\S}\ref{sec:gterm-datatype} above, especially in the form of the |
224 induction hypothesis. Next, we consider the opposite inclusion: |
224 induction hypothesis. Next, we consider the opposite inclusion: |
225 *} |
225 \<close> |
226 (*<*)oops(*>*) |
226 (*<*)oops(*>*) |
227 lemma "well_formed_gterm' arity \<subseteq> well_formed_gterm arity" |
227 lemma "well_formed_gterm' arity \<subseteq> well_formed_gterm arity" |
228 apply clarify |
228 apply clarify |
229 apply (erule well_formed_gterm'.induct) |
229 apply (erule well_formed_gterm'.induct) |
230 apply auto |
230 apply auto |
255 This example is typical of how monotone functions |
255 This example is typical of how monotone functions |
256 \index{monotone functions} can be used. In particular, many of them |
256 \index{monotone functions} can be used. In particular, many of them |
257 distribute over intersection. Monotonicity implies one direction of |
257 distribute over intersection. Monotonicity implies one direction of |
258 this set equality; we have this theorem: |
258 this set equality; we have this theorem: |
259 @{named_thms [display,indent=0] mono_Int [no_vars] (mono_Int)} |
259 @{named_thms [display,indent=0] mono_Int [no_vars] (mono_Int)} |
260 *} |
260 \<close> |
261 (*<*)oops(*>*) |
261 (*<*)oops(*>*) |
262 |
262 |
263 |
263 |
264 subsection{* Another Example of Rule Inversion *} |
264 subsection\<open>Another Example of Rule Inversion\<close> |
265 |
265 |
266 text {* |
266 text \<open> |
267 \index{rule inversion|(}% |
267 \index{rule inversion|(}% |
268 Does @{term gterms} distribute over intersection? We have proved that this |
268 Does @{term gterms} distribute over intersection? We have proved that this |
269 function is monotone, so @{text mono_Int} gives one of the inclusions. The |
269 function is monotone, so @{text mono_Int} gives one of the inclusions. The |
270 opposite inclusion asserts that if @{term t} is a ground term over both of the |
270 opposite inclusion asserts that if @{term t} is a ground term over both of the |
271 sets |
271 sets |
272 @{term F} and~@{term G} then it is also a ground term over their intersection, |
272 @{term F} and~@{term G} then it is also a ground term over their intersection, |
273 @{term "F \<inter> G"}. |
273 @{term "F \<inter> G"}. |
274 *} |
274 \<close> |
275 |
275 |
276 lemma gterms_IntI: |
276 lemma gterms_IntI: |
277 "t \<in> gterms F \<Longrightarrow> t \<in> gterms G \<longrightarrow> t \<in> gterms (F\<inter>G)" |
277 "t \<in> gterms F \<Longrightarrow> t \<in> gterms G \<longrightarrow> t \<in> gterms (F\<inter>G)" |
278 (*<*)oops(*>*) |
278 (*<*)oops(*>*) |
279 text {* |
279 text \<open> |
280 Attempting this proof, we get the assumption |
280 Attempting this proof, we get the assumption |
281 @{term "Apply f args \<in> gterms G"}, which cannot be broken down. |
281 @{term "Apply f args \<in> gterms G"}, which cannot be broken down. |
282 It looks like a job for rule inversion:\cmmdx{inductive\protect\_cases} |
282 It looks like a job for rule inversion:\cmmdx{inductive\protect\_cases} |
283 *} |
283 \<close> |
284 |
284 |
285 inductive_cases gterm_Apply_elim [elim!]: "Apply f args \<in> gterms F" |
285 inductive_cases gterm_Apply_elim [elim!]: "Apply f args \<in> gterms F" |
286 |
286 |
287 text {* |
287 text \<open> |
288 Here is the result. |
288 Here is the result. |
289 @{named_thms [display,indent=0,margin=50] gterm_Apply_elim [no_vars] (gterm_Apply_elim)} |
289 @{named_thms [display,indent=0,margin=50] gterm_Apply_elim [no_vars] (gterm_Apply_elim)} |
290 This rule replaces an assumption about @{term "Apply f args"} by |
290 This rule replaces an assumption about @{term "Apply f args"} by |
291 assumptions about @{term f} and~@{term args}. |
291 assumptions about @{term f} and~@{term args}. |
292 No cases are discarded (there was only one to begin |
292 No cases are discarded (there was only one to begin |
293 with) but the rule applies specifically to the pattern @{term "Apply f args"}. |
293 with) but the rule applies specifically to the pattern @{term "Apply f args"}. |
294 It can be applied repeatedly as an elimination rule without looping, so we |
294 It can be applied repeatedly as an elimination rule without looping, so we |
295 have given the @{text "elim!"} attribute. |
295 have given the @{text "elim!"} attribute. |
296 |
296 |
297 Now we can prove the other half of that distributive law. |
297 Now we can prove the other half of that distributive law. |
298 *} |
298 \<close> |
299 |
299 |
300 lemma gterms_IntI [rule_format, intro!]: |
300 lemma gterms_IntI [rule_format, intro!]: |
301 "t \<in> gterms F \<Longrightarrow> t \<in> gterms G \<longrightarrow> t \<in> gterms (F\<inter>G)" |
301 "t \<in> gterms F \<Longrightarrow> t \<in> gterms G \<longrightarrow> t \<in> gterms (F\<inter>G)" |
302 apply (erule gterms.induct) |
302 apply (erule gterms.induct) |
303 apply blast |
303 apply blast |
304 done |
304 done |
305 (*<*) |
305 (*<*) |
306 lemma "t \<in> gterms F \<Longrightarrow> t \<in> gterms G \<longrightarrow> t \<in> gterms (F\<inter>G)" |
306 lemma "t \<in> gterms F \<Longrightarrow> t \<in> gterms G \<longrightarrow> t \<in> gterms (F\<inter>G)" |
307 apply (erule gterms.induct) |
307 apply (erule gterms.induct) |
308 (*>*) |
308 (*>*) |
309 txt {* |
309 txt \<open> |
310 The proof begins with rule induction over the definition of |
310 The proof begins with rule induction over the definition of |
311 @{term gterms}, which leaves a single subgoal: |
311 @{term gterms}, which leaves a single subgoal: |
312 @{subgoals[display,indent=0,margin=65]} |
312 @{subgoals[display,indent=0,margin=65]} |
313 To prove this, we assume @{term "Apply f args \<in> gterms G"}. Rule inversion, |
313 To prove this, we assume @{term "Apply f args \<in> gterms G"}. Rule inversion, |
314 in the form of @{text gterm_Apply_elim}, infers |
314 in the form of @{text gterm_Apply_elim}, infers |
350 "\<lbrakk>\<forall>pair \<in> set args. pair \<in> well_typed_gterm sig; |
350 "\<lbrakk>\<forall>pair \<in> set args. pair \<in> well_typed_gterm sig; |
351 sig f = (map snd args, rtype)\<rbrakk> |
351 sig f = (map snd args, rtype)\<rbrakk> |
352 \<Longrightarrow> (Apply f (map fst args), rtype) |
352 \<Longrightarrow> (Apply f (map fst args), rtype) |
353 \<in> well_typed_gterm sig" |
353 \<in> well_typed_gterm sig" |
354 (*>*) |
354 (*>*) |
355 text_raw {* |
355 text_raw \<open> |
356 \end{isabelle} |
356 \end{isabelle} |
357 \end{exercise} |
357 \end{exercise} |
358 \end{isamarkuptext} |
358 \end{isamarkuptext} |
359 *} |
359 \<close> |
360 |
360 |
361 (*<*) |
361 (*<*) |
362 |
362 |
363 text{*the following declaration isn't actually used*} |
363 text\<open>the following declaration isn't actually used\<close> |
364 primrec |
364 primrec |
365 integer_arity :: "integer_op \<Rightarrow> nat" |
365 integer_arity :: "integer_op \<Rightarrow> nat" |
366 where |
366 where |
367 "integer_arity (Number n) = 0" |
367 "integer_arity (Number n) = 0" |
368 | "integer_arity UnaryMinus = 1" |
368 | "integer_arity UnaryMinus = 1" |
369 | "integer_arity Plus = 2" |
369 | "integer_arity Plus = 2" |
370 |
370 |
371 text{* the rest isn't used: too complicated. OK for an exercise though.*} |
371 text\<open>the rest isn't used: too complicated. OK for an exercise though.\<close> |
372 |
372 |
373 inductive_set |
373 inductive_set |
374 integer_signature :: "(integer_op * (unit list * unit)) set" |
374 integer_signature :: "(integer_op * (unit list * unit)) set" |
375 where |
375 where |
376 Number: "(Number n, ([], ())) \<in> integer_signature" |
376 Number: "(Number n, ([], ())) \<in> integer_signature" |