doc-src/TutorialI/CTL/CTL.thy
author nipkow
Mon, 29 Jan 2001 22:25:45 +0100
changeset 10995 ef0b521698b7
parent 10983 59961d32b1ae
child 11149 e258b536a137
permissions -rw-r--r--
*** empty log message ***
     1 (*<*)theory CTL = Base:;(*>*)
     2 
     3 subsection{*Computation Tree Logic --- CTL*};
     4 
     5 text{*\label{sec:CTL}
     6 The semantics of PDL only needs reflexive transitive closure.
     7 Let us be adventurous and introduce a more expressive temporal operator.
     8 We extend the datatype
     9 @{text formula} by a new constructor
    10 *};
    11 (*<*)
    12 datatype formula = Atom atom
    13                   | Neg formula
    14                   | And formula formula
    15                   | AX formula
    16                   | EF formula(*>*)
    17                   | AF formula;
    18 
    19 text{*\noindent
    20 which stands for ``\emph{A}lways in the \emph{F}uture'':
    21 on all infinite paths, at some point the formula holds.
    22 Formalizing the notion of an infinite path is easy
    23 in HOL: it is simply a function from @{typ nat} to @{typ state}.
    24 *};
    25 
    26 constdefs Paths :: "state \<Rightarrow> (nat \<Rightarrow> state)set"
    27          "Paths s \<equiv> {p. s = p 0 \<and> (\<forall>i. (p i, p(i+1)) \<in> M)}";
    28 
    29 text{*\noindent
    30 This definition allows a very succinct statement of the semantics of @{term AF}:
    31 \footnote{Do not be misled: neither datatypes nor recursive functions can be
    32 extended by new constructors or equations. This is just a trick of the
    33 presentation. In reality one has to define a new datatype and a new function.}
    34 *};
    35 (*<*)
    36 consts valid :: "state \<Rightarrow> formula \<Rightarrow> bool" ("(_ \<Turnstile> _)" [80,80] 80);
    37 
    38 primrec
    39 "s \<Turnstile> Atom a  =  (a \<in> L s)"
    40 "s \<Turnstile> Neg f   = (~(s \<Turnstile> f))"
    41 "s \<Turnstile> And f g = (s \<Turnstile> f \<and> s \<Turnstile> g)"
    42 "s \<Turnstile> AX f    = (\<forall>t. (s,t) \<in> M \<longrightarrow> t \<Turnstile> f)"
    43 "s \<Turnstile> EF f    = (\<exists>t. (s,t) \<in> M\<^sup>* \<and> t \<Turnstile> f)"
    44 (*>*)
    45 "s \<Turnstile> AF f    = (\<forall>p \<in> Paths s. \<exists>i. p i \<Turnstile> f)";
    46 
    47 text{*\noindent
    48 Model checking @{term AF} involves a function which
    49 is just complicated enough to warrant a separate definition:
    50 *};
    51 
    52 constdefs af :: "state set \<Rightarrow> state set \<Rightarrow> state set"
    53          "af A T \<equiv> A \<union> {s. \<forall>t. (s, t) \<in> M \<longrightarrow> t \<in> T}";
    54 
    55 text{*\noindent
    56 Now we define @{term "mc(AF f)"} as the least set @{term T} that includes
    57 @{term"mc f"} and all states all of whose direct successors are in @{term T}:
    58 *};
    59 (*<*)
    60 consts mc :: "formula \<Rightarrow> state set";
    61 primrec
    62 "mc(Atom a)  = {s. a \<in> L s}"
    63 "mc(Neg f)   = -mc f"
    64 "mc(And f g) = mc f \<inter> mc g"
    65 "mc(AX f)    = {s. \<forall>t. (s,t) \<in> M  \<longrightarrow> t \<in> mc f}"
    66 "mc(EF f)    = lfp(\<lambda>T. mc f \<union> M\<inverse> `` T)"(*>*)
    67 "mc(AF f)    = lfp(af(mc f))";
    68 
    69 text{*\noindent
    70 Because @{term af} is monotone in its second argument (and also its first, but
    71 that is irrelevant), @{term"af A"} has a least fixed point:
    72 *};
    73 
    74 lemma mono_af: "mono(af A)";
    75 apply(simp add: mono_def af_def);
    76 apply blast;
    77 done
    78 (*<*)
    79 lemma mono_ef: "mono(\<lambda>T. A \<union> M\<inverse> `` T)";
    80 apply(rule monoI);
    81 by(blast);
    82 
    83 lemma EF_lemma:
    84   "lfp(\<lambda>T. A \<union> M\<inverse> `` T) = {s. \<exists>t. (s,t) \<in> M\<^sup>* \<and> t \<in> A}";
    85 apply(rule equalityI);
    86  apply(rule subsetI);
    87  apply(simp);
    88  apply(erule lfp_induct);
    89   apply(rule mono_ef);
    90  apply(simp);
    91  apply(blast intro: rtrancl_trans);
    92 apply(rule subsetI);
    93 apply(simp, clarify);
    94 apply(erule converse_rtrancl_induct);
    95  apply(rule ssubst[OF lfp_unfold[OF mono_ef]]);
    96  apply(blast);
    97 apply(rule ssubst[OF lfp_unfold[OF mono_ef]]);
    98 by(blast);
    99 (*>*)
   100 text{*
   101 All we need to prove now is  @{prop"mc(AF f) = {s. s \<Turnstile> AF f}"}, which states
   102 that @{term mc} and @{text"\<Turnstile>"} agree for @{term AF}\@.
   103 This time we prove the two inclusions separately, starting
   104 with the easy one:
   105 *};
   106 
   107 theorem AF_lemma1:
   108   "lfp(af A) \<subseteq> {s. \<forall> p \<in> Paths s. \<exists> i. p i \<in> A}";
   109 
   110 txt{*\noindent
   111 In contrast to the analogous property for @{term EF}, and just
   112 for a change, we do not use fixed point induction but a weaker theorem,
   113 also known in the literature (after David Park) as \emph{Park-induction}:
   114 \begin{center}
   115 @{thm lfp_lowerbound[of _ "S",no_vars]} \hfill (@{thm[source]lfp_lowerbound})
   116 \end{center}
   117 The instance of the premise @{prop"f S \<subseteq> S"} is proved pointwise,
   118 a decision that clarification takes for us:
   119 *};
   120 apply(rule lfp_lowerbound);
   121 apply(clarsimp simp add: af_def Paths_def);
   122 
   123 txt{*
   124 @{subgoals[display,indent=0,margin=70,goals_limit=1]}
   125 Now we eliminate the disjunction. The case @{prop"p 0 \<in> A"} is trivial:
   126 *};
   127 
   128 apply(erule disjE);
   129  apply(blast);
   130 
   131 txt{*\noindent
   132 In the other case we set @{term t} to @{term"p 1"} and simplify matters:
   133 *};
   134 
   135 apply(erule_tac x = "p 1" in allE);
   136 apply(clarsimp);
   137 
   138 txt{*
   139 @{subgoals[display,indent=0,margin=70,goals_limit=1]}
   140 It merely remains to set @{term pa} to @{term"\<lambda>i. p(i+1)"}, i.e.\ @{term p} without its
   141 first element. The rest is practically automatic:
   142 *};
   143 
   144 apply(erule_tac x = "\<lambda>i. p(i+1)" in allE);
   145 apply simp;
   146 apply blast;
   147 done;
   148 
   149 
   150 text{*
   151 The opposite inclusion is proved by contradiction: if some state
   152 @{term s} is not in @{term"lfp(af A)"}, then we can construct an
   153 infinite @{term A}-avoiding path starting from @{term s}. The reason is
   154 that by unfolding @{term lfp} we find that if @{term s} is not in
   155 @{term"lfp(af A)"}, then @{term s} is not in @{term A} and there is a
   156 direct successor of @{term s} that is again not in \mbox{@{term"lfp(af
   157 A)"}}. Iterating this argument yields the promised infinite
   158 @{term A}-avoiding path. Let us formalize this sketch.
   159 
   160 The one-step argument in the sketch above
   161 is proved by a variant of contraposition:
   162 *};
   163 
   164 lemma not_in_lfp_afD:
   165  "s \<notin> lfp(af A) \<Longrightarrow> s \<notin> A \<and> (\<exists> t. (s,t) \<in> M \<and> t \<notin> lfp(af A))";
   166 apply(erule contrapos_np);
   167 apply(rule ssubst[OF lfp_unfold[OF mono_af]]);
   168 apply(simp add:af_def);
   169 done;
   170 
   171 text{*\noindent
   172 We assume the negation of the conclusion and prove @{term"s : lfp(af A)"}.
   173 Unfolding @{term lfp} once and
   174 simplifying with the definition of @{term af} finishes the proof.
   175 
   176 Now we iterate this process. The following construction of the desired
   177 path is parameterized by a predicate @{term Q} that should hold along the path:
   178 *};
   179 
   180 consts path :: "state \<Rightarrow> (state \<Rightarrow> bool) \<Rightarrow> (nat \<Rightarrow> state)";
   181 primrec
   182 "path s Q 0 = s"
   183 "path s Q (Suc n) = (SOME t. (path s Q n,t) \<in> M \<and> Q t)";
   184 
   185 text{*\noindent
   186 Element @{term"n+1"} on this path is some arbitrary successor
   187 @{term t} of element @{term n} such that @{term"Q t"} holds.  Remember that @{text"SOME t. R t"}
   188 is some arbitrary but fixed @{term t} such that @{prop"R t"} holds (see \S\ref{sec:SOME}). Of
   189 course, such a @{term t} need not exist, but that is of no
   190 concern to us since we will only use @{term path} when a
   191 suitable @{term t} does exist.
   192 
   193 Let us show that if each state @{term s} that satisfies @{term Q}
   194 has a successor that again satisfies @{term Q}, then there exists an infinite @{term Q}-path:
   195 *};
   196 
   197 lemma infinity_lemma:
   198   "\<lbrakk> Q s; \<forall>s. Q s \<longrightarrow> (\<exists> t. (s,t) \<in> M \<and> Q t) \<rbrakk> \<Longrightarrow>
   199    \<exists>p\<in>Paths s. \<forall>i. Q(p i)";
   200 
   201 txt{*\noindent
   202 First we rephrase the conclusion slightly because we need to prove simultaneously
   203 both the path property and the fact that @{term Q} holds:
   204 *};
   205 
   206 apply(subgoal_tac "\<exists>p. s = p 0 \<and> (\<forall>i. (p i,p(i+1)) \<in> M \<and> Q(p i))");
   207 
   208 txt{*\noindent
   209 From this proposition the original goal follows easily:
   210 *};
   211 
   212  apply(simp add:Paths_def, blast);
   213 
   214 txt{*\noindent
   215 The new subgoal is proved by providing the witness @{term "path s Q"} for @{term p}:
   216 *};
   217 
   218 apply(rule_tac x = "path s Q" in exI);
   219 apply(clarsimp);
   220 
   221 txt{*\noindent
   222 After simplification and clarification, the subgoal has the following form
   223 @{subgoals[display,indent=0,margin=70,goals_limit=1]}
   224 and invites a proof by induction on @{term i}:
   225 *};
   226 
   227 apply(induct_tac i);
   228  apply(simp);
   229 
   230 txt{*\noindent
   231 After simplification, the base case boils down to
   232 @{subgoals[display,indent=0,margin=70,goals_limit=1]}
   233 The conclusion looks exceedingly trivial: after all, @{term t} is chosen such that @{prop"(s,t):M"}
   234 holds. However, we first have to show that such a @{term t} actually exists! This reasoning
   235 is embodied in the theorem @{thm[source]someI2_ex}:
   236 @{thm[display,eta_contract=false]someI2_ex}
   237 When we apply this theorem as an introduction rule, @{text"?P x"} becomes
   238 @{prop"(s, x) : M & Q x"} and @{text"?Q x"} becomes @{prop"(s,x) : M"} and we have to prove
   239 two subgoals: @{prop"EX a. (s, a) : M & Q a"}, which follows from the assumptions, and
   240 @{prop"(s, x) : M & Q x ==> (s,x) : M"}, which is trivial. Thus it is not surprising that
   241 @{text fast} can prove the base case quickly:
   242 *};
   243 
   244  apply(fast intro:someI2_ex);
   245 
   246 txt{*\noindent
   247 What is worth noting here is that we have used @{text fast} rather than
   248 @{text blast}.  The reason is that @{text blast} would fail because it cannot
   249 cope with @{thm[source]someI2_ex}: unifying its conclusion with the current
   250 subgoal is nontrivial because of the nested schematic variables. For
   251 efficiency reasons @{text blast} does not even attempt such unifications.
   252 Although @{text fast} can in principle cope with complicated unification
   253 problems, in practice the number of unifiers arising is often prohibitive and
   254 the offending rule may need to be applied explicitly rather than
   255 automatically. This is what happens in the step case.
   256 
   257 The induction step is similar, but more involved, because now we face nested
   258 occurrences of @{text SOME}. As a result, @{text fast} is no longer able to
   259 solve the subgoal and we apply @{thm[source]someI2_ex} by hand.  We merely
   260 show the proof commands but do not describe the details:
   261 *};
   262 
   263 apply(simp);
   264 apply(rule someI2_ex);
   265  apply(blast);
   266 apply(rule someI2_ex);
   267  apply(blast);
   268 apply(blast);
   269 done;
   270 
   271 text{*
   272 Function @{term path} has fulfilled its purpose now and can be forgotten.
   273 It was merely defined to provide the witness in the proof of the
   274 @{thm[source]infinity_lemma}. Aficionados of minimal proofs might like to know
   275 that we could have given the witness without having to define a new function:
   276 the term
   277 @{term[display]"nat_rec s (\<lambda>n t. SOME u. (t,u)\<in>M \<and> Q u)"}
   278 is extensionally equal to @{term"path s Q"},
   279 where @{term nat_rec} is the predefined primitive recursor on @{typ nat}.
   280 *};
   281 (*<*)
   282 lemma infinity_lemma:
   283 "\<lbrakk> Q s; \<forall> s. Q s \<longrightarrow> (\<exists> t. (s,t)\<in>M \<and> Q t) \<rbrakk> \<Longrightarrow>
   284  \<exists> p\<in>Paths s. \<forall> i. Q(p i)";
   285 apply(subgoal_tac
   286  "\<exists> p. s = p 0 \<and> (\<forall> i. (p i,p(Suc i))\<in>M \<and> Q(p i))");
   287  apply(simp add:Paths_def);
   288  apply(blast);
   289 apply(rule_tac x = "nat_rec s (\<lambda>n t. SOME u. (t,u)\<in>M \<and> Q u)" in exI);
   290 apply(simp);
   291 apply(intro strip);
   292 apply(induct_tac i);
   293  apply(simp);
   294  apply(fast intro:someI2_ex);
   295 apply(simp);
   296 apply(rule someI2_ex);
   297  apply(blast);
   298 apply(rule someI2_ex);
   299  apply(blast);
   300 by(blast);
   301 (*>*)
   302 
   303 text{*
   304 At last we can prove the opposite direction of @{thm[source]AF_lemma1}:
   305 *};
   306 
   307 theorem AF_lemma2: "{s. \<forall> p \<in> Paths s. \<exists> i. p i \<in> A} \<subseteq> lfp(af A)";
   308 
   309 txt{*\noindent
   310 The proof is again pointwise and then by contraposition:
   311 *};
   312 
   313 apply(rule subsetI);
   314 apply(erule contrapos_pp);
   315 apply simp;
   316 
   317 txt{*
   318 @{subgoals[display,indent=0,goals_limit=1]}
   319 Applying the @{thm[source]infinity_lemma} as a destruction rule leaves two subgoals, the second
   320 premise of @{thm[source]infinity_lemma} and the original subgoal:
   321 *};
   322 
   323 apply(drule infinity_lemma);
   324 
   325 txt{*
   326 @{subgoals[display,indent=0,margin=65]}
   327 Both are solved automatically:
   328 *};
   329 
   330  apply(auto dest:not_in_lfp_afD);
   331 done;
   332 
   333 text{*
   334 If you find these proofs too complicated, we recommend that you read
   335 \S\ref{sec:CTL-revisited}, where we show how inductive definitions lead to
   336 simpler arguments.
   337 
   338 The main theorem is proved as for PDL, except that we also derive the
   339 necessary equality @{text"lfp(af A) = ..."} by combining
   340 @{thm[source]AF_lemma1} and @{thm[source]AF_lemma2} on the spot:
   341 *}
   342 
   343 theorem "mc f = {s. s \<Turnstile> f}";
   344 apply(induct_tac f);
   345 apply(auto simp add: EF_lemma equalityI[OF AF_lemma1 AF_lemma2]);
   346 done
   347 
   348 text{*
   349 
   350 The language defined above is not quite CTL\@. The latter also includes an
   351 until-operator @{term"EU f g"} with semantics ``there \emph{E}xists a path
   352 where @{term f} is true \emph{U}ntil @{term g} becomes true''. With the help
   353 of an auxiliary function
   354 *}
   355 
   356 consts until:: "state set \<Rightarrow> state set \<Rightarrow> state \<Rightarrow> state list \<Rightarrow> bool"
   357 primrec
   358 "until A B s []    = (s \<in> B)"
   359 "until A B s (t#p) = (s \<in> A \<and> (s,t) \<in> M \<and> until A B t p)"
   360 (*<*)constdefs
   361  eusem :: "state set \<Rightarrow> state set \<Rightarrow> state set"
   362 "eusem A B \<equiv> {s. \<exists>p. until A B s p}"(*>*)
   363 
   364 text{*\noindent
   365 the semantics of @{term EU} is straightforward:
   366 @{prop[display]"s \<Turnstile> EU f g = (\<exists>p. until {t. t \<Turnstile> f} {t. t \<Turnstile> g} s p)"}
   367 Note that @{term EU} is not definable in terms of the other operators!
   368 
   369 Model checking @{term EU} is again a least fixed point construction:
   370 @{text[display]"mc(EU f g) = lfp(\<lambda>T. mc g \<union> mc f \<inter> (M\<inverse> `` T))"}
   371 
   372 \begin{exercise}
   373 Extend the datatype of formulae by the above until operator
   374 and prove the equivalence between semantics and model checking, i.e.\ that
   375 @{prop[display]"mc(EU f g) = {s. s \<Turnstile> EU f g}"}
   376 %For readability you may want to annotate {term EU} with its customary syntax
   377 %{text[display]"| EU formula formula    E[_ U _]"}
   378 %which enables you to read and write {text"E[f U g]"} instead of {term"EU f g"}.
   379 \end{exercise}
   380 For more CTL exercises see, for example, Huth and Ryan \cite{Huth-Ryan-book}.
   381 *}
   382 
   383 (*<*)
   384 constdefs
   385  eufix :: "state set \<Rightarrow> state set \<Rightarrow> state set \<Rightarrow> state set"
   386 "eufix A B T \<equiv> B \<union> A \<inter> (M\<inverse> `` T)"
   387 
   388 lemma "lfp(eufix A B) \<subseteq> eusem A B"
   389 apply(rule lfp_lowerbound)
   390 apply(clarsimp simp add:eusem_def eufix_def);
   391 apply(erule disjE);
   392  apply(rule_tac x = "[]" in exI);
   393  apply simp
   394 apply(clarsimp);
   395 apply(rule_tac x = "y#xc" in exI);
   396 apply simp;
   397 done
   398 
   399 lemma mono_eufix: "mono(eufix A B)";
   400 apply(simp add: mono_def eufix_def);
   401 apply blast;
   402 done
   403 
   404 lemma "eusem A B \<subseteq> lfp(eufix A B)";
   405 apply(clarsimp simp add:eusem_def);
   406 apply(erule rev_mp);
   407 apply(rule_tac x = x in spec);
   408 apply(induct_tac p);
   409  apply(rule ssubst[OF lfp_unfold[OF mono_eufix]]);
   410  apply(simp add:eufix_def);
   411 apply(clarsimp);
   412 apply(rule ssubst[OF lfp_unfold[OF mono_eufix]]);
   413 apply(simp add:eufix_def);
   414 apply blast;
   415 done
   416 
   417 (*
   418 constdefs
   419  eusem :: "state set \<Rightarrow> state set \<Rightarrow> state set"
   420 "eusem A B \<equiv> {s. \<exists>p\<in>Paths s. \<exists>j. p j \<in> B \<and> (\<forall>i < j. p i \<in> A)}"
   421 
   422 axioms
   423 M_total: "\<exists>t. (s,t) \<in> M"
   424 
   425 consts apath :: "state \<Rightarrow> (nat \<Rightarrow> state)"
   426 primrec
   427 "apath s 0 = s"
   428 "apath s (Suc i) = (SOME t. (apath s i,t) \<in> M)"
   429 
   430 lemma [iff]: "apath s \<in> Paths s";
   431 apply(simp add:Paths_def);
   432 apply(blast intro: M_total[THEN someI_ex])
   433 done
   434 
   435 constdefs
   436  pcons :: "state \<Rightarrow> (nat \<Rightarrow> state) \<Rightarrow> (nat \<Rightarrow> state)"
   437 "pcons s p == \<lambda>i. case i of 0 \<Rightarrow> s | Suc j \<Rightarrow> p j"
   438 
   439 lemma pcons_PathI: "[| (s,t) : M; p \<in> Paths t |] ==> pcons s p \<in> Paths s";
   440 by(simp add:Paths_def pcons_def split:nat.split);
   441 
   442 lemma "lfp(eufix A B) \<subseteq> eusem A B"
   443 apply(rule lfp_lowerbound)
   444 apply(clarsimp simp add:eusem_def eufix_def);
   445 apply(erule disjE);
   446  apply(rule_tac x = "apath x" in bexI);
   447   apply(rule_tac x = 0 in exI);
   448   apply simp;
   449  apply simp;
   450 apply(clarify);
   451 apply(rule_tac x = "pcons xb p" in bexI);
   452  apply(rule_tac x = "j+1" in exI);
   453  apply (simp add:pcons_def split:nat.split);
   454 apply (simp add:pcons_PathI)
   455 done
   456 *)
   457 (*>*)
   458 text{*
   459 Let us close this section with a few words about the executability of our model checkers.
   460 It is clear that if all sets are finite, they can be represented as lists and the usual
   461 set operations are easily implemented. Only @{term lfp} requires a little thought.
   462 Fortunately, the HOL Library%
   463 \footnote{See theory \isa{While_Combinator}.}
   464 provides a theorem stating that 
   465 in the case of finite sets and a monotone function~@{term F},
   466 the value of \mbox{@{term"lfp F"}} can be computed by iterated application of @{term F} to~@{term"{}"} until
   467 a fixed point is reached. It is actually possible to generate executable functional programs
   468 from HOL definitions, but that is beyond the scope of the tutorial.
   469 *}
   470 (*<*)end(*>*)