Theory Relation_Extensions

section ‹Relations›

theory Relation_Extensions
imports
  Basic_Extensions
begin

  abbreviation rev_lex_prod (infixr "<*rlex*>" 80)
    where "r1 <*rlex*> r2  inv_image (r2 <*lex*> r1) swap"

  lemmas sym_rtranclp[intro] = sym_rtrancl[to_pred]

  definition liftablep :: "('a  'a  bool)  ('a  'a)  bool"
    where "liftablep r f   x y. r x y  r (f x) (f y)"

  lemma liftablepI[intro]:
    assumes " x y. r x y  r (f x) (f y)"
    shows "liftablep r f"
    using assms
    unfolding liftablep_def
    by simp
  lemma liftablepE[elim]:
    assumes "liftablep r f"
    assumes "r x y"
    obtains "r (f x) (f y)"
    using assms
    unfolding liftablep_def
    by simp

  lemma liftablep_rtranclp:
    assumes "liftablep r f"
    shows "liftablep r** f"
  proof
    fix x y
    assume "r** x y"
    thus "r** (f x) (f y)"
      using assms
      by (induct rule: rtranclp_induct, force+)
  qed

  definition confluentp :: "('a  'a  bool)  bool"
    where "confluentp r   x y1 y2. r** x y1  r** x y2  ( z. r** y1 z  r** y2 z)"

  lemma confluentpI[intro]:
    assumes " x y1 y2. r** x y1  r** x y2   z. r** y1 z  r** y2 z"
    shows "confluentp r"
    using assms
    unfolding confluentp_def
    by simp

  lemma confluentpE[elim]:
    assumes "confluentp r"
    assumes "r** x y1" "r** x y2"
    obtains z
    where "r** y1 z" "r** y2 z"
    using assms
    unfolding confluentp_def
    by blast

  lemma confluentpI'[intro]:
    assumes " x y1 y2. r** x y1  r x y2   z. r** y1 z  r** y2 z"
    shows "confluentp r"
  proof
    fix x y1 y2
    assume "r** x y1" "r** x y2"
    thus " z. r** y1 z  r** y2 z" using assms by (induct rule: rtranclp_induct, force+)
  qed

  lemma transclp_eq_implies_confluent_imp:
    assumes "r1** = r2**"
    assumes "confluentp r1"
    shows "confluentp r2"
    using assms
    by force

  lemma transclp_eq_implies_confluent_eq:
    assumes "r1** = r2**"
    shows "confluentp r1  confluentp r2"
    using assms transclp_eq_implies_confluent_imp
    by metis

  definition diamondp :: "('a  'a  bool)  bool"
    where "diamondp r   x y1 y2. r x y1  r x y2  ( z. r y1 z  r y2 z)"

  lemma diamondpI[intro]:
    assumes " x y1 y2. r x y1  r x y2   z. r y1 z  r y2 z"
    shows "diamondp r"
    using assms
    unfolding diamondp_def
    by simp

  lemma diamondpE[elim]:
    assumes "diamondp r"
    assumes "r x y1" "r x y2"
    obtains z
    where "r y1 z" "r y2 z"
    using assms
    unfolding diamondp_def
    by blast

  lemma diamondp_implies_confluentp:
    assumes "diamondp r"
    shows "confluentp r"
  proof (rule confluentpI')
    fix x y1 y2
    assume "r** x y1" "r x y2"
    hence " z. r y1 z  r** y2 z" using assms by (induct rule: rtranclp_induct, force+)
    thus " z. r** y1 z  r** y2 z" by blast
  qed

  locale wellfounded_relation =
    fixes R :: "'a  'a  bool"
    assumes wellfounded: "wfP R"

end