1 (* Title: ZF/Fixedpt.thy
2 Author: Lawrence C Paulson, Cambridge University Computer Laboratory
3 Copyright 1992 University of Cambridge
6 header{*Least and Greatest Fixed Points; the Knaster-Tarski Theorem*}
8 theory Fixedpt imports equalities begin
11 (*monotone operator from Pow(D) to itself*)
12 bnd_mono :: "[i,i=>i]=>o" where
13 "bnd_mono(D,h) == h(D)<=D & (ALL W X. W<=X --> X<=D --> h(W) <= h(X))"
16 lfp :: "[i,i=>i]=>i" where
17 "lfp(D,h) == Inter({X: Pow(D). h(X) <= X})"
20 gfp :: "[i,i=>i]=>i" where
21 "gfp(D,h) == Union({X: Pow(D). X <= h(X)})"
23 text{*The theorem is proved in the lattice of subsets of @{term D},
24 namely @{term "Pow(D)"}, with Inter as the greatest lower bound.*}
26 subsection{*Monotone Operators*}
30 !!W X. [| W<=D; X<=D; W<=X |] ==> h(W) <= h(X)
32 by (unfold bnd_mono_def, clarify, blast)
34 lemma bnd_monoD1: "bnd_mono(D,h) ==> h(D) <= D"
35 apply (unfold bnd_mono_def)
36 apply (erule conjunct1)
39 lemma bnd_monoD2: "[| bnd_mono(D,h); W<=X; X<=D |] ==> h(W) <= h(X)"
40 by (unfold bnd_mono_def, blast)
42 lemma bnd_mono_subset:
43 "[| bnd_mono(D,h); X<=D |] ==> h(X) <= D"
44 by (unfold bnd_mono_def, clarify, blast)
47 "[| bnd_mono(D,h); A <= D; B <= D |] ==> h(A) Un h(B) <= h(A Un B)"
48 apply (unfold bnd_mono_def)
49 apply (rule Un_least, blast+)
54 "[| bnd_mono(D,h); \<forall>i\<in>I. A(i) <= D |]
55 ==> (\<Union>i\<in>I. h(A(i))) <= h((\<Union>i\<in>I. A(i)))"
56 apply (unfold bnd_mono_def)
59 apply (drule_tac x="A(i)" in spec)
60 apply (drule_tac x="(\<Union>i\<in>I. A(i))" in spec)
66 "[| bnd_mono(D,h); A <= D; B <= D |] ==> h(A Int B) <= h(A) Int h(B)"
67 apply (rule Int_greatest)
68 apply (erule bnd_monoD2, rule Int_lower1, assumption)
69 apply (erule bnd_monoD2, rule Int_lower2, assumption)
72 subsection{*Proof of Knaster-Tarski Theorem using @{term lfp}*}
74 (*lfp is contained in each pre-fixedpoint*)
76 "[| h(A) <= A; A<=D |] ==> lfp(D,h) <= A"
77 by (unfold lfp_def, blast)
79 (*Unfolding the defn of Inter dispenses with the premise bnd_mono(D,h)!*)
80 lemma lfp_subset: "lfp(D,h) <= D"
81 by (unfold lfp_def Inter_def, blast)
83 (*Used in datatype package*)
84 lemma def_lfp_subset: "A == lfp(D,h) ==> A <= D"
86 apply (rule lfp_subset)
90 "[| h(D) <= D; !!X. [| h(X) <= X; X<=D |] ==> A<=X |] ==> A <= lfp(D,h)"
91 by (unfold lfp_def, blast)
94 "[| bnd_mono(D,h); h(A)<=A; A<=D |] ==> h(lfp(D,h)) <= A"
95 apply (erule bnd_monoD2 [THEN subset_trans])
96 apply (rule lfp_lowerbound, assumption+)
99 lemma lfp_lemma2: "bnd_mono(D,h) ==> h(lfp(D,h)) <= lfp(D,h)"
100 apply (rule bnd_monoD1 [THEN lfp_greatest])
101 apply (rule_tac [2] lfp_lemma1)
106 "bnd_mono(D,h) ==> lfp(D,h) <= h(lfp(D,h))"
107 apply (rule lfp_lowerbound)
108 apply (rule bnd_monoD2, assumption)
109 apply (rule lfp_lemma2, assumption)
110 apply (erule_tac [2] bnd_mono_subset)
111 apply (rule lfp_subset)+
114 lemma lfp_unfold: "bnd_mono(D,h) ==> lfp(D,h) = h(lfp(D,h))"
115 apply (rule equalityI)
116 apply (erule lfp_lemma3)
117 apply (erule lfp_lemma2)
120 (*Definition form, to control unfolding*)
121 lemma def_lfp_unfold:
122 "[| A==lfp(D,h); bnd_mono(D,h) |] ==> A = h(A)"
124 apply (erule lfp_unfold)
127 subsection{*General Induction Rule for Least Fixedpoints*}
129 lemma Collect_is_pre_fixedpt:
130 "[| bnd_mono(D,h); !!x. x : h(Collect(lfp(D,h),P)) ==> P(x) |]
131 ==> h(Collect(lfp(D,h),P)) <= Collect(lfp(D,h),P)"
132 by (blast intro: lfp_lemma2 [THEN subsetD] bnd_monoD2 [THEN subsetD]
133 lfp_subset [THEN subsetD])
135 (*This rule yields an induction hypothesis in which the components of a
136 data structure may be assumed to be elements of lfp(D,h)*)
138 "[| bnd_mono(D,h); a : lfp(D,h);
139 !!x. x : h(Collect(lfp(D,h),P)) ==> P(x)
141 apply (rule Collect_is_pre_fixedpt
142 [THEN lfp_lowerbound, THEN subsetD, THEN CollectD2])
143 apply (rule_tac [3] lfp_subset [THEN Collect_subset [THEN subset_trans]],
147 (*Definition form, to control unfolding*)
149 "[| A == lfp(D,h); bnd_mono(D,h); a:A;
150 !!x. x : h(Collect(A,P)) ==> P(x)
152 by (rule induct, blast+)
154 (*This version is useful when "A" is not a subset of D
155 second premise could simply be h(D Int A) <= D or !!X. X<=D ==> h(X)<=D *)
156 lemma lfp_Int_lowerbound:
157 "[| h(D Int A) <= A; bnd_mono(D,h) |] ==> lfp(D,h) <= A"
158 apply (rule lfp_lowerbound [THEN subset_trans])
159 apply (erule bnd_mono_subset [THEN Int_greatest], blast+)
162 (*Monotonicity of lfp, where h precedes i under a domain-like partial order
163 monotonicity of h is not strictly necessary; h must be bounded by D*)
165 assumes hmono: "bnd_mono(D,h)"
166 and imono: "bnd_mono(E,i)"
167 and subhi: "!!X. X<=D ==> h(X) <= i(X)"
168 shows "lfp(D,h) <= lfp(E,i)"
169 apply (rule bnd_monoD1 [THEN lfp_greatest])
171 apply (rule hmono [THEN [2] lfp_Int_lowerbound])
172 apply (rule Int_lower1 [THEN subhi, THEN subset_trans])
173 apply (rule imono [THEN bnd_monoD2, THEN subset_trans], auto)
176 (*This (unused) version illustrates that monotonicity is not really needed,
177 but both lfp's must be over the SAME set D; Inter is anti-monotonic!*)
179 "[| i(D) <= D; !!X. X<=D ==> h(X) <= i(X) |] ==> lfp(D,h) <= lfp(D,i)"
180 apply (rule lfp_greatest, assumption)
181 apply (rule lfp_lowerbound, blast, assumption)
185 "[|D=D'; !!X. X <= D' ==> h(X) = h'(X)|] ==> lfp(D,h) = lfp(D',h')"
186 apply (simp add: lfp_def)
187 apply (rule_tac t=Inter in subst_context)
188 apply (rule Collect_cong, simp_all)
192 subsection{*Proof of Knaster-Tarski Theorem using @{term gfp}*}
194 (*gfp contains each post-fixedpoint that is contained in D*)
195 lemma gfp_upperbound: "[| A <= h(A); A<=D |] ==> A <= gfp(D,h)"
196 apply (unfold gfp_def)
197 apply (rule PowI [THEN CollectI, THEN Union_upper])
201 lemma gfp_subset: "gfp(D,h) <= D"
202 by (unfold gfp_def, blast)
204 (*Used in datatype package*)
205 lemma def_gfp_subset: "A==gfp(D,h) ==> A <= D"
207 apply (rule gfp_subset)
211 "[| bnd_mono(D,h); !!X. [| X <= h(X); X<=D |] ==> X<=A |] ==>
213 apply (unfold gfp_def)
214 apply (blast dest: bnd_monoD1)
218 "[| bnd_mono(D,h); A<=h(A); A<=D |] ==> A <= h(gfp(D,h))"
219 apply (rule subset_trans, assumption)
220 apply (erule bnd_monoD2)
221 apply (rule_tac [2] gfp_subset)
222 apply (simp add: gfp_upperbound)
225 lemma gfp_lemma2: "bnd_mono(D,h) ==> gfp(D,h) <= h(gfp(D,h))"
226 apply (rule gfp_least)
227 apply (rule_tac [2] gfp_lemma1)
232 "bnd_mono(D,h) ==> h(gfp(D,h)) <= gfp(D,h)"
233 apply (rule gfp_upperbound)
234 apply (rule bnd_monoD2, assumption)
235 apply (rule gfp_lemma2, assumption)
236 apply (erule bnd_mono_subset, rule gfp_subset)+
239 lemma gfp_unfold: "bnd_mono(D,h) ==> gfp(D,h) = h(gfp(D,h))"
240 apply (rule equalityI)
241 apply (erule gfp_lemma2)
242 apply (erule gfp_lemma3)
245 (*Definition form, to control unfolding*)
246 lemma def_gfp_unfold:
247 "[| A==gfp(D,h); bnd_mono(D,h) |] ==> A = h(A)"
249 apply (erule gfp_unfold)
253 subsection{*Coinduction Rules for Greatest Fixed Points*}
256 lemma weak_coinduct: "[| a: X; X <= h(X); X <= D |] ==> a : gfp(D,h)"
257 by (blast intro: gfp_upperbound [THEN subsetD])
259 lemma coinduct_lemma:
260 "[| X <= h(X Un gfp(D,h)); X <= D; bnd_mono(D,h) |] ==>
261 X Un gfp(D,h) <= h(X Un gfp(D,h))"
262 apply (erule Un_least)
263 apply (rule gfp_lemma2 [THEN subset_trans], assumption)
264 apply (rule Un_upper2 [THEN subset_trans])
265 apply (rule bnd_mono_Un, assumption+)
266 apply (rule gfp_subset)
271 "[| bnd_mono(D,h); a: X; X <= h(X Un gfp(D,h)); X <= D |]
273 apply (rule weak_coinduct)
274 apply (erule_tac [2] coinduct_lemma)
275 apply (simp_all add: gfp_subset Un_subset_iff)
278 (*Definition form, to control unfolding*)
280 "[| A == gfp(D,h); bnd_mono(D,h); a: X; X <= h(X Un A); X <= D |] ==>
283 apply (rule coinduct, assumption+)
286 (*The version used in the induction/coinduction package*)
287 lemma def_Collect_coinduct:
288 "[| A == gfp(D, %w. Collect(D,P(w))); bnd_mono(D, %w. Collect(D,P(w)));
289 a: X; X <= D; !!z. z: X ==> P(X Un A, z) |] ==>
291 apply (rule def_coinduct, assumption+, blast+)
294 (*Monotonicity of gfp!*)
296 "[| bnd_mono(D,h); D <= E;
297 !!X. X<=D ==> h(X) <= i(X) |] ==> gfp(D,h) <= gfp(E,i)"
298 apply (rule gfp_upperbound)
299 apply (rule gfp_lemma2 [THEN subset_trans], assumption)
300 apply (blast del: subsetI intro: gfp_subset)
301 apply (blast del: subsetI intro: subset_trans gfp_subset)