Theory Min_Max_Least_Greatest.Relation_Reachability

theory Relation_Reachability
  imports Main
begin


section ‹Definitions›

text ‹When a binary relation hold for two values, i.e., termR x y, we say that termx reaches
termy and, conversely, that termy is reachable by termx.›

definition non_reachable_wrt where
  "non_reachable_wrt R X x  x  X  (y  X - {x}. ¬ (R y x))"

definition non_reaching_wrt where
  "non_reaching_wrt R X x  x  X  (y  X - {x}. ¬ (R x y))"

definition reaching_all_wrt where
  "reaching_all_wrt R X x  x  X  (y  X - {x}. R x y)"

definition reachable_by_all_wrt where
  "reachable_by_all_wrt R X x  x  X  (y  X - {x}. R y x)"


section ‹Conversions›

lemma non_reachable_wrt_iff:
  "non_reachable_wrt R X x  x  X  (y  X. y  x  ¬ R y x)"
  unfolding non_reachable_wrt_def by blast

lemma non_reaching_wrt_iff:
  "non_reaching_wrt R X x  x  X  (y  X. y  x  ¬ R x y)"
  unfolding non_reaching_wrt_def by blast

lemma reaching_all_wrt_iff:
  "reaching_all_wrt R X x  x  X  (y  X. y  x  R x y)"
  unfolding reaching_all_wrt_def by blast

lemma reachable_by_all_wrt_iff:
  "reachable_by_all_wrt R X x  x  X  (y  X. y  x  R y x)"
  unfolding reachable_by_all_wrt_def by blast

lemma non_reachable_wrt_filter_iff:
  "non_reachable_wrt R {y  X. P y} x  x  X  P x  (y  X - {x}. P y  ¬ R y x)"
  by (auto simp: non_reachable_wrt_def)

lemma non_reachable_wrt_conversep[simp]:
  "non_reachable_wrt R¯¯ = non_reaching_wrt R"
  unfolding non_reaching_wrt_def non_reachable_wrt_def by simp

lemma non_reaching_wrt_conversep[simp]:
  "non_reaching_wrt R¯¯ = non_reachable_wrt R"
  unfolding non_reaching_wrt_def non_reachable_wrt_def by simp

lemma reaching_all_wrt_conversep[simp]:
  "reaching_all_wrt R¯¯ = reachable_by_all_wrt R"
  unfolding reaching_all_wrt_def reachable_by_all_wrt_def by simp

lemma reachable_by_all_wrt_conversep[simp]:
  "reachable_by_all_wrt R¯¯ = reaching_all_wrt R"
  unfolding reaching_all_wrt_def reachable_by_all_wrt_def by simp


lemma non_reachable_wrt_eq_reaching_all_wrt:
  assumes asym: "asymp_on X R" and tot: "totalp_on X R"
  shows "non_reachable_wrt R X = reaching_all_wrt R X"
proof (intro ext iffI)
  fix x
  from tot show "non_reachable_wrt R X x  reaching_all_wrt R X x"
    unfolding non_reachable_wrt_def reaching_all_wrt_def
    by (metis Diff_iff insertCI totalp_onD)
next
  fix x
  from asym show "reaching_all_wrt R X x  non_reachable_wrt R X x"
    unfolding reaching_all_wrt_def non_reachable_wrt_def
    by (metis Diff_iff asymp_onD)
qed

lemma non_reaching_wrt_eq_reachable_by_all_wrt:
  assumes asym: "asymp_on X R" and tot: "totalp_on X R"
  shows "non_reaching_wrt R X = reachable_by_all_wrt R X"
proof (intro ext iffI)
  fix x
  from tot show "non_reaching_wrt R X x  reachable_by_all_wrt R X x"
    unfolding non_reaching_wrt_def reachable_by_all_wrt_def
    by (metis Diff_iff insertCI totalp_onD)
next
  fix x
  from asym show "reachable_by_all_wrt R X x  non_reaching_wrt R X x"
    unfolding reachable_by_all_wrt_def non_reaching_wrt_def
    by (metis Diff_iff asymp_onD)
qed

lemma non_reachable_wrt_reflclp[simp]:
  "non_reachable_wrt R== = non_reachable_wrt R"
  by (intro ext iffI) (simp_all add: non_reachable_wrt_iff)

lemma non_reaching_wrt_reflclp[simp]:
  "non_reaching_wrt R== = non_reaching_wrt R"
  by (intro ext iffI) (simp_all add: non_reaching_wrt_iff)

lemma reaching_all_wrt_reflclp[simp]:
  "reaching_all_wrt R== = reaching_all_wrt R"
  by (intro ext iffI) (simp_all add: reaching_all_wrt_iff)

lemma reachable_by_all_wrt_reflclp[simp]:
  "reachable_by_all_wrt R== = reachable_by_all_wrt R"
  by (intro ext iffI) (simp_all add: reachable_by_all_wrt_iff)


section ‹Existence›

lemma ex_non_reachable_wrt:
  "transp_on A R  asymp_on A R  finite A  A  {}  m. non_reachable_wrt R A m"
  using Finite_Set.bex_min_element
  by (metis non_reachable_wrt_iff)

lemma ex_non_reaching_wrt:
  "transp_on A R  asymp_on A R  finite A  A  {}  m. non_reaching_wrt R A m"
  using Finite_Set.bex_max_element
  by (metis non_reaching_wrt_iff)

lemma ex_reaching_all_wrt:
  "transp_on A R  totalp_on A R  finite A  A  {}  g. reaching_all_wrt R A g"
  using Finite_Set.bex_least_element[of A R]
  by (metis reaching_all_wrt_iff)

lemma ex_reachable_by_all_wrt:
  "transp_on A R  totalp_on A R  finite A  A  {}  g. reachable_by_all_wrt R A g"
  using Finite_Set.bex_greatest_element[of A R]
  by (metis reachable_by_all_wrt_iff)

lemma not_ex_greatest_element_doubleton_if:
  assumes "x  y" and "¬ R x y" and "¬ R y x"
  shows "g. reachable_by_all_wrt R {x, y} g"
proof (rule notI)
  assume "g. reachable_by_all_wrt R {x, y} g"
  then obtain g where "reachable_by_all_wrt R {x, y} g" ..
  then show False
    unfolding reachable_by_all_wrt_def
    using assms(1) assms(2) assms(3) by blast
qed


section ‹Uniqueness›

lemma Uniq_non_reachable_wrt:
  "totalp_on X R  1x. non_reachable_wrt R X x"
  by (rule Uniq_I) (metis insert_Diff insert_iff non_reachable_wrt_def totalp_onD)

lemma Uniq_non_reaching_wrt:
  "totalp_on X R  1x. non_reaching_wrt R X x"
  by (rule Uniq_I) (metis insert_Diff insert_iff non_reaching_wrt_def totalp_onD)

lemma Uniq_reaching_all_wrt:
  "asymp_on X R  1x. reaching_all_wrt R X x"
  by (rule Uniq_I)
    (metis antisymp_onD antisymp_on_if_asymp_on insertE insert_Diff reaching_all_wrt_def)

lemma Uniq_reachable_by_all_wrt:
  "asymp_on X R  1x. reachable_by_all_wrt R X x"
  by (rule Uniq_I)
    (metis antisymp_onD antisymp_on_if_asymp_on insertE insert_Diff reachable_by_all_wrt_def)


section ‹Existence of unique element›

lemma ex1_reaching_all_wrt:
  "transp_on X R  asymp_on X R  totalp_on X R  finite X  X  {} 
    ∃!x. reaching_all_wrt R X x"
  using ex1_iff_ex_Uniq ex_reaching_all_wrt Uniq_reaching_all_wrt by metis

lemma ex1_reachable_by_all_wrt:
  "transp_on X R  asymp_on X R  totalp_on X R  finite X  X  {} 
    ∃!x. reachable_by_all_wrt R X x"
  using ex1_iff_ex_Uniq ex_reachable_by_all_wrt Uniq_reachable_by_all_wrt by metis


section ‹Transformations›

lemma non_reachable_wrt_insert_wrtI:
  assumes
    trans: "transp_on (insert y X) R" and
    asym: "asymp_on (insert y X) R" and
    "R y x" and
    x_non_reachable: "non_reachable_wrt R X x"
  shows "non_reachable_wrt R (insert y X) y"
proof -
  from x_non_reachable have x_in: "x  X" and x_min': "yX - {x}. ¬ R y x"
    by (simp_all add: non_reachable_wrt_iff)

  have "¬ R z y" if "z  insert y X - {y}" for z
  proof -
    from that have "z  X" and "z  y"
      by simp_all

    show "¬ R z y"
    proof (cases "z = x")
      case True
      thus ?thesis
        using R y x asym x_in
        by (metis asymp_onD insertI1 insertI2)
    next
      case False
      hence "¬ R z x"
        using x_min'[rule_format, of z, simplified] z  X by metis
      then show ?thesis
        using R y x trans z  X x_in
        by (meson insertCI transp_onD)
    qed
  qed
  thus ?thesis
    by (simp add: non_reachable_wrt_def)
qed

end