1 (* Title: ZF/trancl.thy |
1 (* Title: ZF/trancl.thy |
2 ID: $Id$ |
2 ID: $Id$ |
3 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
3 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
4 Copyright 1992 University of Cambridge |
4 Copyright 1992 University of Cambridge |
5 |
5 |
6 Transitive closure of a relation |
6 1. General Properties of relations |
|
7 2. Transitive closure of a relation |
7 *) |
8 *) |
8 |
9 |
9 Trancl = Fixedpt + Perm + mono + Rel + |
10 theory Trancl = Fixedpt + Perm + mono: |
10 consts |
11 |
11 rtrancl :: "i=>i" ("(_^*)" [100] 100) (*refl/transitive closure*) |
12 constdefs |
12 trancl :: "i=>i" ("(_^+)" [100] 100) (*transitive closure*) |
13 refl :: "[i,i]=>o" |
13 |
14 "refl(A,r) == (ALL x: A. <x,x> : r)" |
14 defs |
15 |
15 rtrancl_def "r^* == lfp(field(r)*field(r), %s. id(field(r)) Un (r O s))" |
16 irrefl :: "[i,i]=>o" |
16 trancl_def "r^+ == r O r^*" |
17 "irrefl(A,r) == ALL x: A. <x,x> ~: r" |
|
18 |
|
19 equiv :: "[i,i]=>o" |
|
20 "equiv(A,r) == r <= A*A & refl(A,r) & sym(r) & trans(r)" |
|
21 |
|
22 sym :: "i=>o" |
|
23 "sym(r) == ALL x y. <x,y>: r --> <y,x>: r" |
|
24 |
|
25 asym :: "i=>o" |
|
26 "asym(r) == ALL x y. <x,y>:r --> ~ <y,x>:r" |
|
27 |
|
28 antisym :: "i=>o" |
|
29 "antisym(r) == ALL x y.<x,y>:r --> <y,x>:r --> x=y" |
|
30 |
|
31 trans :: "i=>o" |
|
32 "trans(r) == ALL x y z. <x,y>: r --> <y,z>: r --> <x,z>: r" |
|
33 |
|
34 trans_on :: "[i,i]=>o" ("trans[_]'(_')") |
|
35 "trans[A](r) == ALL x:A. ALL y:A. ALL z:A. |
|
36 <x,y>: r --> <y,z>: r --> <x,z>: r" |
|
37 |
|
38 rtrancl :: "i=>i" ("(_^*)" [100] 100) (*refl/transitive closure*) |
|
39 "r^* == lfp(field(r)*field(r), %s. id(field(r)) Un (r O s))" |
|
40 |
|
41 trancl :: "i=>i" ("(_^+)" [100] 100) (*transitive closure*) |
|
42 "r^+ == r O r^*" |
|
43 |
|
44 subsection{*General properties of relations*} |
|
45 |
|
46 subsubsection{*irreflexivity*} |
|
47 |
|
48 lemma irreflI: |
|
49 "[| !!x. x:A ==> <x,x> ~: r |] ==> irrefl(A,r)" |
|
50 by (simp add: irrefl_def); |
|
51 |
|
52 lemma symI: "[| irrefl(A,r); x:A |] ==> <x,x> ~: r" |
|
53 apply (simp add: irrefl_def) |
|
54 done |
|
55 |
|
56 subsubsection{*symmetry*} |
|
57 |
|
58 lemma symI: |
|
59 "[| !!x y.<x,y>: r ==> <y,x>: r |] ==> sym(r)" |
|
60 apply (unfold sym_def); |
|
61 apply (blast intro: elim:); |
|
62 done |
|
63 |
|
64 lemma antisymI: "[| sym(r); <x,y>: r |] ==> <y,x>: r" |
|
65 apply (unfold sym_def) |
|
66 apply blast |
|
67 done |
|
68 |
|
69 subsubsection{*antisymmetry*} |
|
70 |
|
71 lemma antisymI: |
|
72 "[| !!x y.[| <x,y>: r; <y,x>: r |] ==> x=y |] ==> antisym(r)" |
|
73 apply (simp add: antisym_def) |
|
74 apply (blast intro: elim:); |
|
75 done |
|
76 |
|
77 lemma antisymE: "[| antisym(r); <x,y>: r; <y,x>: r |] ==> x=y" |
|
78 apply (simp add: antisym_def) |
|
79 apply blast |
|
80 done |
|
81 |
|
82 subsubsection{*transitivity*} |
|
83 |
|
84 lemma transD: "[| trans(r); <a,b>:r; <b,c>:r |] ==> <a,c>:r" |
|
85 apply (unfold trans_def) |
|
86 apply blast |
|
87 done |
|
88 |
|
89 lemma trans_onD: |
|
90 "[| trans[A](r); <a,b>:r; <b,c>:r; a:A; b:A; c:A |] ==> <a,c>:r" |
|
91 apply (unfold trans_on_def) |
|
92 apply blast |
|
93 done |
|
94 |
|
95 subsection{*Transitive closure of a relation*} |
|
96 |
|
97 lemma rtrancl_bnd_mono: |
|
98 "bnd_mono(field(r)*field(r), %s. id(field(r)) Un (r O s))" |
|
99 apply (rule bnd_monoI) |
|
100 apply (blast intro: elim:)+ |
|
101 done |
|
102 |
|
103 lemma rtrancl_mono: "r<=s ==> r^* <= s^*" |
|
104 apply (unfold rtrancl_def) |
|
105 apply (rule lfp_mono) |
|
106 apply (rule rtrancl_bnd_mono)+ |
|
107 apply (blast intro: elim:); |
|
108 done |
|
109 |
|
110 (* r^* = id(field(r)) Un ( r O r^* ) *) |
|
111 lemmas rtrancl_unfold = |
|
112 rtrancl_bnd_mono [THEN rtrancl_def [THEN def_lfp_unfold], standard] |
|
113 |
|
114 (** The relation rtrancl **) |
|
115 |
|
116 (* r^* <= field(r) * field(r) *) |
|
117 lemmas rtrancl_type = rtrancl_def [THEN def_lfp_subset, standard] |
|
118 |
|
119 (*Reflexivity of rtrancl*) |
|
120 lemma rtrancl_refl: "[| a: field(r) |] ==> <a,a> : r^*" |
|
121 apply (rule rtrancl_unfold [THEN ssubst]) |
|
122 apply (erule idI [THEN UnI1]) |
|
123 done |
|
124 |
|
125 (*Closure under composition with r *) |
|
126 lemma rtrancl_into_rtrancl: "[| <a,b> : r^*; <b,c> : r |] ==> <a,c> : r^*" |
|
127 apply (rule rtrancl_unfold [THEN ssubst]) |
|
128 apply (rule compI [THEN UnI2]) |
|
129 apply assumption |
|
130 apply assumption |
|
131 done |
|
132 |
|
133 (*rtrancl of r contains all pairs in r *) |
|
134 lemma r_into_rtrancl: "<a,b> : r ==> <a,b> : r^*" |
|
135 apply (rule rtrancl_refl [THEN rtrancl_into_rtrancl]) |
|
136 apply (blast intro: elim:)+ |
|
137 done |
|
138 |
|
139 (*The premise ensures that r consists entirely of pairs*) |
|
140 lemma r_subset_rtrancl: "r <= Sigma(A,B) ==> r <= r^*" |
|
141 apply (blast intro: r_into_rtrancl) |
|
142 done |
|
143 |
|
144 lemma rtrancl_field: "field(r^*) = field(r)" |
|
145 apply (blast intro: r_into_rtrancl dest!: rtrancl_type [THEN subsetD]) |
|
146 done |
|
147 |
|
148 |
|
149 (** standard induction rule **) |
|
150 |
|
151 lemma rtrancl_full_induct: |
|
152 "[| <a,b> : r^*; |
|
153 !!x. x: field(r) ==> P(<x,x>); |
|
154 !!x y z.[| P(<x,y>); <x,y>: r^*; <y,z>: r |] ==> P(<x,z>) |] |
|
155 ==> P(<a,b>)" |
|
156 apply (erule def_induct [OF rtrancl_def rtrancl_bnd_mono]) |
|
157 apply (blast intro: elim:); |
|
158 done |
|
159 |
|
160 (*nice induction rule. |
|
161 Tried adding the typing hypotheses y,z:field(r), but these |
|
162 caused expensive case splits!*) |
|
163 lemma rtrancl_induct: |
|
164 "[| <a,b> : r^*; |
|
165 P(a); |
|
166 !!y z.[| <a,y> : r^*; <y,z> : r; P(y) |] ==> P(z) |
|
167 |] ==> P(b)" |
|
168 (*by induction on this formula*) |
|
169 apply (subgoal_tac "ALL y. <a,b> = <a,y> --> P (y) ") |
|
170 (*now solve first subgoal: this formula is sufficient*) |
|
171 apply (erule spec [THEN mp], rule refl) |
|
172 (*now do the induction*) |
|
173 apply (erule rtrancl_full_induct) |
|
174 apply (blast)+ |
|
175 done |
|
176 |
|
177 (*transitivity of transitive closure!! -- by induction.*) |
|
178 lemma trans_rtrancl: "trans(r^*)" |
|
179 apply (unfold trans_def) |
|
180 apply (intro allI impI) |
|
181 apply (erule_tac b = "z" in rtrancl_induct) |
|
182 apply assumption; |
|
183 apply (blast intro: rtrancl_into_rtrancl) |
|
184 done |
|
185 |
|
186 lemmas rtrancl_trans = trans_rtrancl [THEN transD, standard] |
|
187 |
|
188 (*elimination of rtrancl -- by induction on a special formula*) |
|
189 lemma rtranclE: |
|
190 "[| <a,b> : r^*; (a=b) ==> P; |
|
191 !!y.[| <a,y> : r^*; <y,b> : r |] ==> P |] |
|
192 ==> P" |
|
193 apply (subgoal_tac "a = b | (EX y. <a,y> : r^* & <y,b> : r) ") |
|
194 (*see HOL/trancl*) |
|
195 apply (blast intro: elim:); |
|
196 apply (erule rtrancl_induct) |
|
197 apply (blast intro: elim:)+ |
|
198 done |
|
199 |
|
200 |
|
201 (**** The relation trancl ****) |
|
202 |
|
203 (*Transitivity of r^+ is proved by transitivity of r^* *) |
|
204 lemma trans_trancl: "trans(r^+)" |
|
205 apply (unfold trans_def trancl_def) |
|
206 apply (blast intro: rtrancl_into_rtrancl |
|
207 trans_rtrancl [THEN transD, THEN compI]) |
|
208 done |
|
209 |
|
210 lemmas trancl_trans = trans_trancl [THEN transD, standard] |
|
211 |
|
212 (** Conversions between trancl and rtrancl **) |
|
213 |
|
214 lemma trancl_into_rtrancl: "<a,b> : r^+ ==> <a,b> : r^*" |
|
215 apply (unfold trancl_def) |
|
216 apply (blast intro: rtrancl_into_rtrancl) |
|
217 done |
|
218 |
|
219 (*r^+ contains all pairs in r *) |
|
220 lemma r_into_trancl: "<a,b> : r ==> <a,b> : r^+" |
|
221 apply (unfold trancl_def) |
|
222 apply (blast intro!: rtrancl_refl) |
|
223 done |
|
224 |
|
225 (*The premise ensures that r consists entirely of pairs*) |
|
226 lemma r_subset_trancl: "r <= Sigma(A,B) ==> r <= r^+" |
|
227 apply (blast intro: r_into_trancl) |
|
228 done |
|
229 |
|
230 (*intro rule by definition: from r^* and r *) |
|
231 lemma rtrancl_into_trancl1: "[| <a,b> : r^*; <b,c> : r |] ==> <a,c> : r^+" |
|
232 apply (unfold trancl_def) |
|
233 apply blast |
|
234 done |
|
235 |
|
236 (*intro rule from r and r^* *) |
|
237 lemma rtrancl_into_trancl2: |
|
238 "[| <a,b> : r; <b,c> : r^* |] ==> <a,c> : r^+" |
|
239 apply (erule rtrancl_induct) |
|
240 apply (erule r_into_trancl) |
|
241 apply (blast intro: r_into_trancl trancl_trans) |
|
242 done |
|
243 |
|
244 (*Nice induction rule for trancl*) |
|
245 lemma trancl_induct: |
|
246 "[| <a,b> : r^+; |
|
247 !!y. [| <a,y> : r |] ==> P(y); |
|
248 !!y z.[| <a,y> : r^+; <y,z> : r; P(y) |] ==> P(z) |
|
249 |] ==> P(b)" |
|
250 apply (rule compEpair) |
|
251 apply (unfold trancl_def, assumption) |
|
252 (*by induction on this formula*) |
|
253 apply (subgoal_tac "ALL z. <y,z> : r --> P (z) ") |
|
254 (*now solve first subgoal: this formula is sufficient*) |
|
255 apply blast |
|
256 apply (erule rtrancl_induct) |
|
257 apply (blast intro: rtrancl_into_trancl1)+ |
|
258 done |
|
259 |
|
260 (*elimination of r^+ -- NOT an induction rule*) |
|
261 lemma tranclE: |
|
262 "[| <a,b> : r^+; |
|
263 <a,b> : r ==> P; |
|
264 !!y.[| <a,y> : r^+; <y,b> : r |] ==> P |
|
265 |] ==> P" |
|
266 apply (subgoal_tac "<a,b> : r | (EX y. <a,y> : r^+ & <y,b> : r) ") |
|
267 apply (blast intro: elim:); |
|
268 apply (rule compEpair) |
|
269 apply (unfold trancl_def, assumption) |
|
270 apply (erule rtranclE) |
|
271 apply (blast intro: rtrancl_into_trancl1)+ |
|
272 done |
|
273 |
|
274 lemma trancl_type: "r^+ <= field(r)*field(r)" |
|
275 apply (unfold trancl_def) |
|
276 apply (blast elim: rtrancl_type [THEN subsetD, THEN SigmaE2]) |
|
277 done |
|
278 |
|
279 lemma trancl_mono: "r<=s ==> r^+ <= s^+" |
|
280 by (unfold trancl_def, intro comp_mono rtrancl_mono) |
|
281 |
|
282 |
|
283 (** Suggested by Sidi Ould Ehmety **) |
|
284 |
|
285 lemma rtrancl_idemp [simp]: "(r^*)^* = r^*" |
|
286 apply (rule equalityI) |
|
287 apply auto |
|
288 prefer 2 |
|
289 apply (frule rtrancl_type [THEN subsetD]) |
|
290 apply (blast intro: r_into_rtrancl elim:); |
|
291 txt{*converse direction*} |
|
292 apply (frule rtrancl_type [THEN subsetD]) |
|
293 apply (clarify ); |
|
294 apply (erule rtrancl_induct) |
|
295 apply (simp add: rtrancl_refl rtrancl_field) |
|
296 apply (blast intro: rtrancl_trans) |
|
297 done |
|
298 |
|
299 lemma rtrancl_subset: "[| R <= S; S <= R^* |] ==> S^* = R^*" |
|
300 apply (drule rtrancl_mono) |
|
301 apply (drule rtrancl_mono) |
|
302 apply simp_all |
|
303 apply blast |
|
304 done |
|
305 |
|
306 lemma rtrancl_Un_rtrancl: |
|
307 "[| r<= Sigma(A,B); s<=Sigma(C,D) |] ==> (r^* Un s^*)^* = (r Un s)^*" |
|
308 apply (rule rtrancl_subset) |
|
309 apply (blast dest: r_subset_rtrancl) |
|
310 apply (blast intro: rtrancl_mono [THEN subsetD]) |
|
311 done |
|
312 |
|
313 (*** "converse" laws by Sidi Ould Ehmety ***) |
|
314 |
|
315 (** rtrancl **) |
|
316 |
|
317 lemma rtrancl_converseD: "<x,y>:converse(r)^* ==> <x,y>:converse(r^*)" |
|
318 apply (rule converseI) |
|
319 apply (frule rtrancl_type [THEN subsetD]) |
|
320 apply (erule rtrancl_induct) |
|
321 apply (blast intro: rtrancl_refl) |
|
322 apply (blast intro: r_into_rtrancl rtrancl_trans) |
|
323 done |
|
324 |
|
325 lemma rtrancl_converseI: "<x,y>:converse(r^*) ==> <x,y>:converse(r)^*" |
|
326 apply (drule converseD) |
|
327 apply (frule rtrancl_type [THEN subsetD]) |
|
328 apply (erule rtrancl_induct) |
|
329 apply (blast intro: rtrancl_refl) |
|
330 apply (blast intro: r_into_rtrancl rtrancl_trans) |
|
331 done |
|
332 |
|
333 lemma rtrancl_converse: "converse(r)^* = converse(r^*)" |
|
334 apply (safe intro!: equalityI) |
|
335 apply (frule rtrancl_type [THEN subsetD]) |
|
336 apply (safe dest!: rtrancl_converseD intro!: rtrancl_converseI) |
|
337 done |
|
338 |
|
339 (** trancl **) |
|
340 |
|
341 lemma trancl_converseD: "<a, b>:converse(r)^+ ==> <a, b>:converse(r^+)" |
|
342 apply (erule trancl_induct) |
|
343 apply (auto intro: r_into_trancl trancl_trans) |
|
344 done |
|
345 |
|
346 lemma trancl_converseI: "<x,y>:converse(r^+) ==> <x,y>:converse(r)^+" |
|
347 apply (drule converseD) |
|
348 apply (erule trancl_induct) |
|
349 apply (auto intro: r_into_trancl trancl_trans) |
|
350 done |
|
351 |
|
352 lemma trancl_converse: "converse(r)^+ = converse(r^+)" |
|
353 apply (safe intro!: equalityI) |
|
354 apply (frule trancl_type [THEN subsetD]) |
|
355 apply (safe dest!: trancl_converseD intro!: trancl_converseI) |
|
356 done |
|
357 |
|
358 lemma converse_trancl_induct: |
|
359 "[| <a, b>:r^+; !!y. <y, b> :r ==> P(y); |
|
360 !!y z. [| <y, z> : r; <z, b> : r^+; P(z) |] ==> P(y) |] |
|
361 ==> P(a)" |
|
362 apply (drule converseI) |
|
363 apply (simp (no_asm_use) add: trancl_converse [symmetric]) |
|
364 apply (erule trancl_induct) |
|
365 apply (auto simp add: trancl_converse) |
|
366 done |
|
367 |
|
368 ML |
|
369 {* |
|
370 val refl_def = thm "refl_def"; |
|
371 val irrefl_def = thm "irrefl_def"; |
|
372 val equiv_def = thm "equiv_def"; |
|
373 val sym_def = thm "sym_def"; |
|
374 val asym_def = thm "asym_def"; |
|
375 val antisym_def = thm "antisym_def"; |
|
376 val trans_def = thm "trans_def"; |
|
377 val trans_on_def = thm "trans_on_def"; |
|
378 |
|
379 val irreflI = thm "irreflI"; |
|
380 val symI = thm "symI"; |
|
381 val symI = thm "symI"; |
|
382 val antisymI = thm "antisymI"; |
|
383 val antisymE = thm "antisymE"; |
|
384 val transD = thm "transD"; |
|
385 val trans_onD = thm "trans_onD"; |
|
386 |
|
387 val rtrancl_bnd_mono = thm "rtrancl_bnd_mono"; |
|
388 val rtrancl_mono = thm "rtrancl_mono"; |
|
389 val rtrancl_unfold = thm "rtrancl_unfold"; |
|
390 val rtrancl_type = thm "rtrancl_type"; |
|
391 val rtrancl_refl = thm "rtrancl_refl"; |
|
392 val rtrancl_into_rtrancl = thm "rtrancl_into_rtrancl"; |
|
393 val r_into_rtrancl = thm "r_into_rtrancl"; |
|
394 val r_subset_rtrancl = thm "r_subset_rtrancl"; |
|
395 val rtrancl_field = thm "rtrancl_field"; |
|
396 val rtrancl_full_induct = thm "rtrancl_full_induct"; |
|
397 val rtrancl_induct = thm "rtrancl_induct"; |
|
398 val trans_rtrancl = thm "trans_rtrancl"; |
|
399 val rtrancl_trans = thm "rtrancl_trans"; |
|
400 val rtranclE = thm "rtranclE"; |
|
401 val trans_trancl = thm "trans_trancl"; |
|
402 val trancl_trans = thm "trancl_trans"; |
|
403 val trancl_into_rtrancl = thm "trancl_into_rtrancl"; |
|
404 val r_into_trancl = thm "r_into_trancl"; |
|
405 val r_subset_trancl = thm "r_subset_trancl"; |
|
406 val rtrancl_into_trancl1 = thm "rtrancl_into_trancl1"; |
|
407 val rtrancl_into_trancl2 = thm "rtrancl_into_trancl2"; |
|
408 val trancl_induct = thm "trancl_induct"; |
|
409 val tranclE = thm "tranclE"; |
|
410 val trancl_type = thm "trancl_type"; |
|
411 val trancl_mono = thm "trancl_mono"; |
|
412 val rtrancl_idemp = thm "rtrancl_idemp"; |
|
413 val rtrancl_subset = thm "rtrancl_subset"; |
|
414 val rtrancl_Un_rtrancl = thm "rtrancl_Un_rtrancl"; |
|
415 val rtrancl_converseD = thm "rtrancl_converseD"; |
|
416 val rtrancl_converseI = thm "rtrancl_converseI"; |
|
417 val rtrancl_converse = thm "rtrancl_converse"; |
|
418 val trancl_converseD = thm "trancl_converseD"; |
|
419 val trancl_converseI = thm "trancl_converseI"; |
|
420 val trancl_converse = thm "trancl_converse"; |
|
421 val converse_trancl_induct = thm "converse_trancl_induct"; |
|
422 *} |
|
423 |
17 end |
424 end |