src/HOL/Transitive_Closure.thy
changeset 13704 854501b1e957
parent 12937 0c4fd7529467
child 13726 9550a6f4ed4a
equal deleted inserted replaced
13703:a36a0d417133 13704:854501b1e957
    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)"
   383   apply (erule rtrancl_induct)
   357   apply (erule rtrancl_induct)
   384    apply auto
   358    apply auto
   385   done
   359   done
   386 
   360 
   387 lemma trancl_subset_Sigma: "r \<subseteq> A \<times> A ==> r^+ \<subseteq> A \<times> A"
   361 lemma trancl_subset_Sigma: "r \<subseteq> A \<times> A ==> r^+ \<subseteq> A \<times> A"
   388   apply (unfold trancl_def)
   362   apply (rule subsetI)
   389   apply (blast dest!: trancl_subset_Sigma_aux)
   363   apply (simp only: split_tupled_all)
       
   364   apply (erule tranclE)
       
   365   apply (blast dest!: trancl_into_rtrancl trancl_subset_Sigma_aux)+
   390   done
   366   done
   391 
   367 
   392 lemma reflcl_trancl [simp]: "(r^+)^= = r^*"
   368 lemma reflcl_trancl [simp]: "(r^+)^= = r^*"
   393   apply safe
   369   apply safe
   394    apply (erule trancl_into_rtrancl)
   370    apply (erule trancl_into_rtrancl)
   473   rtrancl_trancl_trancl trancl_rtrancl_trancl
   449   rtrancl_trancl_trancl trancl_rtrancl_trancl
   474 
   450 
   475 declare trancl_into_rtrancl [elim]
   451 declare trancl_into_rtrancl [elim]
   476 
   452 
   477 declare rtranclE [cases set: rtrancl]
   453 declare rtranclE [cases set: rtrancl]
   478 declare trancl_induct [induct set: trancl]
       
   479 declare tranclE [cases set: trancl]
   454 declare tranclE [cases set: trancl]
   480 
   455 
   481 end
   456 end