
nipkow@10213: (*  Title:      HOL/Relation_Power.thy
nipkow@10213:     Author:     Tobias Nipkow
nipkow@10213:     Copyright   1996  TU Muenchen
paulson@15410: *)
nipkow@11306: 
paulson@15410: header{*Powers of Relations and Functions*}
nipkow@10213: 
nipkow@15131: theory Relation_Power
haftmann@29654: imports Power Transitive_Closure Plain
nipkow@15131: begin
nipkow@10213: 
haftmann@30949: consts funpower :: "('a \<Rightarrow> 'b) \<Rightarrow> nat \<Rightarrow> 'a \<Rightarrow> 'b" (infixr "^^" 80)
nipkow@10213: 
haftmann@25861: overloading
haftmann@30949:   relpow \<equiv> "funpower \<Colon> ('a \<times> 'a) set \<Rightarrow> nat \<Rightarrow> ('a \<times> 'a) set"
haftmann@25861: begin
haftmann@25861: 
haftmann@30949: text {* @{text "R ^^ n = R O ... O R"}, the n-fold composition of @{text R} *}
nipkow@10213: 
haftmann@25861: primrec relpow where
haftmann@30949:     "(R \<Colon> ('a \<times> 'a) set) ^^ 0 = Id"
haftmann@30949:   | "(R \<Colon> ('a \<times> 'a) set) ^^ Suc n = R O (R ^^ n)"
haftmann@25861: 
haftmann@25861: end
nipkow@11305: 
haftmann@25861: overloading
haftmann@30949:   funpow \<equiv> "funpower \<Colon> ('a \<Rightarrow> 'a) \<Rightarrow> nat \<Rightarrow> 'a \<Rightarrow> 'a"
haftmann@25861: begin
haftmann@25861: 
haftmann@30949: text {* @{text "f ^^ n = f o ... o f"}, the n-fold composition of @{text f} *}
haftmann@25861: 
haftmann@25861: primrec funpow where
haftmann@30949:     "(f \<Colon> 'a \<Rightarrow> 'a) ^^ 0 = id"
haftmann@30949:   | "(f \<Colon> 'a \<Rightarrow> 'a) ^^ Suc n = f o (f ^^ n)"
haftmann@25861: 
haftmann@25861: end
nipkow@11305: 
haftmann@30949: primrec fun_pow :: "nat \<Rightarrow> ('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a" where
haftmann@30949:     "fun_pow 0 f = id"
haftmann@25861:   | "fun_pow (Suc n) f = f o fun_pow n f"
haftmann@21414: 
haftmann@30949: lemma funpow_fun_pow [code unfold]:
haftmann@30949:   "f ^^ n = fun_pow n f"
haftmann@25861:   unfolding funpow_def fun_pow_def ..
haftmann@21414: 
haftmann@30949: lemma funpow_add:
haftmann@30949:   "f ^^ (m + n) = f ^^ m o f ^^ n"
wenzelm@18398:   by (induct m) simp_all
nipkow@15112: 
haftmann@30949: lemma funpow_swap1:
haftmann@30949:   "f ((f ^^ n) x) = (f ^^ n) (f x)"
nipkow@18049: proof -
haftmann@30949:   have "f ((f ^^ n) x) = (f ^^ (n+1)) x" unfolding One_nat_def by simp
haftmann@30949:   also have "\<dots>  = (f ^^ n o f ^^ 1) x" by (simp only: funpow_add)
haftmann@30949:   also have "\<dots> = (f ^^ n) (f x)" unfolding One_nat_def by simp
nipkow@18049:   finally show ?thesis .
nipkow@18049: qed
nipkow@18049: 
wenzelm@18398: lemma rel_pow_1 [simp]:
haftmann@30949:   fixes R :: "('a * 'a) set"
haftmann@30949:   shows "R ^^ 1 = R"
wenzelm@18398:   by simp
paulson@15410: 
haftmann@30949: lemma rel_pow_0_I: 
haftmann@30949:   "(x, x) \<in> R ^^ 0"
haftmann@30949:   by simp
haftmann@30949: 
haftmann@30949: lemma rel_pow_Suc_I:
haftmann@30949:   "(x, y) \<in>  R ^^ n \<Longrightarrow> (y, z) \<in> R \<Longrightarrow> (x, z) \<in> R ^^ Suc n"
wenzelm@18398:   by auto
paulson@15410: 
wenzelm@18398: lemma rel_pow_Suc_I2:
haftmann@30949:   "(x, y) \<in> R \<Longrightarrow> (y, z) \<in> R ^^ n \<Longrightarrow> (x, z) \<in> R ^^ Suc n"
haftmann@30949:   by (induct n arbitrary: z) (simp, fastsimp)
paulson@15410: 
haftmann@30949: lemma rel_pow_0_E:
haftmann@30949:   "(x, y) \<in> R ^^ 0 \<Longrightarrow> (x = y \<Longrightarrow> P) \<Longrightarrow> P"
wenzelm@18398:   by simp
paulson@15410: 
wenzelm@18398: lemma rel_pow_Suc_E:
haftmann@30949:   "(x, z) \<in> R ^^ Suc n \<Longrightarrow> (\<And>y. (x, y) \<in> R ^^ n \<Longrightarrow> (y, z) \<in> R \<Longrightarrow> P) \<Longrightarrow> P"
wenzelm@18398:   by auto
paulson@15410: 
wenzelm@18398: lemma rel_pow_E:
haftmann@30949:   "(x, z) \<in>  R ^^ n \<Longrightarrow>  (n = 0 \<Longrightarrow> x = z \<Longrightarrow> P)
haftmann@30949:    \<Longrightarrow> (\<And>y m. n = Suc m \<Longrightarrow> (x, y) \<in>  R ^^ m \<Longrightarrow> (y, z) \<in> R \<Longrightarrow> P)
haftmann@30949:    \<Longrightarrow> P"
wenzelm@18398:   by (cases n) auto
paulson@15410: 
wenzelm@18398: lemma rel_pow_Suc_D2:
haftmann@30949:   "(x, z) \<in> R ^^ Suc n \<Longrightarrow> (\<exists>y. (x, y) \<in> R \<and> (y, z) \<in> R ^^ n)"
wenzelm@20503:   apply (induct n arbitrary: x z)
wenzelm@18398:    apply (blast intro: rel_pow_0_I elim: rel_pow_0_E rel_pow_Suc_E)
wenzelm@18398:   apply (blast intro: rel_pow_Suc_I elim: rel_pow_0_E rel_pow_Suc_E)
wenzelm@18398:   done
paulson@15410: 
paulson@15410: lemma rel_pow_Suc_D2':
haftmann@30949:   "\<forall>x y z. (x, y) \<in> R ^^ n \<and> (y, z) \<in> R \<longrightarrow> (\<exists>w. (x, w) \<in> R \<and> (w, z) \<in> R ^^ n)"
wenzelm@18398:   by (induct n) (simp_all, blast)
paulson@15410: 
wenzelm@18398: lemma rel_pow_E2:
haftmann@30949:   "(x, z) \<in> R ^^ n \<Longrightarrow>  (n = 0 \<Longrightarrow> x = z \<Longrightarrow> P)
haftmann@30949:      \<Longrightarrow> (\<And>y m. n = Suc m \<Longrightarrow> (x, y) \<in> R \<Longrightarrow> (y, z) \<in> R ^^ m \<Longrightarrow> P)
haftmann@30949:    \<Longrightarrow> P"
haftmann@30949:   apply (cases n, simp)
wenzelm@18398:   apply (cut_tac n=nat and R=R in rel_pow_Suc_D2', simp, blast)
wenzelm@18398:   done
paulson@15410: 
haftmann@30949: lemma rtrancl_imp_UN_rel_pow:
haftmann@30949:   "p \<in> R^* \<Longrightarrow> p \<in> (\<Union>n. R ^^ n)"
haftmann@30949:   apply (cases p) apply (simp only:)
wenzelm@18398:   apply (erule rtrancl_induct)
wenzelm@18398:    apply (blast intro: rel_pow_0_I rel_pow_Suc_I)+
wenzelm@18398:   done
paulson@15410: 
haftmann@30949: lemma rel_pow_imp_rtrancl:
haftmann@30949:   "p \<in> R ^^ n \<Longrightarrow> p \<in> R^*"
haftmann@30949:   apply (induct n arbitrary: p)
haftmann@30949:   apply (simp_all only: split_tupled_all)
wenzelm@18398:    apply (blast intro: rtrancl_refl elim: rel_pow_0_E)
wenzelm@18398:   apply (blast elim: rel_pow_Suc_E intro: rtrancl_into_rtrancl)
wenzelm@18398:   done
paulson@15410: 
haftmann@30949: lemma rtrancl_is_UN_rel_pow:
haftmann@30949:   "R^* = (UN n. R ^^ n)"
wenzelm@18398:   by (blast intro: rtrancl_imp_UN_rel_pow rel_pow_imp_rtrancl)
paulson@15410: 
kleing@25295: lemma trancl_power:
haftmann@30949:   "x \<in> r^+ = (\<exists>n > 0. x \<in> r ^^ n)"
kleing@25295:   apply (cases x)
kleing@25295:   apply simp
kleing@25295:   apply (rule iffI)
kleing@25295:    apply (drule tranclD2)
kleing@25295:    apply (clarsimp simp: rtrancl_is_UN_rel_pow)
kleing@25295:    apply (rule_tac x="Suc x" in exI)
kleing@25295:    apply (clarsimp simp: rel_comp_def)
kleing@25295:    apply fastsimp
kleing@25295:   apply clarsimp
kleing@25295:   apply (case_tac n, simp)
kleing@25295:   apply clarsimp
kleing@25295:   apply (drule rel_pow_imp_rtrancl)
kleing@25295:   apply fastsimp
kleing@25295:   done
paulson@15410: 
wenzelm@18398: lemma single_valued_rel_pow:
haftmann@30949:   fixes R :: "('a * 'a) set"
haftmann@30949:   shows "single_valued R \<Longrightarrow> single_valued (R ^^ n)"
haftmann@30949:   apply (induct n arbitrary: R)
haftmann@30949:   apply simp_all
wenzelm@18398:   apply (rule single_valuedI)
wenzelm@18398:   apply (fast dest: single_valuedD elim: rel_pow_Suc_E)
wenzelm@18398:   done
paulson@15410: 
nipkow@10213: end




