1 (* Title: HOL/Induct/QuoNestedDataType.thy |
1 (* Title: HOL/Induct/QuoNestedDataType.thy |
2 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
2 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
3 Copyright 2004 University of Cambridge |
3 Copyright 2004 University of Cambridge |
4 *) |
4 *) |
5 |
5 |
6 section{*Quotienting a Free Algebra Involving Nested Recursion*} |
6 section\<open>Quotienting a Free Algebra Involving Nested Recursion\<close> |
7 |
7 |
8 theory QuoNestedDataType imports Main begin |
8 theory QuoNestedDataType imports Main begin |
9 |
9 |
10 subsection{*Defining the Free Algebra*} |
10 subsection\<open>Defining the Free Algebra\<close> |
11 |
11 |
12 text{*Messages with encryption and decryption as free constructors.*} |
12 text\<open>Messages with encryption and decryption as free constructors.\<close> |
13 datatype |
13 datatype |
14 freeExp = VAR nat |
14 freeExp = VAR nat |
15 | PLUS freeExp freeExp |
15 | PLUS freeExp freeExp |
16 | FNCALL nat "freeExp list" |
16 | FNCALL nat "freeExp list" |
17 |
17 |
18 datatype_compat freeExp |
18 datatype_compat freeExp |
19 |
19 |
20 text{*The equivalence relation, which makes PLUS associative.*} |
20 text\<open>The equivalence relation, which makes PLUS associative.\<close> |
21 |
21 |
22 text{*The first rule is the desired equation. The next three rules |
22 text\<open>The first rule is the desired equation. The next three rules |
23 make the equations applicable to subterms. The last two rules are symmetry |
23 make the equations applicable to subterms. The last two rules are symmetry |
24 and transitivity.*} |
24 and transitivity.\<close> |
25 inductive_set |
25 inductive_set |
26 exprel :: "(freeExp * freeExp) set" |
26 exprel :: "(freeExp * freeExp) set" |
27 and exp_rel :: "[freeExp, freeExp] => bool" (infixl "\<sim>" 50) |
27 and exp_rel :: "[freeExp, freeExp] => bool" (infixl "\<sim>" 50) |
28 where |
28 where |
29 "X \<sim> Y == (X,Y) \<in> exprel" |
29 "X \<sim> Y == (X,Y) \<in> exprel" |
65 \<Longrightarrow> FNCALL F (X#Xs) \<sim> FNCALL F (X'#Xs')" |
65 \<Longrightarrow> FNCALL F (X#Xs) \<sim> FNCALL F (X'#Xs')" |
66 by (blast intro: exprel.intros listrel.intros) |
66 by (blast intro: exprel.intros listrel.intros) |
67 |
67 |
68 |
68 |
69 |
69 |
70 subsection{*Some Functions on the Free Algebra*} |
70 subsection\<open>Some Functions on the Free Algebra\<close> |
71 |
71 |
72 subsubsection{*The Set of Variables*} |
72 subsubsection\<open>The Set of Variables\<close> |
73 |
73 |
74 text{*A function to return the set of variables present in a message. It will |
74 text\<open>A function to return the set of variables present in a message. It will |
75 be lifted to the initial algebra, to serve as an example of that process. |
75 be lifted to the initial algebra, to serve as an example of that process. |
76 Note that the "free" refers to the free datatype rather than to the concept |
76 Note that the "free" refers to the free datatype rather than to the concept |
77 of a free variable.*} |
77 of a free variable.\<close> |
78 primrec freevars :: "freeExp \<Rightarrow> nat set" |
78 primrec freevars :: "freeExp \<Rightarrow> nat set" |
79 and freevars_list :: "freeExp list \<Rightarrow> nat set" where |
79 and freevars_list :: "freeExp list \<Rightarrow> nat set" where |
80 "freevars (VAR N) = {N}" |
80 "freevars (VAR N) = {N}" |
81 | "freevars (PLUS X Y) = freevars X \<union> freevars Y" |
81 | "freevars (PLUS X Y) = freevars X \<union> freevars Y" |
82 | "freevars (FNCALL F Xs) = freevars_list Xs" |
82 | "freevars (FNCALL F Xs) = freevars_list Xs" |
83 |
83 |
84 | "freevars_list [] = {}" |
84 | "freevars_list [] = {}" |
85 | "freevars_list (X # Xs) = freevars X \<union> freevars_list Xs" |
85 | "freevars_list (X # Xs) = freevars X \<union> freevars_list Xs" |
86 |
86 |
87 text{*This theorem lets us prove that the vars function respects the |
87 text\<open>This theorem lets us prove that the vars function respects the |
88 equivalence relation. It also helps us prove that Variable |
88 equivalence relation. It also helps us prove that Variable |
89 (the abstract constructor) is injective*} |
89 (the abstract constructor) is injective\<close> |
90 theorem exprel_imp_eq_freevars: "U \<sim> V \<Longrightarrow> freevars U = freevars V" |
90 theorem exprel_imp_eq_freevars: "U \<sim> V \<Longrightarrow> freevars U = freevars V" |
91 apply (induct set: exprel) |
91 apply (induct set: exprel) |
92 apply (erule_tac [4] listrel.induct) |
92 apply (erule_tac [4] listrel.induct) |
93 apply (simp_all add: Un_assoc) |
93 apply (simp_all add: Un_assoc) |
94 done |
94 done |
95 |
95 |
96 |
96 |
97 |
97 |
98 subsubsection{*Functions for Freeness*} |
98 subsubsection\<open>Functions for Freeness\<close> |
99 |
99 |
100 text{*A discriminator function to distinguish vars, sums and function calls*} |
100 text\<open>A discriminator function to distinguish vars, sums and function calls\<close> |
101 primrec freediscrim :: "freeExp \<Rightarrow> int" where |
101 primrec freediscrim :: "freeExp \<Rightarrow> int" where |
102 "freediscrim (VAR N) = 0" |
102 "freediscrim (VAR N) = 0" |
103 | "freediscrim (PLUS X Y) = 1" |
103 | "freediscrim (PLUS X Y) = 1" |
104 | "freediscrim (FNCALL F Xs) = 2" |
104 | "freediscrim (FNCALL F Xs) = 2" |
105 |
105 |
106 theorem exprel_imp_eq_freediscrim: |
106 theorem exprel_imp_eq_freediscrim: |
107 "U \<sim> V \<Longrightarrow> freediscrim U = freediscrim V" |
107 "U \<sim> V \<Longrightarrow> freediscrim U = freediscrim V" |
108 by (induct set: exprel) auto |
108 by (induct set: exprel) auto |
109 |
109 |
110 |
110 |
111 text{*This function, which returns the function name, is used to |
111 text\<open>This function, which returns the function name, is used to |
112 prove part of the injectivity property for FnCall.*} |
112 prove part of the injectivity property for FnCall.\<close> |
113 primrec freefun :: "freeExp \<Rightarrow> nat" where |
113 primrec freefun :: "freeExp \<Rightarrow> nat" where |
114 "freefun (VAR N) = 0" |
114 "freefun (VAR N) = 0" |
115 | "freefun (PLUS X Y) = 0" |
115 | "freefun (PLUS X Y) = 0" |
116 | "freefun (FNCALL F Xs) = F" |
116 | "freefun (FNCALL F Xs) = F" |
117 |
117 |
118 theorem exprel_imp_eq_freefun: |
118 theorem exprel_imp_eq_freefun: |
119 "U \<sim> V \<Longrightarrow> freefun U = freefun V" |
119 "U \<sim> V \<Longrightarrow> freefun U = freefun V" |
120 by (induct set: exprel) (simp_all add: listrel.intros) |
120 by (induct set: exprel) (simp_all add: listrel.intros) |
121 |
121 |
122 |
122 |
123 text{*This function, which returns the list of function arguments, is used to |
123 text\<open>This function, which returns the list of function arguments, is used to |
124 prove part of the injectivity property for FnCall.*} |
124 prove part of the injectivity property for FnCall.\<close> |
125 primrec freeargs :: "freeExp \<Rightarrow> freeExp list" where |
125 primrec freeargs :: "freeExp \<Rightarrow> freeExp list" where |
126 "freeargs (VAR N) = []" |
126 "freeargs (VAR N) = []" |
127 | "freeargs (PLUS X Y) = []" |
127 | "freeargs (PLUS X Y) = []" |
128 | "freeargs (FNCALL F Xs) = Xs" |
128 | "freeargs (FNCALL F Xs) = Xs" |
129 |
129 |
166 FnCall :: "[nat, exp list] \<Rightarrow> exp" where |
166 FnCall :: "[nat, exp list] \<Rightarrow> exp" where |
167 "FnCall F Xs = |
167 "FnCall F Xs = |
168 Abs_Exp (\<Union>Us \<in> listset (map Rep_Exp Xs). exprel `` {FNCALL F Us})" |
168 Abs_Exp (\<Union>Us \<in> listset (map Rep_Exp Xs). exprel `` {FNCALL F Us})" |
169 |
169 |
170 |
170 |
171 text{*Reduces equality of equivalence classes to the @{term exprel} relation: |
171 text\<open>Reduces equality of equivalence classes to the @{term exprel} relation: |
172 @{term "(exprel `` {x} = exprel `` {y}) = ((x,y) \<in> exprel)"} *} |
172 @{term "(exprel `` {x} = exprel `` {y}) = ((x,y) \<in> exprel)"}\<close> |
173 lemmas equiv_exprel_iff = eq_equiv_class_iff [OF equiv_exprel UNIV_I UNIV_I] |
173 lemmas equiv_exprel_iff = eq_equiv_class_iff [OF equiv_exprel UNIV_I UNIV_I] |
174 |
174 |
175 declare equiv_exprel_iff [simp] |
175 declare equiv_exprel_iff [simp] |
176 |
176 |
177 |
177 |
178 text{*All equivalence classes belong to set of representatives*} |
178 text\<open>All equivalence classes belong to set of representatives\<close> |
179 lemma [simp]: "exprel``{U} \<in> Exp" |
179 lemma [simp]: "exprel``{U} \<in> Exp" |
180 by (auto simp add: Exp_def quotient_def intro: exprel_refl) |
180 by (auto simp add: Exp_def quotient_def intro: exprel_refl) |
181 |
181 |
182 lemma inj_on_Abs_Exp: "inj_on Abs_Exp Exp" |
182 lemma inj_on_Abs_Exp: "inj_on Abs_Exp Exp" |
183 apply (rule inj_on_inverseI) |
183 apply (rule inj_on_inverseI) |
184 apply (erule Abs_Exp_inverse) |
184 apply (erule Abs_Exp_inverse) |
185 done |
185 done |
186 |
186 |
187 text{*Reduces equality on abstractions to equality on representatives*} |
187 text\<open>Reduces equality on abstractions to equality on representatives\<close> |
188 declare inj_on_Abs_Exp [THEN inj_on_iff, simp] |
188 declare inj_on_Abs_Exp [THEN inj_on_iff, simp] |
189 |
189 |
190 declare Abs_Exp_inverse [simp] |
190 declare Abs_Exp_inverse [simp] |
191 |
191 |
192 |
192 |
193 text{*Case analysis on the representation of a exp as an equivalence class.*} |
193 text\<open>Case analysis on the representation of a exp as an equivalence class.\<close> |
194 lemma eq_Abs_Exp [case_names Abs_Exp, cases type: exp]: |
194 lemma eq_Abs_Exp [case_names Abs_Exp, cases type: exp]: |
195 "(!!U. z = Abs_Exp(exprel``{U}) ==> P) ==> P" |
195 "(!!U. z = Abs_Exp(exprel``{U}) ==> P) ==> P" |
196 apply (rule Rep_Exp [of z, unfolded Exp_def, THEN quotientE]) |
196 apply (rule Rep_Exp [of z, unfolded Exp_def, THEN quotientE]) |
197 apply (drule arg_cong [where f=Abs_Exp]) |
197 apply (drule arg_cong [where f=Abs_Exp]) |
198 apply (auto simp add: Rep_Exp_inverse intro: exprel_refl) |
198 apply (auto simp add: Rep_Exp_inverse intro: exprel_refl) |
199 done |
199 done |
200 |
200 |
201 |
201 |
202 subsection{*Every list of abstract expressions can be expressed in terms of a |
202 subsection\<open>Every list of abstract expressions can be expressed in terms of a |
203 list of concrete expressions*} |
203 list of concrete expressions\<close> |
204 |
204 |
205 definition |
205 definition |
206 Abs_ExpList :: "freeExp list => exp list" where |
206 Abs_ExpList :: "freeExp list => exp list" where |
207 "Abs_ExpList Xs = map (%U. Abs_Exp(exprel``{U})) Xs" |
207 "Abs_ExpList Xs = map (%U. Abs_Exp(exprel``{U})) Xs" |
208 |
208 |
223 lemma eq_Abs_ExpList [case_names Abs_ExpList]: |
223 lemma eq_Abs_ExpList [case_names Abs_ExpList]: |
224 "(!!Us. z = Abs_ExpList Us ==> P) ==> P" |
224 "(!!Us. z = Abs_ExpList Us ==> P) ==> P" |
225 by (rule exE [OF ExpList_rep], blast) |
225 by (rule exE [OF ExpList_rep], blast) |
226 |
226 |
227 |
227 |
228 subsubsection{*Characteristic Equations for the Abstract Constructors*} |
228 subsubsection\<open>Characteristic Equations for the Abstract Constructors\<close> |
229 |
229 |
230 lemma Plus: "Plus (Abs_Exp(exprel``{U})) (Abs_Exp(exprel``{V})) = |
230 lemma Plus: "Plus (Abs_Exp(exprel``{U})) (Abs_Exp(exprel``{V})) = |
231 Abs_Exp (exprel``{PLUS U V})" |
231 Abs_Exp (exprel``{PLUS U V})" |
232 proof - |
232 proof - |
233 have "(\<lambda>U V. exprel `` {PLUS U V}) respects2 exprel" |
233 have "(\<lambda>U V. exprel `` {PLUS U V}) respects2 exprel" |
234 by (auto simp add: congruent2_def exprel.PLUS) |
234 by (auto simp add: congruent2_def exprel.PLUS) |
235 thus ?thesis |
235 thus ?thesis |
236 by (simp add: Plus_def UN_equiv_class2 [OF equiv_exprel equiv_exprel]) |
236 by (simp add: Plus_def UN_equiv_class2 [OF equiv_exprel equiv_exprel]) |
237 qed |
237 qed |
238 |
238 |
239 text{*It is not clear what to do with FnCall: it's argument is an abstraction |
239 text\<open>It is not clear what to do with FnCall: it's argument is an abstraction |
240 of an @{typ "exp list"}. Is it just Nil or Cons? What seems to work best is to |
240 of an @{typ "exp list"}. Is it just Nil or Cons? What seems to work best is to |
241 regard an @{typ "exp list"} as a @{term "listrel exprel"} equivalence class*} |
241 regard an @{typ "exp list"} as a @{term "listrel exprel"} equivalence class\<close> |
242 |
242 |
243 text{*This theorem is easily proved but never used. There's no obvious way |
243 text\<open>This theorem is easily proved but never used. There's no obvious way |
244 even to state the analogous result, @{text FnCall_Cons}.*} |
244 even to state the analogous result, @{text FnCall_Cons}.\<close> |
245 lemma FnCall_Nil: "FnCall F [] = Abs_Exp (exprel``{FNCALL F []})" |
245 lemma FnCall_Nil: "FnCall F [] = Abs_Exp (exprel``{FNCALL F []})" |
246 by (simp add: FnCall_def) |
246 by (simp add: FnCall_def) |
247 |
247 |
248 lemma FnCall_respects: |
248 lemma FnCall_respects: |
249 "(\<lambda>Us. exprel `` {FNCALL F Us}) respects (listrel exprel)" |
249 "(\<lambda>Us. exprel `` {FNCALL F Us}) respects (listrel exprel)" |
271 by (simp add: FnCall_def UN_equiv_class [OF equiv_list_exprel] |
271 by (simp add: FnCall_def UN_equiv_class [OF equiv_list_exprel] |
272 listset_Rep_Exp_Abs_Exp) |
272 listset_Rep_Exp_Abs_Exp) |
273 qed |
273 qed |
274 |
274 |
275 |
275 |
276 text{*Establishing this equation is the point of the whole exercise*} |
276 text\<open>Establishing this equation is the point of the whole exercise\<close> |
277 theorem Plus_assoc: "Plus X (Plus Y Z) = Plus (Plus X Y) Z" |
277 theorem Plus_assoc: "Plus X (Plus Y Z) = Plus (Plus X Y) Z" |
278 by (cases X, cases Y, cases Z, simp add: Plus exprel.ASSOC) |
278 by (cases X, cases Y, cases Z, simp add: Plus exprel.ASSOC) |
279 |
279 |
280 |
280 |
281 |
281 |
282 subsection{*The Abstract Function to Return the Set of Variables*} |
282 subsection\<open>The Abstract Function to Return the Set of Variables\<close> |
283 |
283 |
284 definition |
284 definition |
285 vars :: "exp \<Rightarrow> nat set" where |
285 vars :: "exp \<Rightarrow> nat set" where |
286 "vars X = (\<Union>U \<in> Rep_Exp X. freevars U)" |
286 "vars X = (\<Union>U \<in> Rep_Exp X. freevars U)" |
287 |
287 |
288 lemma vars_respects: "freevars respects exprel" |
288 lemma vars_respects: "freevars respects exprel" |
289 by (auto simp add: congruent_def exprel_imp_eq_freevars) |
289 by (auto simp add: congruent_def exprel_imp_eq_freevars) |
290 |
290 |
291 text{*The extension of the function @{term vars} to lists*} |
291 text\<open>The extension of the function @{term vars} to lists\<close> |
292 primrec vars_list :: "exp list \<Rightarrow> nat set" where |
292 primrec vars_list :: "exp list \<Rightarrow> nat set" where |
293 "vars_list [] = {}" |
293 "vars_list [] = {}" |
294 | "vars_list(E#Es) = vars E \<union> vars_list Es" |
294 | "vars_list(E#Es) = vars E \<union> vars_list Es" |
295 |
295 |
296 |
296 |
297 text{*Now prove the three equations for @{term vars}*} |
297 text\<open>Now prove the three equations for @{term vars}\<close> |
298 |
298 |
299 lemma vars_Variable [simp]: "vars (Var N) = {N}" |
299 lemma vars_Variable [simp]: "vars (Var N) = {N}" |
300 by (simp add: vars_def Var_def |
300 by (simp add: vars_def Var_def |
301 UN_equiv_class [OF equiv_exprel vars_respects]) |
301 UN_equiv_class [OF equiv_exprel vars_respects]) |
302 |
302 |
318 |
318 |
319 lemma vars_FnCall_Cons: "vars (FnCall F (X#Xs)) = vars X \<union> vars_list Xs" |
319 lemma vars_FnCall_Cons: "vars (FnCall F (X#Xs)) = vars X \<union> vars_list Xs" |
320 by simp |
320 by simp |
321 |
321 |
322 |
322 |
323 subsection{*Injectivity Properties of Some Constructors*} |
323 subsection\<open>Injectivity Properties of Some Constructors\<close> |
324 |
324 |
325 lemma VAR_imp_eq: "VAR m \<sim> VAR n \<Longrightarrow> m = n" |
325 lemma VAR_imp_eq: "VAR m \<sim> VAR n \<Longrightarrow> m = n" |
326 by (drule exprel_imp_eq_freevars, simp) |
326 by (drule exprel_imp_eq_freevars, simp) |
327 |
327 |
328 text{*Can also be proved using the function @{term vars}*} |
328 text\<open>Can also be proved using the function @{term vars}\<close> |
329 lemma Var_Var_eq [iff]: "(Var m = Var n) = (m = n)" |
329 lemma Var_Var_eq [iff]: "(Var m = Var n) = (m = n)" |
330 by (auto simp add: Var_def exprel_refl dest: VAR_imp_eq) |
330 by (auto simp add: Var_def exprel_refl dest: VAR_imp_eq) |
331 |
331 |
332 lemma VAR_neqv_PLUS: "VAR m \<sim> PLUS X Y \<Longrightarrow> False" |
332 lemma VAR_neqv_PLUS: "VAR m \<sim> PLUS X Y \<Longrightarrow> False" |
333 by (drule exprel_imp_eq_freediscrim, simp) |
333 by (drule exprel_imp_eq_freediscrim, simp) |
387 next |
387 next |
388 assume "F=F' & Xs=Xs'" thus "FnCall F Xs = FnCall F' Xs'" by simp |
388 assume "F=F' & Xs=Xs'" thus "FnCall F Xs = FnCall F' Xs'" by simp |
389 qed |
389 qed |
390 |
390 |
391 |
391 |
392 subsection{*The Abstract Discriminator*} |
392 subsection\<open>The Abstract Discriminator\<close> |
393 text{*However, as @{text FnCall_Var_neq_Var} illustrates, we don't need this |
393 text\<open>However, as @{text FnCall_Var_neq_Var} illustrates, we don't need this |
394 function in order to prove discrimination theorems.*} |
394 function in order to prove discrimination theorems.\<close> |
395 |
395 |
396 definition |
396 definition |
397 discrim :: "exp \<Rightarrow> int" where |
397 discrim :: "exp \<Rightarrow> int" where |
398 "discrim X = the_elem (\<Union>U \<in> Rep_Exp X. {freediscrim U})" |
398 "discrim X = the_elem (\<Union>U \<in> Rep_Exp X. {freediscrim U})" |
399 |
399 |
400 lemma discrim_respects: "(\<lambda>U. {freediscrim U}) respects exprel" |
400 lemma discrim_respects: "(\<lambda>U. {freediscrim U}) respects exprel" |
401 by (auto simp add: congruent_def exprel_imp_eq_freediscrim) |
401 by (auto simp add: congruent_def exprel_imp_eq_freediscrim) |
402 |
402 |
403 text{*Now prove the four equations for @{term discrim}*} |
403 text\<open>Now prove the four equations for @{term discrim}\<close> |
404 |
404 |
405 lemma discrim_Var [simp]: "discrim (Var N) = 0" |
405 lemma discrim_Var [simp]: "discrim (Var N) = 0" |
406 by (simp add: discrim_def Var_def |
406 by (simp add: discrim_def Var_def |
407 UN_equiv_class [OF equiv_exprel discrim_respects]) |
407 UN_equiv_class [OF equiv_exprel discrim_respects]) |
408 |
408 |