Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 4676b31

Browse files
committed
feat(data/sym2): add the universal property, and make sym2.is_diag ⟦(x, y)⟧ ↔ x = y true definitionally (#8358)
1 parent 6ac3059 commit 4676b31

File tree

1 file changed

+44
-13
lines changed

1 file changed

+44
-13
lines changed

src/data/sym2.lean

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ test. Given `h : a ∈ z` for `z : sym2 α`, then `h.other` is the other
2222
element of the pair, defined using `classical.choice`. If `α` has
2323
decidable equality, then `h.other'` computably gives the other element.
2424
25+
The universal property of `sym2` is provided as `sym2.lift`, which
26+
states that functions from `sym2 α` are equivalent to symmetric
27+
two-argument functions from `α`.
28+
2529
Recall that an undirected graph (allowing self loops, but no multiple
2630
edges) is equivalent to a symmetric relation on the vertex type `α`.
2731
Given a symmetric relation on `α`, the corresponding edge set is
28-
constructed by `sym2.from_rel`.
32+
constructed by `sym2.from_rel` which is a special case of `sym2.lift`.
2933
3034
## Notation
3135
@@ -94,6 +98,23 @@ begin
9498
{ cases h; rw [h.1, h.2], rw eq_swap }
9599
end
96100

101+
/-- The universal property of `sym2`; symmetric functions of two arguments are equivalent to
102+
functions from `sym2`. Note that when `β` is `Prop`, it can sometimes be more convenient to use
103+
`sym2.from_rel` instead. -/
104+
def lift {β : Type*} : {f : α → α → β // ∀ a₁ a₂, f a₁ a₂ = f a₂ a₁} ≃ (sym2 α → β) :=
105+
{ to_fun := λ f, quotient.lift (uncurry ↑f) $ by { rintro _ _ ⟨⟩, exacts [rfl, f.prop _ _] },
106+
inv_fun := λ F, ⟨curry (F ∘ quotient.mk), λ a₁ a₂, congr_arg F eq_swap⟩,
107+
left_inv := λ f, subtype.ext rfl,
108+
right_inv := λ F, funext $ quotient.ind $ prod.rec $ by exact λ _ _, rfl }
109+
110+
@[simp]
111+
lemma lift_mk {β : Type*} (f : {f : α → α → β // ∀ a₁ a₂, f a₁ a₂ = f a₂ a₁}) (a₁ a₂ : α) :
112+
lift f ⟦(a₁, a₂)⟧ = (f : α → α → β) a₁ a₂ := rfl
113+
114+
@[simp]
115+
lemma coe_lift_symm_apply {β : Type*} (F : sym2 α → β) (a₁ a₂ : α) :
116+
(lift.symm F : α → α → β) a₁ a₂ = F ⟦(a₁, a₂)⟧ := rfl
117+
97118
/--
98119
The functor `sym2` is functorial, and this function constructs the induced maps.
99120
-/
@@ -200,20 +221,31 @@ def diag (x : α) : sym2 α := ⟦(x, x)⟧
200221
/--
201222
A predicate for testing whether an element of `sym2 α` is on the diagonal.
202223
-/
203-
def is_diag (z : sym2 α) : Prop := z ∈ set.range (@diag α)
224+
def is_diag : sym2 α → Prop :=
225+
lift ⟨eq, λ _ _, propext eq_comm⟩
204226

205-
@[simp]
206-
lemma diag_is_diag (a : α) : is_diag (diag a) :=
207-
by use a
227+
lemma is_diag_iff_eq {x y : α} : is_diag ⟦(x, y)⟧ ↔ x = y :=
228+
iff.rfl
208229

209230
@[simp]
210231
lemma is_diag_iff_proj_eq (z : α × α) : is_diag ⟦z⟧ ↔ z.1 = z.2 :=
232+
prod.rec_on z $ λ _ _, is_diag_iff_eq
233+
234+
@[simp]
235+
lemma diag_is_diag (a : α) : is_diag (diag a) :=
236+
eq.refl a
237+
238+
lemma is_diag.mem_range_diag {z : sym2 α} : is_diag z → z ∈ set.range (@diag α) :=
211239
begin
212-
cases z with a, split,
213-
{ rintro ⟨_, h⟩, dsimp only, erw eq_iff at h, rcases h; cc },
214-
{ rintro ⟨⟩, use a, refl },
240+
induction z using quotient.induction_on,
241+
cases z,
242+
rintro (rfl : z_fst = z_snd),
243+
exact ⟨z_fst, rfl⟩,
215244
end
216245

246+
lemma is_diag_iff_mem_range_diag (z : sym2 α) : is_diag z ↔ z ∈ set.range (@diag α) :=
247+
⟨is_diag.mem_range_diag, λ ⟨i, hi⟩, hi ▸ diag_is_diag i⟩
248+
217249
instance is_diag.decidable_pred (α : Type u) [decidable_eq α] : decidable_pred (@is_diag α) :=
218250
by { refine λ z, quotient.rec_on_subsingleton z (λ a, _), erw is_diag_iff_proj_eq, apply_instance }
219251

@@ -237,21 +269,20 @@ Symmetric relations define a set on `sym2 α` by taking all those pairs
237269
of elements that are related.
238270
-/
239271
def from_rel (sym : symmetric r) : set (sym2 α) :=
240-
quotient.lift (uncurry r) (by { rintros _ _ ⟨_, _⟩, tidy })
272+
set_of (lift ⟨r, λ x y, propext ⟨λ h, sym h, λ h, sym h⟩⟩)
241273

242274
@[simp]
243275
lemma from_rel_proj_prop {sym : symmetric r} {z : α × α} :
244276
⟦z⟧ ∈ from_rel sym ↔ r z.1 z.2 := iff.rfl
245277

246278
@[simp]
247279
lemma from_rel_prop {sym : symmetric r} {a b : α} :
248-
⟦(a, b)⟧ ∈ from_rel sym ↔ r a b := by simp only [from_rel_proj_prop]
280+
⟦(a, b)⟧ ∈ from_rel sym ↔ r a b := iff.rfl
249281

250282
lemma from_rel_irreflexive {sym : symmetric r} :
251283
irreflexive r ↔ ∀ {z}, z ∈ from_rel sym → ¬is_diag z :=
252-
{ mp := by { intros h z hr hd, induction z,
253-
erw is_diag_iff_proj_eq at hd, erw from_rel_proj_prop at hr, tidy },
254-
mpr := by { intros h x hr, rw ← @from_rel_prop _ _ sym at hr, exact h hr ⟨x, rfl⟩ }}
284+
{ mp := λ h, quotient.ind $ prod.rec $ by { rintros a b hr (rfl : a = b), exact h _ hr },
285+
mpr := λ h x hr, h (from_rel_prop.mpr hr) rfl }
255286

256287
lemma mem_from_rel_irrefl_other_ne {sym : symmetric r} (irrefl : irreflexive r)
257288
{a : α} {z : sym2 α} (hz : z ∈ from_rel sym) (h : a ∈ z) : h.other ≠ a :=

0 commit comments

Comments
 (0)