Theory Binary_Relations_Transitive_Closure
subsection ‹Transitive Closure›
theory Binary_Relations_Transitive_Closure
  imports
    Binary_Relations_Least
    Binary_Relations_Transitive
begin
consts trans_closure_on :: "'a ⇒ 'b ⇒ 'b"
definition "trans_closure_on_pred (P :: 'a ⇒ bool) R x y ≡
  ∀(R' :: 'a ⇒ 'a ⇒ bool) : transitive_on P. R ≤ R' ⟶ R' x y"
adhoc_overloading trans_closure_on ⇌ trans_closure_on_pred
lemma trans_closure_on_if_all_trans_relI:
  assumes "⋀R'. transitive_on P R' ⟹ R ≤ R' ⟹ R' x y"
  shows "trans_closure_on P R x y"
  using assms unfolding trans_closure_on_pred_def by auto
lemma all_rel_if_trans_closure_onE:
  assumes "trans_closure_on P R x y"
  obtains "⋀R'. transitive_on P R' ⟹ R ≤ R' ⟹ R' x y"
  using assms unfolding trans_closure_on_pred_def by auto
lemma transitive_on_trans_closure_on: "transitive_on P (trans_closure_on P R)"
  by (intro transitive_onI trans_closure_on_if_all_trans_relI, elim all_rel_if_trans_closure_onE)
  (blast dest: transitive_onD)
lemma trans_closure_on_le_if_le_if_transitive_on:
  assumes "transitive_on P S"
  and "R ≤ S"
  shows "trans_closure_on P R ≤ S"
  using assms by (intro le_relI trans_closure_on_if_all_trans_relI) (elim all_rel_if_trans_closure_onE)
lemma trans_closure_on_if_rel: "R x y ⟹ trans_closure_on P R x y"
  by (intro trans_closure_on_if_all_trans_relI) auto
corollary le_trans_closure_on: "R ≤ trans_closure_on P R"
  using trans_closure_on_if_rel by fast
corollary is_least_wrt_rel_trans_closure_on:
  "is_least_wrt_rel (≤) ((≤) R ⊓ transitive_on P) (trans_closure_on P R)"
  by (intro is_least_wrt_rel_if_antisymmetric_onI is_minimal_wrt_relI inf1I
    trans_closure_on_le_if_le_if_transitive_on le_trans_closure_on transitive_on_trans_closure_on)
  auto
corollary trans_closure_on_eq_least_wrt_rel:
  "trans_closure_on P R = least_wrt_rel (≤) ((≤) R ⊓ transitive_on P)"
  by (intro least_wrt_rel_eqI[symmetric] is_least_wrt_rel_trans_closure_on)
lemma trans_closure_on_le_sup:
  fixes P R defines "S ≡ R ⊔ (λx y. P x ∧ P y ∧ (∃z : P. trans_closure_on P R x z ∧ R z y))"
  shows "trans_closure_on P R ≤ S"
proof (rule trans_closure_on_le_if_le_if_transitive_on)
  show "transitive_on P S"
  proof (intro transitive_onI)
    fix x y z assume Ps: "P x" "P y" "P z" and "S x y"
    then have txy: "trans_closure_on P R x y" unfolding S_def
      using transitive_on_trans_closure_on[of P R] by (elim sup2E conjE bexE)
      (blast dest: trans_closure_on_if_rel[of R] transitive_onD
        intro: trans_closure_on_if_all_trans_relI)+
    assume "S y z"
    then consider "R y z" | z' where "P z'" "trans_closure_on P R y z'" "R z' z"
      unfolding S_def by auto
    then show "S x z"
    proof cases
      case 1 with Ps txy show ?thesis unfolding S_def by fastforce
    next
      case 2 with Ps txy show ?thesis unfolding S_def
        using transitive_on_trans_closure_on[of P R] by (fastforce dest: transitive_onD)
    qed
  qed
  show "R ≤ S" unfolding S_def by fastforce
qed
lemma trans_closure_on_cases:
  assumes "trans_closure_on P R x y"
  obtains (rel) "R x y" | (step) z where "P x" "P z" "P y" "trans_closure_on P R x z" "R z y"
  using le_relD[OF trans_closure_on_le_sup assms] by auto
lemma trans_closure_on_eq_rel_sup_trans_closure_on:
  "trans_closure_on P R = R ⊔ trans_closure_on P R↾⇘P⇙↿⇘P⇙"
proof -
  have "R' x y" if "⋀R'. transitive_on P R' ⟹ R ≤ R' ⟹ R' x y" "¬(R x y)" "transitive_on P R'"
    "R↾⇘P⇙↿⇘P⇙ ≤ R'" for R' x y
  proof -
    let ?R'plus = "R ⊔ R'"
    from that(3-4) have "transitive_on P ?R'plus"
      by (intro transitive_onI sup2CI) (auto dest: transitive_onD)+
    with that show ?thesis by fastforce
  qed
  moreover have "R' x y" if "⋀R'. transitive_on P R' ⟹ R↾⇘P⇙↿⇘P⇙ ≤ R' ⟹ R' x y" "transitive_on P R'"
    "R ≤ R'" for R' x y
    using that by blast
  ultimately show ?thesis
    by (intro ext iffI sup2CI; elim sup2E all_rel_if_trans_closure_onE )
    (blast intro!: trans_closure_on_if_all_trans_relI dest: transitive_onD)+
qed
consts trans_closure :: "'a ⇒ 'a"
definition "trans_closure_rel ≡ trans_closure_on ⊤"
adhoc_overloading trans_closure ⇌ trans_closure_rel
lemma trans_closure_eq_trans_closure_on: "trans_closure = trans_closure_on ⊤"
  unfolding trans_closure_rel_def ..
lemma trans_closure_eq_trans_closure_on_uhint [uhint]:
  assumes "P ≡ ⊤"
  shows "trans_closure = trans_closure_on P"
  using assms trans_closure_eq_trans_closure_on by simp
lemma trans_closure_iff_trans_closure_on: "trans_closure R x y = trans_closure_on ⊤ R x y"
  unfolding trans_closure_eq_trans_closure_on by simp
lemma all_rel_if_trans_closureE:
  assumes "trans_closure R x y"
  obtains "⋀R'. transitive R' ⟹ R ≤ R' ⟹ R' x y"
  using assms by (urule (e) all_rel_if_trans_closure_onE)
lemma transitive_trans_closure: "transitive (trans_closure R)"
  by (urule transitive_on_trans_closure_on)
lemma trans_closure_le_if_le_if_transitive:
  assumes "transitive S"
  and "R ≤ S"
  shows "trans_closure R ≤ S"
  using assms by (urule trans_closure_on_le_if_le_if_transitive_on)
lemma trans_closure_if_rel: "R x y ⟹ trans_closure R x y"
  by (urule trans_closure_on_if_rel)
corollary trans_closure_eq_least_wrt_rel: "trans_closure R = least_wrt_rel (≤) ((≤) R ⊓ transitive)"
  by (urule trans_closure_on_eq_least_wrt_rel)
lemma trans_closure_cases:
  assumes "trans_closure R x y"
  obtains (rel) "R x y" | (step) z where "trans_closure R x z" "R z y"
  using assms unfolding trans_closure_eq_trans_closure_on by (urule (e) trans_closure_on_cases)
end