|
1 (* Title: HOL/BNF/Examples/Process.thy |
|
2 Author: Andrei Popescu, TU Muenchen |
|
3 Copyright 2012 |
|
4 |
|
5 Processes. |
|
6 *) |
|
7 |
|
8 header {* Processes *} |
|
9 |
|
10 theory Process |
|
11 imports "../BNF" |
|
12 begin |
|
13 |
|
14 hide_fact (open) Quotient_Product.prod_rel_def |
|
15 |
|
16 codata 'a process = |
|
17 isAction: Action (prefOf: 'a) (contOf: "'a process") | |
|
18 isChoice: Choice (ch1Of: "'a process") (ch2Of: "'a process") |
|
19 |
|
20 (* Read: prefix of, continuation of, choice 1 of, choice 2 of *) |
|
21 |
|
22 section {* Customization *} |
|
23 |
|
24 subsection {* Basic properties *} |
|
25 |
|
26 declare |
|
27 pre_process_rel_def[simp] |
|
28 sum_rel_def[simp] |
|
29 prod_rel_def[simp] |
|
30 |
|
31 (* Constructors versus discriminators *) |
|
32 theorem isAction_isChoice: |
|
33 "isAction p \<or> isChoice p" |
|
34 by (rule process.disc_exhaust) auto |
|
35 |
|
36 theorem not_isAction_isChoice: "\<not> (isAction p \<and> isChoice p)" |
|
37 by (cases rule: process.exhaust[of p]) auto |
|
38 |
|
39 |
|
40 subsection{* Coinduction *} |
|
41 |
|
42 theorem process_coind[elim, consumes 1, case_names iss Action Choice, induct pred: "HOL.eq"]: |
|
43 assumes phi: "\<phi> p p'" and |
|
44 iss: "\<And>p p'. \<phi> p p' \<Longrightarrow> (isAction p \<longleftrightarrow> isAction p') \<and> (isChoice p \<longleftrightarrow> isChoice p')" and |
|
45 Act: "\<And> a a' p p'. \<phi> (Action a p) (Action a' p') \<Longrightarrow> a = a' \<and> \<phi> p p'" and |
|
46 Ch: "\<And> p q p' q'. \<phi> (Choice p q) (Choice p' q') \<Longrightarrow> \<phi> p p' \<and> \<phi> q q'" |
|
47 shows "p = p'" |
|
48 proof(intro mp[OF process.rel_coinduct, of \<phi>, OF _ phi], clarify) |
|
49 fix p p' assume \<phi>: "\<phi> p p'" |
|
50 show "pre_process_rel (op =) \<phi> (process_dtor p) (process_dtor p')" |
|
51 proof(cases rule: process.exhaust[of p]) |
|
52 case (Action a q) note p = Action |
|
53 hence "isAction p'" using iss[OF \<phi>] by (cases rule: process.exhaust[of p'], auto) |
|
54 then obtain a' q' where p': "p' = Action a' q'" by (cases rule: process.exhaust[of p'], auto) |
|
55 have 0: "a = a' \<and> \<phi> q q'" using Act[OF \<phi>[unfolded p p']] . |
|
56 have dtor: "process_dtor p = Inl (a,q)" "process_dtor p' = Inl (a',q')" |
|
57 unfolding p p' Action_def process.dtor_ctor by simp_all |
|
58 show ?thesis using 0 unfolding dtor by simp |
|
59 next |
|
60 case (Choice p1 p2) note p = Choice |
|
61 hence "isChoice p'" using iss[OF \<phi>] by (cases rule: process.exhaust[of p'], auto) |
|
62 then obtain p1' p2' where p': "p' = Choice p1' p2'" |
|
63 by (cases rule: process.exhaust[of p'], auto) |
|
64 have 0: "\<phi> p1 p1' \<and> \<phi> p2 p2'" using Ch[OF \<phi>[unfolded p p']] . |
|
65 have dtor: "process_dtor p = Inr (p1,p2)" "process_dtor p' = Inr (p1',p2')" |
|
66 unfolding p p' Choice_def process.dtor_ctor by simp_all |
|
67 show ?thesis using 0 unfolding dtor by simp |
|
68 qed |
|
69 qed |
|
70 |
|
71 (* Stronger coinduction, up to equality: *) |
|
72 theorem process_strong_coind[elim, consumes 1, case_names iss Action Choice]: |
|
73 assumes phi: "\<phi> p p'" and |
|
74 iss: "\<And>p p'. \<phi> p p' \<Longrightarrow> (isAction p \<longleftrightarrow> isAction p') \<and> (isChoice p \<longleftrightarrow> isChoice p')" and |
|
75 Act: "\<And> a a' p p'. \<phi> (Action a p) (Action a' p') \<Longrightarrow> a = a' \<and> (\<phi> p p' \<or> p = p')" and |
|
76 Ch: "\<And> p q p' q'. \<phi> (Choice p q) (Choice p' q') \<Longrightarrow> (\<phi> p p' \<or> p = p') \<and> (\<phi> q q' \<or> q = q')" |
|
77 shows "p = p'" |
|
78 proof(intro mp[OF process.rel_strong_coinduct, of \<phi>, OF _ phi], clarify) |
|
79 fix p p' assume \<phi>: "\<phi> p p'" |
|
80 show "pre_process_rel (op =) (\<lambda>a b. \<phi> a b \<or> a = b) (process_dtor p) (process_dtor p')" |
|
81 proof(cases rule: process.exhaust[of p]) |
|
82 case (Action a q) note p = Action |
|
83 hence "isAction p'" using iss[OF \<phi>] by (cases rule: process.exhaust[of p'], auto) |
|
84 then obtain a' q' where p': "p' = Action a' q'" by (cases rule: process.exhaust[of p'], auto) |
|
85 have 0: "a = a' \<and> (\<phi> q q' \<or> q = q')" using Act[OF \<phi>[unfolded p p']] . |
|
86 have dtor: "process_dtor p = Inl (a,q)" "process_dtor p' = Inl (a',q')" |
|
87 unfolding p p' Action_def process.dtor_ctor by simp_all |
|
88 show ?thesis using 0 unfolding dtor by simp |
|
89 next |
|
90 case (Choice p1 p2) note p = Choice |
|
91 hence "isChoice p'" using iss[OF \<phi>] by (cases rule: process.exhaust[of p'], auto) |
|
92 then obtain p1' p2' where p': "p' = Choice p1' p2'" |
|
93 by (cases rule: process.exhaust[of p'], auto) |
|
94 have 0: "(\<phi> p1 p1' \<or> p1 = p1') \<and> (\<phi> p2 p2' \<or> p2 = p2')" using Ch[OF \<phi>[unfolded p p']] . |
|
95 have dtor: "process_dtor p = Inr (p1,p2)" "process_dtor p' = Inr (p1',p2')" |
|
96 unfolding p p' Choice_def process.dtor_ctor by simp_all |
|
97 show ?thesis using 0 unfolding dtor by simp |
|
98 qed |
|
99 qed |
|
100 |
|
101 |
|
102 subsection {* Coiteration (unfold) *} |
|
103 |
|
104 |
|
105 section{* Coinductive definition of the notion of trace *} |
|
106 |
|
107 (* Say we have a type of streams: *) |
|
108 |
|
109 typedecl 'a stream |
|
110 |
|
111 consts Ccons :: "'a \<Rightarrow> 'a stream \<Rightarrow> 'a stream" |
|
112 |
|
113 (* Use the existing coinductive package (distinct from our |
|
114 new codatatype package, but highly compatible with it): *) |
|
115 |
|
116 coinductive trace where |
|
117 "trace p as \<Longrightarrow> trace (Action a p) (Ccons a as)" |
|
118 | |
|
119 "trace p as \<or> trace q as \<Longrightarrow> trace (Choice p q) as" |
|
120 |
|
121 |
|
122 section{* Examples of corecursive definitions: *} |
|
123 |
|
124 subsection{* Single-guard fixpoint definition *} |
|
125 |
|
126 definition |
|
127 "BX \<equiv> |
|
128 process_unfold |
|
129 (\<lambda> P. True) |
|
130 (\<lambda> P. ''a'') |
|
131 (\<lambda> P. P) |
|
132 undefined |
|
133 undefined |
|
134 ()" |
|
135 |
|
136 lemma BX: "BX = Action ''a'' BX" |
|
137 unfolding BX_def |
|
138 using process.unfolds(1)[of "\<lambda> P. True" "()" "\<lambda> P. ''a''" "\<lambda> P. P"] by simp |
|
139 |
|
140 |
|
141 subsection{* Multi-guard fixpoint definitions, simulated with auxiliary arguments *} |
|
142 |
|
143 datatype x_y_ax = x | y | ax |
|
144 |
|
145 definition "isA \<equiv> \<lambda> K. case K of x \<Rightarrow> False |y \<Rightarrow> True |ax \<Rightarrow> True" |
|
146 definition "pr \<equiv> \<lambda> K. case K of x \<Rightarrow> undefined |y \<Rightarrow> ''b'' |ax \<Rightarrow> ''a''" |
|
147 definition "co \<equiv> \<lambda> K. case K of x \<Rightarrow> undefined |y \<Rightarrow> x |ax \<Rightarrow> x" |
|
148 lemmas Action_defs = isA_def pr_def co_def |
|
149 |
|
150 definition "c1 \<equiv> \<lambda> K. case K of x \<Rightarrow> ax |y \<Rightarrow> undefined |ax \<Rightarrow> undefined" |
|
151 definition "c2 \<equiv> \<lambda> K. case K of x \<Rightarrow> y |y \<Rightarrow> undefined |ax \<Rightarrow> undefined" |
|
152 lemmas Choice_defs = c1_def c2_def |
|
153 |
|
154 definition "F \<equiv> process_unfold isA pr co c1 c2" |
|
155 definition "X = F x" definition "Y = F y" definition "AX = F ax" |
|
156 |
|
157 lemma X_Y_AX: "X = Choice AX Y" "Y = Action ''b'' X" "AX = Action ''a'' X" |
|
158 unfolding X_def Y_def AX_def F_def |
|
159 using process.unfolds(2)[of isA x "pr" co c1 c2] |
|
160 process.unfolds(1)[of isA y "pr" co c1 c2] |
|
161 process.unfolds(1)[of isA ax "pr" co c1 c2] |
|
162 unfolding Action_defs Choice_defs by simp_all |
|
163 |
|
164 (* end product: *) |
|
165 lemma X_AX: |
|
166 "X = Choice AX (Action ''b'' X)" |
|
167 "AX = Action ''a'' X" |
|
168 using X_Y_AX by simp_all |
|
169 |
|
170 |
|
171 |
|
172 section{* Case study: Multi-guard fixpoint definitions, without auxiliary arguments *} |
|
173 |
|
174 hide_const x y ax X Y AX |
|
175 |
|
176 (* Process terms *) |
|
177 datatype ('a,'pvar) process_term = |
|
178 VAR 'pvar | |
|
179 PROC "'a process" | |
|
180 ACT 'a "('a,'pvar) process_term" | CH "('a,'pvar) process_term" "('a,'pvar) process_term" |
|
181 |
|
182 (* below, sys represents a system of equations *) |
|
183 fun isACT where |
|
184 "isACT sys (VAR X) = |
|
185 (case sys X of ACT a T \<Rightarrow> True |PROC p \<Rightarrow> isAction p |_ \<Rightarrow> False)" |
|
186 | |
|
187 "isACT sys (PROC p) = isAction p" |
|
188 | |
|
189 "isACT sys (ACT a T) = True" |
|
190 | |
|
191 "isACT sys (CH T1 T2) = False" |
|
192 |
|
193 fun PREF where |
|
194 "PREF sys (VAR X) = |
|
195 (case sys X of ACT a T \<Rightarrow> a | PROC p \<Rightarrow> prefOf p)" |
|
196 | |
|
197 "PREF sys (PROC p) = prefOf p" |
|
198 | |
|
199 "PREF sys (ACT a T) = a" |
|
200 |
|
201 fun CONT where |
|
202 "CONT sys (VAR X) = |
|
203 (case sys X of ACT a T \<Rightarrow> T | PROC p \<Rightarrow> PROC (contOf p))" |
|
204 | |
|
205 "CONT sys (PROC p) = PROC (contOf p)" |
|
206 | |
|
207 "CONT sys (ACT a T) = T" |
|
208 |
|
209 fun CH1 where |
|
210 "CH1 sys (VAR X) = |
|
211 (case sys X of CH T1 T2 \<Rightarrow> T1 |PROC p \<Rightarrow> PROC (ch1Of p))" |
|
212 | |
|
213 "CH1 sys (PROC p) = PROC (ch1Of p)" |
|
214 | |
|
215 "CH1 sys (CH T1 T2) = T1" |
|
216 |
|
217 fun CH2 where |
|
218 "CH2 sys (VAR X) = |
|
219 (case sys X of CH T1 T2 \<Rightarrow> T2 |PROC p \<Rightarrow> PROC (ch2Of p))" |
|
220 | |
|
221 "CH2 sys (PROC p) = PROC (ch2Of p)" |
|
222 | |
|
223 "CH2 sys (CH T1 T2) = T2" |
|
224 |
|
225 definition "guarded sys \<equiv> \<forall> X Y. sys X \<noteq> VAR Y" |
|
226 |
|
227 definition |
|
228 "solution sys \<equiv> |
|
229 process_unfold |
|
230 (isACT sys) |
|
231 (PREF sys) |
|
232 (CONT sys) |
|
233 (CH1 sys) |
|
234 (CH2 sys)" |
|
235 |
|
236 lemma solution_Action: |
|
237 assumes "isACT sys T" |
|
238 shows "solution sys T = Action (PREF sys T) (solution sys (CONT sys T))" |
|
239 unfolding solution_def |
|
240 using process.unfolds(1)[of "isACT sys" T "PREF sys" "CONT sys" "CH1 sys" "CH2 sys"] |
|
241 assms by simp |
|
242 |
|
243 lemma solution_Choice: |
|
244 assumes "\<not> isACT sys T" |
|
245 shows "solution sys T = Choice (solution sys (CH1 sys T)) (solution sys (CH2 sys T))" |
|
246 unfolding solution_def |
|
247 using process.unfolds(2)[of "isACT sys" T "PREF sys" "CONT sys" "CH1 sys" "CH2 sys"] |
|
248 assms by simp |
|
249 |
|
250 lemma isACT_VAR: |
|
251 assumes g: "guarded sys" |
|
252 shows "isACT sys (VAR X) \<longleftrightarrow> isACT sys (sys X)" |
|
253 using g unfolding guarded_def by (cases "sys X") auto |
|
254 |
|
255 lemma solution_VAR: |
|
256 assumes g: "guarded sys" |
|
257 shows "solution sys (VAR X) = solution sys (sys X)" |
|
258 proof(cases "isACT sys (VAR X)") |
|
259 case True |
|
260 hence T: "isACT sys (sys X)" unfolding isACT_VAR[OF g] . |
|
261 show ?thesis |
|
262 unfolding solution_Action[OF T] using solution_Action[of sys "VAR X"] True g |
|
263 unfolding guarded_def by (cases "sys X", auto) |
|
264 next |
|
265 case False note FFalse = False |
|
266 hence TT: "\<not> isACT sys (sys X)" unfolding isACT_VAR[OF g] . |
|
267 show ?thesis |
|
268 unfolding solution_Choice[OF TT] using solution_Choice[of sys "VAR X"] FFalse g |
|
269 unfolding guarded_def by (cases "sys X", auto) |
|
270 qed |
|
271 |
|
272 lemma solution_PROC[simp]: |
|
273 "solution sys (PROC p) = p" |
|
274 proof- |
|
275 {fix q assume "q = solution sys (PROC p)" |
|
276 hence "p = q" |
|
277 proof(induct rule: process_coind) |
|
278 case (iss p p') |
|
279 from isAction_isChoice[of p] show ?case |
|
280 proof |
|
281 assume p: "isAction p" |
|
282 hence 0: "isACT sys (PROC p)" by simp |
|
283 thus ?thesis using iss not_isAction_isChoice |
|
284 unfolding solution_Action[OF 0] by auto |
|
285 next |
|
286 assume "isChoice p" |
|
287 hence 0: "\<not> isACT sys (PROC p)" |
|
288 using not_isAction_isChoice by auto |
|
289 thus ?thesis using iss isAction_isChoice |
|
290 unfolding solution_Choice[OF 0] by auto |
|
291 qed |
|
292 next |
|
293 case (Action a a' p p') |
|
294 hence 0: "isACT sys (PROC (Action a p))" by simp |
|
295 show ?case using Action unfolding solution_Action[OF 0] by simp |
|
296 next |
|
297 case (Choice p q p' q') |
|
298 hence 0: "\<not> isACT sys (PROC (Choice p q))" using not_isAction_isChoice by auto |
|
299 show ?case using Choice unfolding solution_Choice[OF 0] by simp |
|
300 qed |
|
301 } |
|
302 thus ?thesis by metis |
|
303 qed |
|
304 |
|
305 lemma solution_ACT[simp]: |
|
306 "solution sys (ACT a T) = Action a (solution sys T)" |
|
307 by (metis CONT.simps(3) PREF.simps(3) isACT.simps(3) solution_Action) |
|
308 |
|
309 lemma solution_CH[simp]: |
|
310 "solution sys (CH T1 T2) = Choice (solution sys T1) (solution sys T2)" |
|
311 by (metis CH1.simps(3) CH2.simps(3) isACT.simps(4) solution_Choice) |
|
312 |
|
313 |
|
314 (* Example: *) |
|
315 |
|
316 fun sys where |
|
317 "sys 0 = CH (VAR (Suc 0)) (ACT ''b'' (VAR 0))" |
|
318 | |
|
319 "sys (Suc 0) = ACT ''a'' (VAR 0)" |
|
320 | (* dummy guarded term for variables outside the system: *) |
|
321 "sys X = ACT ''a'' (VAR 0)" |
|
322 |
|
323 lemma guarded_sys: |
|
324 "guarded sys" |
|
325 unfolding guarded_def proof (intro allI) |
|
326 fix X Y show "sys X \<noteq> VAR Y" by (cases X, simp, case_tac nat, auto) |
|
327 qed |
|
328 |
|
329 (* the actual processes: *) |
|
330 definition "x \<equiv> solution sys (VAR 0)" |
|
331 definition "ax \<equiv> solution sys (VAR (Suc 0))" |
|
332 |
|
333 (* end product: *) |
|
334 lemma x_ax: |
|
335 "x = Choice ax (Action ''b'' x)" |
|
336 "ax = Action ''a'' x" |
|
337 unfolding x_def ax_def by (subst solution_VAR[OF guarded_sys], simp)+ |
|
338 |
|
339 |
|
340 (* Thanks to the inclusion of processes as process terms, one can |
|
341 also consider parametrized systems of equations---here, x is a (semantic) |
|
342 process parameter: *) |
|
343 |
|
344 fun sys' where |
|
345 "sys' 0 = CH (PROC x) (ACT ''b'' (VAR 0))" |
|
346 | |
|
347 "sys' (Suc 0) = CH (ACT ''a'' (VAR 0)) (PROC x)" |
|
348 | (* dummy guarded term : *) |
|
349 "sys' X = ACT ''a'' (VAR 0)" |
|
350 |
|
351 lemma guarded_sys': |
|
352 "guarded sys'" |
|
353 unfolding guarded_def proof (intro allI) |
|
354 fix X Y show "sys' X \<noteq> VAR Y" by (cases X, simp, case_tac nat, auto) |
|
355 qed |
|
356 |
|
357 (* the actual processes: *) |
|
358 definition "y \<equiv> solution sys' (VAR 0)" |
|
359 definition "ay \<equiv> solution sys' (VAR (Suc 0))" |
|
360 |
|
361 (* end product: *) |
|
362 lemma y_ay: |
|
363 "y = Choice x (Action ''b'' y)" |
|
364 "ay = Choice (Action ''a'' y) x" |
|
365 unfolding y_def ay_def by (subst solution_VAR[OF guarded_sys'], simp)+ |
|
366 |
|
367 end |