Theory Relations

theory Relations
  imports Main "HOL-Library.LaTeXsugar" "HOL-Library.OptionalSugar"
begin

section ‹Relations›

subsection ‹Basic Conditions›

text ‹We recall the standard definitions for reflexivity, symmetry, transitivity, preoders,
        equivalence, and inverse relations.›

abbreviation "preorder Rel  preorder_on UNIV Rel"
abbreviation "equivalence Rel  equiv UNIV Rel"

text ‹A symmetric preorder is an equivalence.›

lemma symm_preorder_is_equivalence:
  fixes Rel :: "('a × 'a) set"
  assumes "preorder Rel"
      and "sym Rel"
  shows "equivalence Rel"
      using assms
      unfolding preorder_on_def equiv_def
    by simp

text ‹The symmetric closure of a relation is the union of this relation and its inverse.›

definition symcl :: "('a × 'a) set  ('a × 'a) set" where
  "symcl Rel = Rel  Rel¯"

text ‹For all (a, b) in R, the symmetric closure of R contains (a, b) as well as (b, a).›

lemma elem_of_symcl:
  fixes Rel :: "('a × 'a) set"
    and a b :: "'a"
  assumes elem: "(a, b)  Rel"
  shows "(a, b)  symcl Rel"
    and "(b, a)  symcl Rel"
    by (auto simp add: elem symcl_def)

text ‹The symmetric closure of a relation is symmetric.›

lemma sym_symcl:
  fixes Rel :: "('a × 'a) set"
  shows "sym (symcl Rel)"
    by (simp add: symcl_def sym_Un_converse)

text ‹The reflexive and symmetric closure of a relation is equal to its symmetric and reflexive
        closure.›

lemma refl_symm_closure_is_symm_refl_closure:
  fixes Rel :: "('a × 'a) set"
  shows "symcl (Rel=) = (symcl Rel)="
    by (auto simp add: symcl_def refl)

text ‹The symmetric closure of a reflexive relation is reflexive.›

lemma refl_symcl_of_refl_rel:
  fixes Rel :: "('a × 'a) set"
    and A   :: "'a set"
  assumes "refl_on A Rel"
  shows "refl_on A (symcl Rel)"
      using assms
    by (auto simp add: refl_on_def' symcl_def)

text ‹Accordingly, the reflexive, symmetric, and transitive closure of a relation is equal to its
        symmetric, reflexive, and transitive closure.›

lemma refl_symm_trans_closure_is_symm_refl_trans_closure:
  fixes Rel :: "('a × 'a) set"
  shows "(symcl (Rel=))+ = (symcl Rel)*"
      using refl_symm_closure_is_symm_refl_closure[where Rel="Rel"]
    by simp

text ‹The reflexive closure of a symmetric relation is symmetric.›

lemma sym_reflcl_of_symm_rel:
  fixes Rel :: "('a × 'a) set"
  assumes "sym Rel"
  shows "sym (Rel=)"
      using assms
    by (simp add: sym_Id sym_Un)

text ‹The reflexive closure of a reflexive relation is the relation itself.›

lemma reflcl_of_refl_rel:
  fixes Rel :: "('a × 'a) set"
  assumes "refl Rel"
  shows "Rel= = Rel"
      using assms
      unfolding refl_on_def
    by auto

text ‹The symmetric closure of a symmetric relation is the relation itself.›

lemma symm_closure_of_symm_rel:
  fixes Rel :: "('a × 'a) set"
  assumes "sym Rel"
  shows "symcl Rel = Rel"
      using assms
      unfolding symcl_def sym_def
    by auto

text ‹The reflexive and transitive closure of a preorder Rel is Rel.›

lemma rtrancl_of_preorder:
  fixes Rel :: "('a × 'a) set"
  assumes "preorder Rel"
  shows "Rel* = Rel"
      using assms reflcl_of_refl_rel[of Rel] trancl_id[of "Rel="] trancl_reflcl[of Rel]
      unfolding preorder_on_def
    by auto

text ‹The reflexive and transitive closure of a relation is a subset of its reflexive, symmetric,
        and transtive closure.›

lemma refl_trans_closure_subset_of_refl_symm_trans_closure:
  fixes Rel :: "('a × 'a) set"
  shows "Rel*  (symcl (Rel=))+"
proof clarify
  fix a b
  assume "(a, b)  Rel*"
  hence "(a, b)  (symcl Rel)*"
      using in_rtrancl_UnI[of "(a, b)" "Rel" "Rel¯"]
    by (simp add: symcl_def)
  thus "(a, b)  (symcl (Rel=))+"
      using refl_symm_trans_closure_is_symm_refl_trans_closure[of Rel]
    by simp
qed

text ‹If a preorder Rel satisfies the following two conditions, then its symmetric closure is
        transitive:
        (1) If (a, b) and (c, b) in Rel but not (a, c) in Rel, then (b, a) in Rel or (b, c) in Rel.
        (2) If (a, b) and (a, c) in Rel but not (b, c) in Rel, then (b, a) in Rel or (c, a) in Rel.
›

lemma symm_closure_of_preorder_is_trans:
  fixes Rel :: "('a × 'a) set"
  assumes condA: "a b c. (a, b)  Rel  (c, b)  Rel  (a, c)  Rel
                   (b, a)  Rel  (b, c)  Rel"
      and condB: "a b c. (a, b)  Rel  (a, c)  Rel  (b, c)  Rel
                   (b, a)  Rel  (c, a)  Rel"
      and reflR: "refl Rel"
      and tranR: "trans Rel"
  shows "trans (symcl Rel)"
    unfolding trans_def
proof clarify
  fix a b c
  have "(a, b)  Rel; (b, c)  Rel  (a, c)  symcl Rel"
  proof -
    assume "(a, b)  Rel" and "(b, c)  Rel"
    with tranR have "(a, c)  Rel"
        unfolding trans_def
      by blast
    thus "(a, c)  symcl Rel"
      by (simp add: symcl_def)
  qed
  moreover have "(a, b)  Rel; (c, b)  Rel; (a, c)  Rel  (a, c)  symcl Rel"
  proof -
    assume A1: "(a, b)  Rel" and A2: "(c, b)  Rel" and "(a, c)  Rel"
    with condA have "(b, a)  Rel  (b, c)  Rel"
      by blast
    thus "(a, c)  symcl Rel"
    proof auto
      assume "(b, a)  Rel"
      with A2 tranR have "(c, a)  Rel"
          unfolding trans_def
        by blast
      thus "(a, c)  symcl Rel"
        by (simp add: symcl_def)
    next
      assume "(b, c)  Rel"
      with A1 tranR have "(a, c)  Rel"
          unfolding trans_def
        by blast
      thus "(a, c)  symcl Rel"
        by (simp add: symcl_def)
    qed
  qed
  moreover have "(b, a)  Rel; (b, c)  Rel; (a, c)  Rel  (a, c)  symcl Rel"
  proof -
    assume B1: "(b, a)  Rel" and B2: "(b, c)  Rel" and "(a, c)  Rel"
    with condB have "(a, b)  Rel  (c, b)  Rel"
      by blast
    thus "(a, c)  symcl Rel"
    proof auto
      assume "(a, b)  Rel"
      with B2 tranR have "(a, c)  Rel"
          unfolding trans_def
        by blast
      thus "(a, c)  symcl Rel"
        by (simp add: symcl_def)
    next
      assume "(c, b)  Rel"
      with B1 tranR have "(c, a)  Rel"
          unfolding trans_def
        by blast
      thus "(a, c)  symcl Rel"
        by (simp add: symcl_def)
    qed
  qed
  moreover have "(b, a)  Rel; (c, b)  Rel  (a, c)  symcl Rel"
  proof -
    assume "(c, b)  Rel" and "(b, a)  Rel"
    with tranR have "(c, a)  Rel"
        unfolding trans_def
      by blast
    thus "(a, c)  symcl Rel"
      by (simp add: symcl_def)
  qed
  moreover assume "(a, b)  symcl Rel" and "(b, c)  symcl Rel"
  ultimately show "(a, c)  symcl Rel"
    by (auto simp add: symcl_def)
qed

subsection ‹Preservation, Reflection, and Respection of Predicates›

text ‹A relation R preserves some predicate P if P(a) implies P(b) for all (a, b) in R.›

abbreviation rel_preserves_pred :: "('a × 'a) set  ('a  bool)  bool" where
  "rel_preserves_pred Rel Pred  a b. (a, b)  Rel  Pred a  Pred b"

abbreviation rel_preserves_binary_pred :: "('a × 'a) set  ('a  'b  bool)  bool" where
  "rel_preserves_binary_pred Rel Pred  a b x. (a, b)  Rel  Pred a x  Pred b x"

text ‹A relation R reflects some predicate P if P(b) implies P(a) for all (a, b) in R.›

abbreviation rel_reflects_pred :: "('a × 'a) set  ('a  bool)  bool" where
  "rel_reflects_pred Rel Pred  a b. (a, b)  Rel  Pred b  Pred a"

abbreviation rel_reflects_binary_pred :: "('a × 'a) set  ('a  'b  bool)  bool" where
  "rel_reflects_binary_pred Rel Pred  a b x. (a, b)  Rel  Pred b x  Pred a x"

text ‹A relation respects a predicate if it preserves and reflects it.›

abbreviation rel_respects_pred :: "('a × 'a) set  ('a  bool)  bool" where
  "rel_respects_pred Rel Pred  rel_preserves_pred Rel Pred  rel_reflects_pred Rel Pred"

abbreviation rel_respects_binary_pred :: "('a × 'a) set  ('a  'b  bool)  bool" where
  "rel_respects_binary_pred Rel Pred 
   rel_preserves_binary_pred Rel Pred  rel_reflects_binary_pred Rel Pred"

text ‹For symmetric relations preservation, reflection, and respection of predicates means the
        same.›

lemma symm_relation_impl_preservation_equals_reflection:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
  assumes symm: "sym Rel"
  shows "rel_preserves_pred Rel Pred = rel_reflects_pred Rel Pred"
    and "rel_preserves_pred Rel Pred = rel_respects_pred Rel Pred"
    and "rel_reflects_pred Rel Pred = rel_respects_pred Rel Pred"
      using symm
      unfolding sym_def
    by blast+

lemma symm_relation_impl_preservation_equals_reflection_of_binary_predicates:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  'b  bool"
  assumes symm: "sym Rel"
  shows "rel_preserves_binary_pred Rel Pred = rel_reflects_binary_pred Rel Pred"
    and "rel_preserves_binary_pred Rel Pred = rel_respects_binary_pred Rel Pred"
    and "rel_reflects_binary_pred Rel Pred = rel_respects_binary_pred Rel Pred"
      using symm
      unfolding sym_def
    by blast+

text ‹If a relation preserves a predicate then so does its reflexive or/and transitive closure.
›

lemma preservation_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
  assumes preservation: "rel_preserves_pred Rel Pred"
  shows "rel_preserves_pred (Rel=) Pred"
    and "rel_preserves_pred (Rel+) Pred"
    and "rel_preserves_pred (Rel*) Pred"
proof -
  from preservation show A: "rel_preserves_pred (Rel=) Pred"
    by (auto simp add: refl)
  have B: "Rel. rel_preserves_pred Rel Pred  rel_preserves_pred (Rel+) Pred"
  proof clarify
    fix Rel a b
    assume "(a, b)  Rel+" and "rel_preserves_pred Rel Pred" and "Pred a"
    thus "Pred b"
      by (induct, blast+)
  qed
  with preservation show "rel_preserves_pred (Rel+) Pred"
    by blast
  from preservation A B[where Rel="Rel="] show "rel_preserves_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by blast
qed

lemma preservation_of_binary_predicates_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  'b  bool"
  assumes preservation: "rel_preserves_binary_pred Rel Pred"
  shows "rel_preserves_binary_pred (Rel=) Pred"
    and "rel_preserves_binary_pred (Rel+) Pred"
    and "rel_preserves_binary_pred (Rel*) Pred"
proof -
  from preservation show A: "rel_preserves_binary_pred (Rel=) Pred"
    by (auto simp add: refl)
  have B: "Rel. rel_preserves_binary_pred Rel Pred
            rel_preserves_binary_pred (Rel+) Pred"
  proof clarify
    fix Rel a b x
    assume "(a, b)  Rel+" and "rel_preserves_binary_pred Rel Pred" and "Pred a x"
    thus "Pred b x"
      by (induct, blast+)
  qed
  with preservation show "rel_preserves_binary_pred (Rel+) Pred"
    by blast
  from preservation A B[where Rel="Rel="]
  show "rel_preserves_binary_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
qed

text ‹If a relation reflects a predicate then so does its reflexive or/and transitive closure.›

lemma reflection_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
  assumes reflection: "rel_reflects_pred Rel Pred"
  shows "rel_reflects_pred (Rel=) Pred"
    and "rel_reflects_pred (Rel+) Pred"
    and "rel_reflects_pred (Rel*) Pred"
proof -
  from reflection show A: "rel_reflects_pred (Rel=) Pred"
    by (auto simp add: refl)
  have B: "Rel. rel_reflects_pred Rel Pred  rel_reflects_pred (Rel+) Pred"
  proof clarify
    fix Rel a b
    assume "(a, b)  Rel+" and "rel_reflects_pred Rel Pred" and "Pred b"
    thus "Pred a"
      by (induct, blast+)
  qed
  with reflection show "rel_reflects_pred (Rel+) Pred"
    by blast
  from reflection A B[where Rel="Rel="] show "rel_reflects_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
qed

lemma reflection_of_binary_predicates_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  'b  bool"
  assumes reflection: "rel_reflects_binary_pred Rel Pred"
  shows "rel_reflects_binary_pred (Rel=) Pred"
    and "rel_reflects_binary_pred (Rel+) Pred"
    and "rel_reflects_binary_pred (Rel*) Pred"
proof -
  from reflection show A: "rel_reflects_binary_pred (Rel=) Pred"
    by (auto simp add: refl)
  have B: "Rel. rel_reflects_binary_pred Rel Pred  rel_reflects_binary_pred (Rel+) Pred"
  proof clarify
    fix Rel a b x
    assume "(a, b)  Rel+" and "rel_reflects_binary_pred Rel Pred" and "Pred b x"
    thus "Pred a x"
      by (induct, blast+)
  qed
  with reflection show "rel_reflects_binary_pred (Rel+) Pred"
    by blast
  from reflection A B[where Rel="Rel="]
  show "rel_reflects_binary_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
qed

text ‹If a relation respects a predicate then so does its reflexive, symmetric, or/and transitive
        closure.›

lemma respection_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
  assumes respection: "rel_respects_pred Rel Pred"
  shows "rel_respects_pred (Rel=) Pred"
    and "rel_respects_pred (symcl Rel) Pred"
    and "rel_respects_pred (Rel+) Pred"
    and "rel_respects_pred (symcl (Rel=)) Pred"
    and "rel_respects_pred (Rel*) Pred"
    and "rel_respects_pred ((symcl (Rel=))+) Pred"
proof -
  from respection show A: "rel_respects_pred (Rel=) Pred"
      using preservation_and_closures(1)[where Rel="Rel" and Pred="Pred"]
            reflection_and_closures(1)[where Rel="Rel" and Pred="Pred"]
    by blast
  have B: "Rel. rel_respects_pred Rel Pred  rel_respects_pred (symcl Rel) Pred"
  proof
    fix Rel
    assume B1: "rel_respects_pred Rel Pred"
    show "rel_preserves_pred (symcl Rel) Pred"
    proof clarify
      fix a b
      assume "(a, b)  symcl Rel"
      hence "(a, b)  Rel  (b, a)  Rel"
        by (simp add: symcl_def)
      moreover assume "Pred a"
      ultimately show "Pred b"
          using B1
        by blast
    qed
  next
    fix Rel  :: "('a × 'a) set"
    and Pred :: "'a  bool"
    assume B2: "rel_respects_pred Rel Pred"
    show "rel_reflects_pred (symcl Rel) Pred"
    proof clarify
      fix a b
      assume "(a, b)  symcl Rel"
      hence "(a, b)  Rel  (b, a)  Rel"
        by (simp add: symcl_def)
      moreover assume "Pred b"
      ultimately show "Pred a"
          using B2
        by blast
    qed
  qed
  from respection B[where Rel="Rel"] show "rel_respects_pred (symcl Rel) Pred"
    by blast
  have C: "Rel. rel_respects_pred Rel Pred  rel_respects_pred (Rel+) Pred"
  proof -
    fix Rel
    assume "rel_respects_pred Rel Pred"
    thus "rel_respects_pred (Rel+) Pred"
        using preservation_and_closures(2)[where Rel="Rel" and Pred="Pred"]
              reflection_and_closures(2)[where Rel="Rel" and Pred="Pred"]
      by blast
  qed
  from respection C[where Rel="Rel"] show "rel_respects_pred (Rel+) Pred"
    by blast
  from A B[where Rel="Rel="] show "rel_respects_pred (symcl (Rel=)) Pred"
    by blast
  from A C[where Rel="Rel="] show "rel_respects_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
  from A B[where Rel="Rel="] C[where Rel="symcl (Rel=)"]
  show "rel_respects_pred ((symcl (Rel=))+) Pred"
    by blast
qed

lemma respection_of_binary_predicates_and_closures:
  fixes Rel  :: "('a × 'a) set"
    and Pred :: "'a  'b  bool"
  assumes respection: "rel_respects_binary_pred Rel Pred"
  shows "rel_respects_binary_pred (Rel=) Pred"
    and "rel_respects_binary_pred (symcl Rel) Pred"
    and "rel_respects_binary_pred (Rel+) Pred"
    and "rel_respects_binary_pred (symcl (Rel=)) Pred"
    and "rel_respects_binary_pred (Rel*) Pred"
    and "rel_respects_binary_pred ((symcl (Rel=))+) Pred"
proof -
  from respection show A: "rel_respects_binary_pred (Rel=) Pred"
      using preservation_of_binary_predicates_and_closures(1)[where Rel="Rel" and Pred="Pred"]
            reflection_of_binary_predicates_and_closures(1)[where Rel="Rel" and Pred="Pred"]
    by blast
  have B: "Rel. rel_respects_binary_pred Rel Pred  rel_respects_binary_pred (symcl Rel) Pred"
  proof
    fix Rel
    assume B1: "rel_respects_binary_pred Rel Pred"
    show "rel_preserves_binary_pred (symcl Rel) Pred"
    proof clarify
      fix a b x
      assume "(a, b)  symcl Rel"
      hence "(a, b)  Rel  (b, a)  Rel"
        by (simp add: symcl_def)
      moreover assume "Pred a x"
      ultimately show "Pred b x"
          using B1
        by blast
    qed
  next
    fix Rel
    assume B2: "rel_respects_binary_pred Rel Pred"
    show "rel_reflects_binary_pred (symcl Rel) Pred"
    proof clarify
      fix a b x
      assume "(a, b)  symcl Rel"
      hence "(a, b)  Rel  (b, a)  Rel"
        by (simp add: symcl_def)
      moreover assume "Pred b x"
      ultimately show "Pred a x"
          using B2
        by blast
    qed
  qed
  from respection B[where Rel="Rel"] show "rel_respects_binary_pred (symcl Rel) Pred"
    by blast
  have C: "Rel. rel_respects_binary_pred Rel Pred  rel_respects_binary_pred (Rel+) Pred"
  proof -
    fix Rel
    assume "rel_respects_binary_pred Rel Pred"
    thus "rel_respects_binary_pred (Rel+) Pred"
        using preservation_of_binary_predicates_and_closures(2)[where Rel="Rel" and Pred="Pred"]
              reflection_of_binary_predicates_and_closures(2)[where Rel="Rel" and Pred="Pred"]
      by blast
  qed
  from respection C[where Rel="Rel"] show "rel_respects_binary_pred (Rel+) Pred"
    by blast
  from A B[where Rel="Rel="]
  show "rel_respects_binary_pred (symcl (Rel=)) Pred"
    by blast
  from A C[where Rel="Rel="]
  show "rel_respects_binary_pred (Rel*) Pred"
      using trancl_reflcl[of Rel]
    by fast
  from A B[where Rel="Rel="] C[where Rel="symcl (Rel=)"]
  show "rel_respects_binary_pred ((symcl (Rel=))+) Pred"
    by blast
qed

end