src/HOL/Transitive_Closure.thy
changeset 12691 d21db58bcdc2
parent 12566 fe20540bcf93
child 12823 9d3f5056296b
--- a/src/HOL/Transitive_Closure.thy	Wed Jan 09 17:42:49 2002 +0100
+++ b/src/HOL/Transitive_Closure.thy	Wed Jan 09 17:48:40 2002 +0100
@@ -2,48 +2,394 @@
     ID:         $Id$
     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     Copyright   1992  University of Cambridge
-
-Relfexive and Transitive closure of a relation
-
-rtrancl is reflexive/transitive closure;
-trancl  is transitive closure
-reflcl  is reflexive closure
-
-These postfix operators have MAXIMUM PRIORITY, forcing their operands
-to be atomic.
 *)
 
-theory Transitive_Closure = Inductive
-files ("Transitive_Closure_lemmas.ML"):
+header {* Reflexive and Transitive closure of a relation *}
+
+theory Transitive_Closure = Inductive:
+
+text {*
+  @{text rtrancl} is reflexive/transitive closure,
+  @{text trancl} is transitive closure,
+  @{text reflcl} is reflexive closure.
+
+  These postfix operators have \emph{maximum priority}, forcing their
+  operands to be atomic.
+*}
 
 consts
-  rtrancl :: "('a * 'a) set => ('a * 'a) set"    ("(_^*)" [1000] 999)
+  rtrancl :: "('a \<times> 'a) set => ('a \<times> 'a) set"    ("(_^*)" [1000] 999)
 
 inductive "r^*"
-intros
-  rtrancl_refl [intro!, simp]: "(a, a) : r^*"
-  rtrancl_into_rtrancl:        "[| (a,b) : r^*; (b,c) : r |] ==> (a,c) : r^*"
+  intros
+    rtrancl_refl [intro!, simp]: "(a, a) : r^*"
+    rtrancl_into_rtrancl: "(a, b) : r^* ==> (b, c) : r ==> (a, c) : r^*"
 
 constdefs
-  trancl :: "('a * 'a) set => ('a * 'a) set"    ("(_^+)" [1000] 999)
+  trancl :: "('a \<times> 'a) set => ('a \<times> 'a) set"    ("(_^+)" [1000] 999)
   "r^+ ==  r O rtrancl r"
 
 syntax
-  "_reflcl" :: "('a * 'a) set => ('a * 'a) set"    ("(_^=)" [1000] 999)
+  "_reflcl" :: "('a \<times> 'a) set => ('a \<times> 'a) set"    ("(_^=)" [1000] 999)
 translations
-  "r^=" == "r Un Id"
+  "r^=" == "r \<union> Id"
 
 syntax (xsymbols)
-  rtrancl :: "('a * 'a) set => ('a * 'a) set"    ("(_\\<^sup>*)" [1000] 999)
-  trancl :: "('a * 'a) set => ('a * 'a) set"    ("(_\\<^sup>+)" [1000] 999)
-  "_reflcl" :: "('a * 'a) set => ('a * 'a) set"    ("(_\\<^sup>=)" [1000] 999)
+  rtrancl :: "('a \<times> 'a) set => ('a \<times> 'a) set"    ("(_\\<^sup>*)" [1000] 999)
+  trancl :: "('a \<times> 'a) set => ('a \<times> 'a) set"    ("(_\\<^sup>+)" [1000] 999)
+  "_reflcl" :: "('a \<times> 'a) set => ('a \<times> 'a) set"    ("(_\\<^sup>=)" [1000] 999)
+
+
+subsection {* Reflexive-transitive closure *}
+
+lemma r_into_rtrancl [intro]: "!!p. p \<in> r ==> p \<in> r^*"
+  -- {* @{text rtrancl} of @{text r} contains @{text r} *}
+  apply (simp only: split_tupled_all)
+  apply (erule rtrancl_refl [THEN rtrancl_into_rtrancl])
+  done
+
+lemma rtrancl_mono: "r \<subseteq> s ==> r^* \<subseteq> s^*"
+  -- {* monotonicity of @{text rtrancl} *}
+  apply (rule subsetI)
+  apply (simp only: split_tupled_all)
+  apply (erule rtrancl.induct)
+   apply (rule_tac [2] rtrancl_into_rtrancl)
+    apply blast+
+  done
+
+theorem rtrancl_induct [consumes 1]:
+  (assumes a: "(a, b) : r^*"
+    and cases: "P a" "!!y z. [| (a, y) : r^*; (y, z) : r; P y |] ==> P z")
+  "P b"
+proof -
+  from a have "a = a --> P b"
+    by (induct "%x y. x = a --> P y" a b rule: rtrancl.induct)
+      (rules intro: cases)+
+  thus ?thesis by rules
+qed
+
+ML_setup {*
+  bind_thm ("rtrancl_induct2", split_rule
+    (read_instantiate [("a","(ax,ay)"), ("b","(bx,by)")] (thm "rtrancl_induct")));
+*}
+
+lemma trans_rtrancl: "trans(r^*)"
+  -- {* transitivity of transitive closure!! -- by induction *}
+  apply (unfold trans_def)
+  apply safe
+  apply (erule_tac b = z in rtrancl_induct)
+   apply (blast intro: rtrancl_into_rtrancl)+
+  done
+
+lemmas rtrancl_trans = trans_rtrancl [THEN transD, standard]
+
+lemma rtranclE:
+  "[| (a::'a,b) : r^*;  (a = b) ==> P;
+      !!y.[| (a,y) : r^*; (y,b) : r |] ==> P
+   |] ==> P"
+  -- {* elimination of @{text rtrancl} -- by induction on a special formula *}
+proof -
+  assume major: "(a::'a,b) : r^*"
+  case rule_context
+  show ?thesis
+    apply (subgoal_tac "(a::'a) = b | (EX y. (a,y) : r^* & (y,b) : r)")
+     apply (rule_tac [2] major [THEN rtrancl_induct])
+      prefer 2 apply (blast!)
+      prefer 2 apply (blast!)
+    apply (erule asm_rl exE disjE conjE prems)+
+    done
+qed
+
+lemmas converse_rtrancl_into_rtrancl = r_into_rtrancl [THEN rtrancl_trans, standard]
+
+text {*
+  \medskip More @{term "r^*"} equations and inclusions.
+*}
+
+lemma rtrancl_idemp [simp]: "(r^*)^* = r^*"
+  apply auto
+  apply (erule rtrancl_induct)
+   apply (rule rtrancl_refl)
+  apply (blast intro: rtrancl_trans)
+  done
+
+lemma rtrancl_idemp_self_comp [simp]: "R^* O R^* = R^*"
+  apply (rule set_ext)
+  apply (simp only: split_tupled_all)
+  apply (blast intro: rtrancl_trans)
+  done
+
+lemma rtrancl_subset_rtrancl: "r \<subseteq> s^* ==> r^* \<subseteq> s^*"
+  apply (drule rtrancl_mono)
+  apply simp
+  done
+
+lemma rtrancl_subset: "R \<subseteq> S ==> S \<subseteq> R^* ==> S^* = R^*"
+  apply (drule rtrancl_mono)
+  apply (drule rtrancl_mono)
+  apply simp
+  apply blast
+  done
+
+lemma rtrancl_Un_rtrancl: "(R^* \<union> S^*)^* = (R \<union> S)^*"
+  by (blast intro!: rtrancl_subset intro: r_into_rtrancl rtrancl_mono [THEN subsetD])
+
+lemma rtrancl_reflcl [simp]: "(R^=)^* = R^*"
+  by (blast intro!: rtrancl_subset intro: r_into_rtrancl)
+
+lemma rtrancl_r_diff_Id: "(r - Id)^* = r^*"
+  apply (rule sym)
+  apply (rule rtrancl_subset)
+   apply blast
+  apply clarify
+  apply (rename_tac a b)
+  apply (case_tac "a = b")
+   apply blast
+  apply (blast intro!: r_into_rtrancl)
+  done
+
+lemma rtrancl_converseD: "(x, y) \<in> (r^-1)^* ==> (y, x) \<in> r^*"
+  apply (erule rtrancl_induct)
+   apply (rule rtrancl_refl)
+  apply (blast intro: rtrancl_trans)
+  done
+
+lemma rtrancl_converseI: "(y, x) \<in> r^* ==> (x, y) \<in> (r^-1)^*"
+  apply (erule rtrancl_induct)
+   apply (rule rtrancl_refl)
+  apply (blast intro: rtrancl_trans)
+  done
+
+lemma rtrancl_converse: "(r^-1)^* = (r^*)^-1"
+  by (fast dest!: rtrancl_converseD intro!: rtrancl_converseI)
+
+lemma converse_rtrancl_induct:
+  "[| (a,b) : r^*; P(b);
+      !!y z.[| (y,z) : r;  (z,b) : r^*;  P(z) |] ==> P(y) |]
+    ==> P(a)"
+proof -
+  assume major: "(a,b) : r^*"
+  case rule_context
+  show ?thesis
+    apply (rule major [THEN rtrancl_converseI, THEN rtrancl_induct])
+     apply assumption
+    apply (blast! dest!: rtrancl_converseD)
+  done
+qed
+
+ML_setup {*
+  bind_thm ("converse_rtrancl_induct2", split_rule
+    (read_instantiate [("a","(ax,ay)"),("b","(bx,by)")] (thm "converse_rtrancl_induct")));
+*}
+
+lemma converse_rtranclE:
+  "[| (x,z):r^*;
+      x=z ==> P;
+      !!y. [| (x,y):r; (y,z):r^* |] ==> P
+   |] ==> P"
+proof -
+  assume major: "(x,z):r^*"
+  case rule_context
+  show ?thesis
+    apply (subgoal_tac "x = z | (EX y. (x,y) : r & (y,z) : r^*)")
+     apply (rule_tac [2] major [THEN converse_rtrancl_induct])
+      prefer 2 apply (blast!)
+     prefer 2 apply (blast!)
+    apply (erule asm_rl exE disjE conjE prems)+
+    done
+qed
+
+ML_setup {*
+  bind_thm ("converse_rtranclE2", split_rule
+    (read_instantiate [("x","(xa,xb)"), ("z","(za,zb)")] (thm "converse_rtranclE")));
+*}
+
+lemma r_comp_rtrancl_eq: "r O r^* = r^* O r"
+  by (blast elim: rtranclE converse_rtranclE
+    intro: rtrancl_into_rtrancl converse_rtrancl_into_rtrancl)
+
+
+subsection {* Transitive closure *}
 
-use "Transitive_Closure_lemmas.ML"
+lemma trancl_mono: "p \<in> r^+ ==> r \<subseteq> s ==> p \<in> s^+"
+  apply (unfold trancl_def)
+  apply (blast intro: rtrancl_mono [THEN subsetD])
+  done
+
+text {*
+  \medskip Conversions between @{text trancl} and @{text rtrancl}.
+*}
+
+lemma trancl_into_rtrancl: "!!p. p \<in> r^+ ==> p \<in> r^*"
+  apply (unfold trancl_def)
+  apply (simp only: split_tupled_all)
+  apply (erule rel_compEpair)
+  apply (assumption | rule rtrancl_into_rtrancl)+
+  done
+
+lemma r_into_trancl [intro]: "!!p. p \<in> r ==> p \<in> r^+"
+  -- {* @{text "r^+"} contains @{text r} *}
+  apply (unfold trancl_def)
+  apply (simp only: split_tupled_all)
+  apply (assumption | rule rel_compI rtrancl_refl)+
+  done
+
+lemma rtrancl_into_trancl1: "(a, b) \<in> r^* ==> (b, c) \<in> r ==> (a, c) \<in> r^+"
+  -- {* intro rule by definition: from @{text rtrancl} and @{text r} *}
+  by (auto simp add: trancl_def)
+
+lemma rtrancl_into_trancl2: "[| (a,b) : r;  (b,c) : r^* |]   ==>  (a,c) : r^+"
+  -- {* intro rule from @{text r} and @{text rtrancl} *}
+  apply (erule rtranclE)
+   apply (blast intro: r_into_trancl)
+  apply (rule rtrancl_trans [THEN rtrancl_into_trancl1])
+   apply (assumption | rule r_into_rtrancl)+
+  done
+
+lemma trancl_induct:
+  "[| (a,b) : r^+;
+      !!y.  [| (a,y) : r |] ==> P(y);
+      !!y z.[| (a,y) : r^+;  (y,z) : r;  P(y) |] ==> P(z)
+   |] ==> P(b)"
+  -- {* Nice induction rule for @{text trancl} *}
+proof -
+  assume major: "(a, b) : r^+"
+  case rule_context
+  show ?thesis
+    apply (rule major [unfolded trancl_def, THEN rel_compEpair])
+    txt {* by induction on this formula *}
+    apply (subgoal_tac "ALL z. (y,z) : r --> P (z)")
+     txt {* now solve first subgoal: this formula is sufficient *}
+     apply blast
+    apply (erule rtrancl_induct)
+    apply (blast intro: rtrancl_into_trancl1 prems)+
+    done
+qed
+
+lemma trancl_trans_induct:
+  "[| (x,y) : r^+;
+      !!x y. (x,y) : r ==> P x y;
+      !!x y z. [| (x,y) : r^+; P x y; (y,z) : r^+; P y z |] ==> P x z
+   |] ==> P x y"
+  -- {* Another induction rule for trancl, incorporating transitivity *}
+proof -
+  assume major: "(x,y) : r^+"
+  case rule_context
+  show ?thesis
+    by (blast intro: r_into_trancl major [THEN trancl_induct] prems)
+qed
+
+lemma tranclE:
+  "[| (a::'a,b) : r^+;
+      (a,b) : r ==> P;
+      !!y.[| (a,y) : r^+;  (y,b) : r |] ==> P
+   |] ==> P"
+  -- {* elimination of @{text "r^+"} -- \emph{not} an induction rule *}
+proof -
+  assume major: "(a::'a,b) : r^+"
+  case rule_context
+  show ?thesis
+    apply (subgoal_tac "(a::'a, b) : r | (EX y. (a,y) : r^+ & (y,b) : r)")
+     apply (erule asm_rl disjE exE conjE prems)+
+    apply (rule major [unfolded trancl_def, THEN rel_compEpair])
+    apply (erule rtranclE)
+     apply blast
+    apply (blast intro!: rtrancl_into_trancl1)
+    done
+qed
 
+lemma trans_trancl: "trans(r^+)"
+  -- {* Transitivity of @{term "r^+"} *}
+  -- {* Proved by unfolding since it uses transitivity of @{text rtrancl} *}
+  apply (unfold trancl_def)
+  apply (rule transI)
+  apply (erule rel_compEpair)+
+  apply (rule rtrancl_into_rtrancl [THEN rtrancl_trans [THEN rel_compI]])
+  apply assumption+
+  done
+
+lemmas trancl_trans = trans_trancl [THEN transD, standard]
+
+lemma rtrancl_trancl_trancl: "(x, y) \<in> r^* ==> (y, z) \<in> r^+ ==> (x, z) \<in> r^+"
+  apply (unfold trancl_def)
+  apply (blast intro: rtrancl_trans)
+  done
+
+lemma trancl_into_trancl2: "(a, b) \<in> r ==> (b, c) \<in> r^+ ==> (a, c) \<in> r^+"
+  by (erule transD [OF trans_trancl r_into_trancl])
+
+lemma trancl_insert:
+  "(insert (y, x) r)^+ = r^+ \<union> {(a, b). (a, y) \<in> r^* \<and> (x, b) \<in> r^*}"
+  -- {* primitive recursion for @{text trancl} over finite relations *}
+  apply (rule equalityI)
+   apply (rule subsetI)
+   apply (simp only: split_tupled_all)
+   apply (erule trancl_induct)
+    apply blast
+   apply (blast intro: rtrancl_into_trancl1 trancl_into_rtrancl r_into_trancl trancl_trans)
+  apply (rule subsetI)
+  apply (blast intro: trancl_mono rtrancl_mono
+    [THEN [2] rev_subsetD] rtrancl_trancl_trancl rtrancl_into_trancl2)
+  done
+
+lemma trancl_converse: "(r^-1)^+ = (r^+)^-1"
+  apply (unfold trancl_def)
+  apply (simp add: rtrancl_converse converse_rel_comp)
+  apply (simp add: rtrancl_converse [symmetric] r_comp_rtrancl_eq)
+  done
+
+lemma trancl_converseI: "(x, y) \<in> (r^+)^-1 ==> (x,y) \<in> (r^-1)^+"
+  by (simp add: trancl_converse)
+
+lemma trancl_converseD: "(x, y) \<in> (r^-1)^+ ==> (x, y) \<in> (r^+)^-1"
+  by (simp add: trancl_converse)
+
+lemma converse_trancl_induct:
+  "[| (a,b) : r^+; !!y. (y,b) : r ==> P(y);
+      !!y z.[| (y,z) : r;  (z,b) : r^+;  P(z) |] ==> P(y) |]
+    ==> P(a)"
+proof -
+  assume major: "(a,b) : r^+"
+  case rule_context
+  show ?thesis
+    apply (rule major [THEN converseI, THEN trancl_converseI [THEN trancl_induct]])
+     apply (rule prems)
+     apply (erule converseD)
+    apply (blast intro: prems dest!: trancl_converseD)
+    done
+qed
+
+lemma tranclD: "(x, y) \<in> R^+ ==> EX z. (x, z) \<in> R \<and> (z, y) \<in> R^*"
+  apply (erule converse_trancl_induct)
+   apply auto
+  apply (blast intro: rtrancl_trans)
+  done
+
+lemma irrefl_tranclI: "r^-1 \<inter> r^+ = {} ==> (x, x) \<notin> r^+"
+  apply (subgoal_tac "ALL y. (x, y) : r^+ --> x \<noteq> y")
+   apply fast
+  apply (intro strip)
+  apply (erule trancl_induct)
+   apply (auto intro: r_into_trancl)
+  done
+
+lemma irrefl_trancl_rD: "!!X. ALL x. (x, x) \<notin> r^+ ==> (x, y) \<in> r ==> x \<noteq> y"
+  by (blast dest: r_into_trancl)
+
+lemma trancl_subset_Sigma_aux:
+    "(a, b) \<in> r^* ==> r \<subseteq> A \<times> A ==> a = b \<or> a \<in> A"
+  apply (erule rtrancl_induct)
+   apply auto
+  done
+
+lemma trancl_subset_Sigma: "r \<subseteq> A \<times> A ==> r^+ \<subseteq> A \<times> A"
+  apply (unfold trancl_def)
+  apply (blast dest!: trancl_subset_Sigma_aux)
+  done
 
 lemma reflcl_trancl [simp]: "(r^+)^= = r^*"
   apply safe
-  apply (erule trancl_into_rtrancl)
+   apply (erule trancl_into_rtrancl)
   apply (blast elim: rtranclE dest: rtrancl_into_trancl1)
   done
 
@@ -70,7 +416,7 @@
   by (force simp add: reflcl_trancl [symmetric] simp del: reflcl_trancl)
 
 
-(* should be merged with the main body of lemmas: *)
+text {* @{text Domain} and @{text Range} *}
 
 lemma Domain_rtrancl [simp]: "Domain (R^*) = UNIV"
   by blast
@@ -91,24 +437,26 @@
   by (simp add: Range_def trancl_converse [symmetric])
 
 lemma Not_Domain_rtrancl:
-	"x ~: Domain R ==> ((x, y) : R^*) = (x = y)"
- apply (auto)
- by (erule rev_mp, erule rtrancl_induct, auto)
+    "x ~: Domain R ==> ((x, y) : R^*) = (x = y)"
+  apply auto
+  by (erule rev_mp, erule rtrancl_induct, auto)
+
 
-(* more about converse rtrancl and trancl, should be merged with main body *)
+text {* More about converse @{text rtrancl} and @{text trancl}, should
+  be merged with main body. *}
 
-lemma r_r_into_trancl: "(a,b) \<in> R \<Longrightarrow> (b,c) \<in> R \<Longrightarrow> (a,c) \<in> R^+"
+lemma r_r_into_trancl: "(a, b) \<in> R ==> (b, c) \<in> R ==> (a, c) \<in> R^+"
   by (fast intro: trancl_trans)
 
 lemma trancl_into_trancl [rule_format]:
-  "(a,b) \<in> r\<^sup>+ \<Longrightarrow> (b,c) \<in> r \<longrightarrow> (a,c) \<in> r\<^sup>+"
-  apply (erule trancl_induct)   
+    "(a, b) \<in> r\<^sup>+ ==> (b, c) \<in> r --> (a,c) \<in> r\<^sup>+"
+  apply (erule trancl_induct)
    apply (fast intro: r_r_into_trancl)
   apply (fast intro: r_r_into_trancl trancl_trans)
   done
 
 lemma trancl_rtrancl_trancl:
-  "(a,b) \<in> r\<^sup>+ \<Longrightarrow> (b,c) \<in> r\<^sup>* \<Longrightarrow> (a,c) \<in> r\<^sup>+"
+    "(a, b) \<in> r\<^sup>+ ==> (b, c) \<in> r\<^sup>* ==> (a, c) \<in> r\<^sup>+"
   apply (drule tranclD)
   apply (erule exE, erule conjE)
   apply (drule rtrancl_trans, assumption)
@@ -116,10 +464,11 @@
   apply assumption
   done
 
-lemmas [trans] = r_r_into_trancl trancl_trans rtrancl_trans 
-                 trancl_into_trancl trancl_into_trancl2
-                 rtrancl_into_rtrancl converse_rtrancl_into_rtrancl
-                 rtrancl_trancl_trancl trancl_rtrancl_trancl
+lemmas transitive_closure_trans [trans] =
+  r_r_into_trancl trancl_trans rtrancl_trans
+  trancl_into_trancl trancl_into_trancl2
+  rtrancl_into_rtrancl converse_rtrancl_into_rtrancl
+  rtrancl_trancl_trancl trancl_rtrancl_trancl
 
 declare trancl_into_rtrancl [elim]