23 inductive "r^*" |
23 inductive "r^*" |
24 intros |
24 intros |
25 rtrancl_refl [intro!, CPure.intro!, simp]: "(a, a) : r^*" |
25 rtrancl_refl [intro!, CPure.intro!, simp]: "(a, a) : r^*" |
26 rtrancl_into_rtrancl [CPure.intro]: "(a, b) : r^* ==> (b, c) : r ==> (a, c) : r^*" |
26 rtrancl_into_rtrancl [CPure.intro]: "(a, b) : r^* ==> (b, c) : r ==> (a, c) : r^*" |
27 |
27 |
28 constdefs |
28 consts |
29 trancl :: "('a \<times> 'a) set => ('a \<times> 'a) set" ("(_^+)" [1000] 999) |
29 trancl :: "('a \<times> 'a) set => ('a \<times> 'a) set" ("(_^+)" [1000] 999) |
30 "r^+ == r O rtrancl r" |
30 |
|
31 inductive "r^+" |
|
32 intros |
|
33 r_into_trancl [intro, CPure.intro]: "(a, b) : r ==> (a, b) : r^+" |
|
34 trancl_into_trancl [CPure.intro]: "(a, b) : r^+ ==> (b, c) : r ==> (a,c) : r^+" |
31 |
35 |
32 syntax |
36 syntax |
33 "_reflcl" :: "('a \<times> 'a) set => ('a \<times> 'a) set" ("(_^=)" [1000] 999) |
37 "_reflcl" :: "('a \<times> 'a) set => ('a \<times> 'a) set" ("(_^=)" [1000] 999) |
34 translations |
38 translations |
35 "r^=" == "r \<union> Id" |
39 "r^=" == "r \<union> Id" |
211 intro: rtrancl_into_rtrancl converse_rtrancl_into_rtrancl) |
215 intro: rtrancl_into_rtrancl converse_rtrancl_into_rtrancl) |
212 |
216 |
213 |
217 |
214 subsection {* Transitive closure *} |
218 subsection {* Transitive closure *} |
215 |
219 |
216 lemma trancl_mono: "p \<in> r^+ ==> r \<subseteq> s ==> p \<in> s^+" |
220 lemma trancl_mono: "!!p. p \<in> r^+ ==> r \<subseteq> s ==> p \<in> s^+" |
217 apply (unfold trancl_def) |
221 apply (simp only: split_tupled_all) |
218 apply (blast intro: rtrancl_mono [THEN subsetD]) |
222 apply (erule trancl.induct) |
219 done |
223 apply (rules dest: subsetD)+ |
|
224 done |
|
225 |
|
226 lemma r_into_trancl': "!!p. p : r ==> p : r^+" |
|
227 by (simp only: split_tupled_all) (erule r_into_trancl) |
220 |
228 |
221 text {* |
229 text {* |
222 \medskip Conversions between @{text trancl} and @{text rtrancl}. |
230 \medskip Conversions between @{text trancl} and @{text rtrancl}. |
223 *} |
231 *} |
224 |
232 |
225 lemma trancl_into_rtrancl: "!!p. p \<in> r^+ ==> p \<in> r^*" |
233 lemma trancl_into_rtrancl: "(a, b) \<in> r^+ ==> (a, b) \<in> r^*" |
226 apply (unfold trancl_def) |
234 by (erule trancl.induct) rules+ |
227 apply (simp only: split_tupled_all) |
235 |
228 apply (erule rel_compEpair) |
236 lemma rtrancl_into_trancl1: assumes r: "(a, b) \<in> r^*" |
229 apply (assumption | rule rtrancl_into_rtrancl)+ |
237 shows "!!c. (b, c) \<in> r ==> (a, c) \<in> r^+" using r |
230 done |
238 by induct rules+ |
231 |
|
232 lemma r_into_trancl [intro]: "!!p. p \<in> r ==> p \<in> r^+" |
|
233 -- {* @{text "r^+"} contains @{text r} *} |
|
234 apply (unfold trancl_def) |
|
235 apply (simp only: split_tupled_all) |
|
236 apply (assumption | rule rel_compI rtrancl_refl)+ |
|
237 done |
|
238 |
|
239 lemma rtrancl_into_trancl1: "(a, b) \<in> r^* ==> (b, c) \<in> r ==> (a, c) \<in> r^+" |
|
240 -- {* intro rule by definition: from @{text rtrancl} and @{text r} *} |
|
241 by (auto simp add: trancl_def) |
|
242 |
239 |
243 lemma rtrancl_into_trancl2: "[| (a,b) : r; (b,c) : r^* |] ==> (a,c) : r^+" |
240 lemma rtrancl_into_trancl2: "[| (a,b) : r; (b,c) : r^* |] ==> (a,c) : r^+" |
244 -- {* intro rule from @{text r} and @{text rtrancl} *} |
241 -- {* intro rule from @{text r} and @{text rtrancl} *} |
245 apply (erule rtranclE) |
242 apply (erule rtranclE) |
246 apply (blast intro: r_into_trancl) |
243 apply rules |
247 apply (rule rtrancl_trans [THEN rtrancl_into_trancl1]) |
244 apply (rule rtrancl_trans [THEN rtrancl_into_trancl1]) |
248 apply (assumption | rule r_into_rtrancl)+ |
245 apply (assumption | rule r_into_rtrancl)+ |
249 done |
246 done |
250 |
247 |
251 lemma trancl_induct: |
248 lemma trancl_induct [consumes 1, induct set: trancl]: |
252 "[| (a,b) : r^+; |
249 assumes a: "(a,b) : r^+" |
253 !!y. [| (a,y) : r |] ==> P(y); |
250 and cases: "!!y. (a, y) : r ==> P y" |
254 !!y z.[| (a,y) : r^+; (y,z) : r; P(y) |] ==> P(z) |
251 "!!y z. (a,y) : r^+ ==> (y, z) : r ==> P y ==> P z" |
255 |] ==> P(b)" |
252 shows "P b" |
256 -- {* Nice induction rule for @{text trancl} *} |
253 -- {* Nice induction rule for @{text trancl} *} |
257 proof - |
254 proof - |
258 assume major: "(a, b) : r^+" |
255 from a have "a = a --> P b" |
259 case rule_context |
256 by (induct "%x y. x = a --> P y" a b) (rules intro: cases)+ |
260 show ?thesis |
257 thus ?thesis by rules |
261 apply (rule major [unfolded trancl_def, THEN rel_compEpair]) |
|
262 txt {* by induction on this formula *} |
|
263 apply (subgoal_tac "ALL z. (y,z) : r --> P (z)") |
|
264 txt {* now solve first subgoal: this formula is sufficient *} |
|
265 apply blast |
|
266 apply (erule rtrancl_induct) |
|
267 apply (blast intro: rtrancl_into_trancl1 prems)+ |
|
268 done |
|
269 qed |
258 qed |
270 |
259 |
271 lemma trancl_trans_induct: |
260 lemma trancl_trans_induct: |
272 "[| (x,y) : r^+; |
261 "[| (x,y) : r^+; |
273 !!x y. (x,y) : r ==> P x y; |
262 !!x y. (x,y) : r ==> P x y; |
276 -- {* Another induction rule for trancl, incorporating transitivity *} |
265 -- {* Another induction rule for trancl, incorporating transitivity *} |
277 proof - |
266 proof - |
278 assume major: "(x,y) : r^+" |
267 assume major: "(x,y) : r^+" |
279 case rule_context |
268 case rule_context |
280 show ?thesis |
269 show ?thesis |
281 by (blast intro: r_into_trancl major [THEN trancl_induct] prems) |
270 by (rules intro: r_into_trancl major [THEN trancl_induct] prems) |
282 qed |
271 qed |
283 |
272 |
284 lemma tranclE: |
273 inductive_cases tranclE: "(a, b) : r^+" |
285 "[| (a::'a,b) : r^+; |
|
286 (a,b) : r ==> P; |
|
287 !!y.[| (a,y) : r^+; (y,b) : r |] ==> P |
|
288 |] ==> P" |
|
289 -- {* elimination of @{text "r^+"} -- \emph{not} an induction rule *} |
|
290 proof - |
|
291 assume major: "(a::'a,b) : r^+" |
|
292 case rule_context |
|
293 show ?thesis |
|
294 apply (subgoal_tac "(a::'a, b) : r | (EX y. (a,y) : r^+ & (y,b) : r)") |
|
295 apply (erule asm_rl disjE exE conjE prems)+ |
|
296 apply (rule major [unfolded trancl_def, THEN rel_compEpair]) |
|
297 apply (erule rtranclE) |
|
298 apply blast |
|
299 apply (blast intro!: rtrancl_into_trancl1) |
|
300 done |
|
301 qed |
|
302 |
274 |
303 lemma trans_trancl: "trans(r^+)" |
275 lemma trans_trancl: "trans(r^+)" |
304 -- {* Transitivity of @{term "r^+"} *} |
276 -- {* Transitivity of @{term "r^+"} *} |
305 -- {* Proved by unfolding since it uses transitivity of @{text rtrancl} *} |
277 proof (rule transI) |
306 apply (unfold trancl_def) |
278 fix x y z |
307 apply (rule transI) |
279 assume "(x, y) \<in> r^+" |
308 apply (erule rel_compEpair)+ |
280 assume "(y, z) \<in> r^+" |
309 apply (rule rtrancl_into_rtrancl [THEN rtrancl_trans [THEN rel_compI]]) |
281 thus "(x, z) \<in> r^+" by induct (rules!)+ |
310 apply assumption+ |
282 qed |
311 done |
|
312 |
283 |
313 lemmas trancl_trans = trans_trancl [THEN transD, standard] |
284 lemmas trancl_trans = trans_trancl [THEN transD, standard] |
314 |
285 |
315 lemma rtrancl_trancl_trancl: "(x, y) \<in> r^* ==> (y, z) \<in> r^+ ==> (x, z) \<in> r^+" |
286 lemma rtrancl_trancl_trancl: assumes r: "(x, y) \<in> r^*" |
316 apply (unfold trancl_def) |
287 shows "!!z. (y, z) \<in> r^+ ==> (x, z) \<in> r^+" using r |
317 apply (blast intro: rtrancl_trans) |
288 by induct (rules intro: trancl_trans)+ |
318 done |
|
319 |
289 |
320 lemma trancl_into_trancl2: "(a, b) \<in> r ==> (b, c) \<in> r^+ ==> (a, c) \<in> r^+" |
290 lemma trancl_into_trancl2: "(a, b) \<in> r ==> (b, c) \<in> r^+ ==> (a, c) \<in> r^+" |
321 by (erule transD [OF trans_trancl r_into_trancl]) |
291 by (erule transD [OF trans_trancl r_into_trancl]) |
322 |
292 |
323 lemma trancl_insert: |
293 lemma trancl_insert: |
332 apply (rule subsetI) |
302 apply (rule subsetI) |
333 apply (blast intro: trancl_mono rtrancl_mono |
303 apply (blast intro: trancl_mono rtrancl_mono |
334 [THEN [2] rev_subsetD] rtrancl_trancl_trancl rtrancl_into_trancl2) |
304 [THEN [2] rev_subsetD] rtrancl_trancl_trancl rtrancl_into_trancl2) |
335 done |
305 done |
336 |
306 |
|
307 lemma trancl_converseI: "(x, y) \<in> (r^+)^-1 ==> (x, y) \<in> (r^-1)^+" |
|
308 apply (drule converseD) |
|
309 apply (erule trancl.induct) |
|
310 apply (rules intro: converseI trancl_trans)+ |
|
311 done |
|
312 |
|
313 lemma trancl_converseD: "(x, y) \<in> (r^-1)^+ ==> (x, y) \<in> (r^+)^-1" |
|
314 apply (rule converseI) |
|
315 apply (erule trancl.induct) |
|
316 apply (rules dest: converseD intro: trancl_trans)+ |
|
317 done |
|
318 |
337 lemma trancl_converse: "(r^-1)^+ = (r^+)^-1" |
319 lemma trancl_converse: "(r^-1)^+ = (r^+)^-1" |
338 apply (unfold trancl_def) |
320 by (fastsimp simp add: split_tupled_all |
339 apply (simp add: rtrancl_converse converse_rel_comp) |
321 intro!: trancl_converseI trancl_converseD) |
340 apply (simp add: rtrancl_converse [symmetric] r_comp_rtrancl_eq) |
|
341 done |
|
342 |
|
343 lemma trancl_converseI: "(x, y) \<in> (r^+)^-1 ==> (x,y) \<in> (r^-1)^+" |
|
344 by (simp add: trancl_converse) |
|
345 |
|
346 lemma trancl_converseD: "(x, y) \<in> (r^-1)^+ ==> (x, y) \<in> (r^+)^-1" |
|
347 by (simp add: trancl_converse) |
|
348 |
322 |
349 lemma converse_trancl_induct: |
323 lemma converse_trancl_induct: |
350 "[| (a,b) : r^+; !!y. (y,b) : r ==> P(y); |
324 "[| (a,b) : r^+; !!y. (y,b) : r ==> P(y); |
351 !!y z.[| (y,z) : r; (z,b) : r^+; P(z) |] ==> P(y) |] |
325 !!y z.[| (y,z) : r; (z,b) : r^+; P(z) |] ==> P(y) |] |
352 ==> P(a)" |
326 ==> P(a)" |