theory Partial_Equivalence_Relation imports Main begin subsection {* Partial Equivalence Relations *} text {* The abstract datatype for a union-find structure is a partial equivalence relation. *} definition "part_equiv R ≡ sym R ∧ trans R" lemma part_equivI[intro?]: "⟦sym R; trans R⟧ ⟹ part_equiv R" by (simp add: part_equiv_def) lemma part_equiv_refl: "part_equiv R ⟹ (x,y)∈R ⟹ (x,x)∈R" "part_equiv R ⟹ (x,y)∈R ⟹ (y,y)∈R" by (metis part_equiv_def symD transD)+ lemma part_equiv_sym: "part_equiv R ⟹ (x,y)∈R ⟹ (y,x)∈R" by (metis part_equiv_def symD) lemma part_equiv_trans: "part_equiv R ⟹ (x,y)∈R ⟹ (y,z)∈R ⟹ (x,z)∈R" by (metis part_equiv_def transD) lemma part_equiv_trans_sym: "⟦ part_equiv R; (a,b)∈R; (c,b)∈R ⟧ ⟹ (a,c)∈R" "⟦ part_equiv R; (a,b)∈R; (a,c)∈R ⟧ ⟹ (b,c)∈R" apply (metis part_equiv_sym part_equiv_trans)+ done text {* We define a shortcut for symmetric closure. *} definition "symcl R ≡ R ∪ R¯" lemma sym_symcl[simp, intro!]: "sym (symcl R)" by (metis sym_Un_converse symcl_def) lemma sym_trans_is_part_equiv[simp, intro!]: "part_equiv ((symcl R)⇧*)" by (metis part_equiv_def sym_rtrancl sym_symcl trans_rtrancl) text {* We also define a shortcut for melding the equivalence classes of two given elements *} definition per_union where "per_union R a b ≡ R ∪ { (x,y). (x,a)∈R ∧ (y,b)∈R } ∪ { (y,x). (x,a)∈R ∧ (y,b)∈R }" lemma union_part_equivp: "part_equiv R ⟹ part_equiv (per_union R a b)" apply rule unfolding per_union_def apply (rule symI) apply (auto dest: part_equiv_sym) [] apply (rule transI) apply (auto dest: part_equiv_trans part_equiv_trans_sym) done lemma per_union_cmp: "⟦ part_equiv R; (l,j)∈R ⟧ ⟹ per_union R l j = R" unfolding per_union_def by (auto dest: part_equiv_trans_sym) lemma per_union_same[simp]: "part_equiv R ⟹ per_union R l l = R" unfolding per_union_def by (auto dest: part_equiv_trans_sym) lemma per_union_commute[simp]: "per_union R i j = per_union R j i" unfolding per_union_def by auto lemma per_union_dom[simp]: "Domain (per_union R i j) = Domain R" unfolding per_union_def by auto lemma per_classes_dj: "⟦part_equiv R; (i,j)∉R⟧ ⟹ R``{i} ∩ R``{j} = {}" by (auto dest: part_equiv_trans_sym) lemma per_class_in_dom: "⟦part_equiv R⟧ ⟹ R``{i} ⊆ Domain R" by (auto dest: part_equiv_trans_sym) end