1 (*<*)theory CTL = Base:;(*>*)
3 subsection{*Computation Tree Logic --- CTL*};
6 The semantics of PDL only needs reflexive transitive closure.
7 Let us be adventurous and introduce a more expressive temporal operator.
9 @{text formula} by a new constructor
12 datatype formula = Atom atom
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}.
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)}";
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.}
36 consts valid :: "state \<Rightarrow> formula \<Rightarrow> bool" ("(_ \<Turnstile> _)" [80,80] 80);
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)"
45 "s \<Turnstile> AF f = (\<forall>p \<in> Paths s. \<exists>i. p i \<Turnstile> f)";
48 Model checking @{term AF} involves a function which
49 is just complicated enough to warrant a separate definition:
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}";
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}:
60 consts mc :: "formula \<Rightarrow> state set";
62 "mc(Atom a) = {s. a \<in> L s}"
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))";
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:
74 lemma mono_af: "mono(af A)";
75 apply(simp add: mono_def af_def);
79 lemma mono_ef: "mono(\<lambda>T. A \<union> M\<inverse> `` T)";
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);
88 apply(erule lfp_induct);
91 apply(blast intro: rtrancl_trans);
94 apply(erule converse_rtrancl_induct);
95 apply(rule ssubst[OF lfp_unfold[OF mono_ef]]);
97 apply(rule ssubst[OF lfp_unfold[OF mono_ef]]);
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
108 "lfp(af A) \<subseteq> {s. \<forall> p \<in> Paths s. \<exists> i. p i \<in> A}";
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}:
115 @{thm lfp_lowerbound[of _ "S",no_vars]} \hfill (@{thm[source]lfp_lowerbound})
117 The instance of the premise @{prop"f S \<subseteq> S"} is proved pointwise,
118 a decision that clarification takes for us:
120 apply(rule lfp_lowerbound);
121 apply(clarsimp simp add: af_def Paths_def);
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:
132 In the other case we set @{term t} to @{term"p 1"} and simplify matters:
135 apply(erule_tac x = "p 1" in allE);
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:
144 apply(erule_tac x = "\<lambda>i. p(i+1)" in allE);
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.
160 The one-step argument in the sketch above
161 is proved by a variant of contraposition:
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);
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.
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:
180 consts path :: "state \<Rightarrow> (state \<Rightarrow> bool) \<Rightarrow> (nat \<Rightarrow> state)";
183 "path s Q (Suc n) = (SOME t. (path s Q n,t) \<in> M \<and> Q t)";
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.
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:
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)";
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:
206 apply(subgoal_tac "\<exists>p. s = p 0 \<and> (\<forall>i. (p i,p(i+1)) \<in> M \<and> Q(p i))");
209 From this proposition the original goal follows easily:
212 apply(simp add:Paths_def, blast);
215 The new subgoal is proved by providing the witness @{term "path s Q"} for @{term p}:
218 apply(rule_tac x = "path s Q" in exI);
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}:
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:
244 apply(fast intro:someI2_ex);
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.
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:
264 apply(rule someI2_ex);
266 apply(rule someI2_ex);
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:
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}.
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)";
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);
289 apply(rule_tac x = "nat_rec s (\<lambda>n t. SOME u. (t,u)\<in>M \<and> Q u)" in exI);
294 apply(fast intro:someI2_ex);
296 apply(rule someI2_ex);
298 apply(rule someI2_ex);
304 At last we can prove the opposite direction of @{thm[source]AF_lemma1}:
307 theorem AF_lemma2: "{s. \<forall> p \<in> Paths s. \<exists> i. p i \<in> A} \<subseteq> lfp(af A)";
310 The proof is again pointwise and then by contraposition:
314 apply(erule contrapos_pp);
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:
323 apply(drule infinity_lemma);
326 @{subgoals[display,indent=0,margin=65]}
327 Both are solved automatically:
330 apply(auto dest:not_in_lfp_afD);
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
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:
343 theorem "mc f = {s. s \<Turnstile> f}";
345 apply(auto simp add: EF_lemma equalityI[OF AF_lemma1 AF_lemma2]);
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
356 consts until:: "state set \<Rightarrow> state set \<Rightarrow> state \<Rightarrow> state list \<Rightarrow> bool"
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)"
361 eusem :: "state set \<Rightarrow> state set \<Rightarrow> state set"
362 "eusem A B \<equiv> {s. \<exists>p. until A B s p}"(*>*)
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!
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))"}
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"}.
380 For more CTL exercises see, for example, Huth and Ryan \cite{Huth-Ryan-book}.
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)"
388 lemma "lfp(eufix A B) \<subseteq> eusem A B"
389 apply(rule lfp_lowerbound)
390 apply(clarsimp simp add:eusem_def eufix_def);
392 apply(rule_tac x = "[]" in exI);
395 apply(rule_tac x = "y#xc" in exI);
399 lemma mono_eufix: "mono(eufix A B)";
400 apply(simp add: mono_def eufix_def);
404 lemma "eusem A B \<subseteq> lfp(eufix A B)";
405 apply(clarsimp simp add:eusem_def);
407 apply(rule_tac x = x in spec);
409 apply(rule ssubst[OF lfp_unfold[OF mono_eufix]]);
410 apply(simp add:eufix_def);
412 apply(rule ssubst[OF lfp_unfold[OF mono_eufix]]);
413 apply(simp add:eufix_def);
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)}"
423 M_total: "\<exists>t. (s,t) \<in> M"
425 consts apath :: "state \<Rightarrow> (nat \<Rightarrow> state)"
428 "apath s (Suc i) = (SOME t. (apath s i,t) \<in> M)"
430 lemma [iff]: "apath s \<in> Paths s";
431 apply(simp add:Paths_def);
432 apply(blast intro: M_total[THEN someI_ex])
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"
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);
442 lemma "lfp(eufix A B) \<subseteq> eusem A B"
443 apply(rule lfp_lowerbound)
444 apply(clarsimp simp add:eusem_def eufix_def);
446 apply(rule_tac x = "apath x" in bexI);
447 apply(rule_tac x = 0 in exI);
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)
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.