src/HOL/BNF/Examples/Process.thy
changeset 49510 ba50d204095e
parent 49509 163914705f8d
child 49546 69ee9f96c423
equal deleted inserted replaced
49509:163914705f8d 49510:ba50d204095e
       
     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