Skip to content

Commit

Permalink
feat(data/equiv/basic): add equiv.set.compl (#4630)
Browse files Browse the repository at this point in the history
Given an equivalence between two sets `e₀ : s ≃ t`, the set of
`e : α ≃ β` that agree with `e₀` on `s` is equivalent to `sᶜ ≃ tᶜ`.

Also add a bunch of lemmas to `data/set/function`; some of them are
used in the definition of `equiv.set.compl`.

Co-authored-by: Chris Hughes <chrishughes24@gmail.com>
  • Loading branch information
urkud and ChrisHughes24 committed Oct 16, 2020
1 parent b0b61e6 commit dca1393
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 7 deletions.
68 changes: 67 additions & 1 deletion src/data/equiv/basic.lean
Expand Up @@ -640,6 +640,14 @@ def sigma_preimage_equiv {α β : Type*} (f : α → β) :
@[simp] lemma sigma_preimage_equiv_symm_apply_snd_fst {α β : Type*} (f : α → β) (a : α) :
((sigma_preimage_equiv f).symm a).2.1 = a := rfl

/-- A set `s` in `α × β` is equivalent to the sigma-type `Σ x, {y | (x, y) ∈ s}`. -/
def set_prod_equiv_sigma {α β : Type*} (s : set (α × β)) :
s ≃ Σ x : α, {y | (x, y) ∈ s} :=
{ to_fun := λ x, ⟨x.1.1, x.1.2, by simp⟩,
inv_fun := λ x, ⟨(x.1, x.2.1), x.2.2⟩,
left_inv := λ ⟨⟨x, y⟩, h⟩, rfl,
right_inv := λ ⟨x, y, h⟩, rfl }

end

section sum_compl
Expand Down Expand Up @@ -1029,6 +1037,16 @@ def subtype_congr {p : α → Prop} {q : β → Prop}
λ ⟨x, h⟩, subtype.ext_val $ by simp,
λ ⟨y, h⟩, subtype.ext_val $ by simp⟩

@[simp] lemma subtype_congr_apply {p : α → Prop} {q : β → Prop} (e : α ≃ β)
(h : ∀ (a : α), p a ↔ q (e a)) (x : {x // p x}) :
e.subtype_congr h x = ⟨e x, (h _).1 x.2⟩ :=
rfl

@[simp] lemma subtype_congr_symm_apply {p : α → Prop} {q : β → Prop} (e : α ≃ β)
(h : ∀ (a : α), p a ↔ q (e a)) (y : {y // q y}) :
(e.subtype_congr h).symm y = ⟨e.symm y, (h _).2 $ (e.apply_symm_apply y).symm ▸ y.2⟩ :=
rfl

/-- If two predicates `p` and `q` are pointwise equivalent, then `{x // p x}` is equivalent to
`{x // q x}`. -/
def subtype_congr_right {p q : α → Prop} (e : ∀x, p x ↔ q x) : {x // p x} ≃ {x // q x} :=
Expand Down Expand Up @@ -1248,6 +1266,14 @@ lemma union_apply_right {α} {s t : set α} [decidable_pred (λ x, x ∈ s)] (H
{a : (s ∪ t : set α)} (ha : ↑a ∈ t) : equiv.set.union H a = sum.inr ⟨a, ha⟩ :=
dif_neg $ λ h, H ⟨h, ha⟩

@[simp] lemma union_symm_apply_left {α} {s t : set α} [decidable_pred (λ x, x ∈ s)] (H : s ∩ t ⊆ ∅)
(a : s) : (equiv.set.union H).symm (sum.inl a) = ⟨a, subset_union_left _ _ a.2⟩ :=
rfl

@[simp] lemma union_symm_apply_right {α} {s t : set α} [decidable_pred (λ x, x ∈ s)] (H : s ∩ t ⊆ ∅)
(a : t) : (equiv.set.union H).symm (sum.inr a) = ⟨a, subset_union_right _ _ a.2⟩ :=
rfl

-- TODO: Any reason to use the same universe?
/-- A singleton set is equivalent to a `punit` type. -/
protected def singleton {α} (a : α) : ({a} : set α) ≃ punit.{u} :=
Expand Down Expand Up @@ -1313,6 +1339,14 @@ lemma sum_compl_symm_apply_of_not_mem {α : Type u} {s : set α} [decidable_pred
have ↑(⟨x, or.inr hx⟩ : (s ∪ sᶜ : set α)) ∈ sᶜ, from hx,
by { rw [equiv.set.sum_compl], simpa using set.union_apply_right _ this }

@[simp] lemma sum_compl_symm_apply {α : Type*} {s : set α} [decidable_pred s] {x : s} :
(equiv.set.sum_compl s).symm x = sum.inl x :=
by cases x with x hx; exact set.sum_compl_symm_apply_of_mem hx

@[simp] lemma sum_compl_symm_apply_compl {α : Type*} {s : set α}
[decidable_pred s] {x : sᶜ} : (equiv.set.sum_compl s).symm x = sum.inr x :=
by cases x with x hx; exact set.sum_compl_symm_apply_of_not_mem hx

/-- `sum_diff_subset s t` is the natural equivalence between
`s ⊕ (t \ s)` and `t`, where `s` and `t` are two sets. -/
protected def sum_diff_subset {α} {s t : set α} (h : s ⊆ t) [decidable_pred s] :
Expand Down Expand Up @@ -1361,6 +1395,38 @@ calc (s ∪ t : set α) ⊕ (s ∩ t : set α)
end
... ≃ s ⊕ t : by { rw (_ : t \ s ∪ s ∩ t = t), rw [union_comm, inter_comm, inter_union_diff] }

/-- Given an equivalence `e₀` between sets `s : set α` and `t : set β`, the set of equivalences
`e : α ≃ β` such that `e ↑x = ↑(e₀ x)` for each `x : s` is equivalent to the set of equivalences
between `sᶜ` and `tᶜ`. -/
protected def compl {α β : Type*} {s : set α} {t : set β} [decidable_pred s] [decidable_pred t]
(e₀ : s ≃ t) : {e : α ≃ β // ∀ x : s, e x = e₀ x} ≃ ((sᶜ : set α) ≃ (tᶜ : set β)) :=
{ to_fun := λ e, subtype_congr e
(λ a, not_congr $ iff.symm $ maps_to.mem_iff
(maps_to_iff_exists_map_subtype.2 ⟨e₀, e.2⟩)
(surj_on.maps_to_compl (surj_on_iff_exists_map_subtype.2
⟨t, e₀, subset.refl t, e₀.surjective, e.2⟩) e.1.injective)),
inv_fun := λ e₁,
subtype.mk
(calc α ≃ s ⊕ (sᶜ : set α) : (set.sum_compl s).symm
... ≃ t ⊕ (tᶜ : set β) : e₀.sum_congr e₁
... ≃ β : set.sum_compl t)
(λ x, by simp only [sum.map_inl, trans_apply, sum_congr_apply,
set.sum_compl_apply_inl, set.sum_compl_symm_apply]),
left_inv := λ e,
begin
ext x,
by_cases hx : x ∈ s,
{ simp only [set.sum_compl_symm_apply_of_mem hx, ←e.prop ⟨x, hx⟩,
sum.map_inl, sum_congr_apply, trans_apply,
subtype.coe_mk, set.sum_compl_apply_inl] },
{ simp only [set.sum_compl_symm_apply_of_not_mem hx, sum.map_inr,
subtype_congr_apply, set.sum_compl_apply_inr, trans_apply,
sum_congr_apply, subtype.coe_mk] },
end,
right_inv := λ e, equiv.ext $ λ x, by simp only [sum.map_inr, subtype_congr_apply,
set.sum_compl_apply_inr, function.comp_app, sum_congr_apply, equiv.coe_trans,
subtype.coe_eta, subtype.coe_mk, set.sum_compl_symm_apply_compl] }

/-- The set product of two sets is equivalent to the type product of their coercions to types. -/
protected def prod {α β} (s : set α) (t : set β) :
s.prod t ≃ s × t :=
Expand All @@ -1377,7 +1443,7 @@ protected noncomputable def image_of_inj_on {α β} (f : α → β) (s : set α)

/-- If `f` is an injective function, then `s` is equivalent to `f '' s`. -/
protected noncomputable def image {α β} (f : α → β) (s : set α) (H : injective f) : s ≃ (f '' s) :=
equiv.set.image_of_inj_on f s (λ x y hx hy hxy, H hxy)
equiv.set.image_of_inj_on f s (H.inj_on s)

@[simp] theorem image_apply {α β} (f : α → β) (s : set α) (H : injective f) (a h) :
set.image f s H ⟨a, h⟩ = ⟨f a, mem_image_of_mem _ h⟩ := rfl
Expand Down
58 changes: 52 additions & 6 deletions src/data/set/function.lean
Expand Up @@ -106,6 +106,10 @@ subtype.map f h
@[simp] lemma maps_to.coe_restrict_apply (h : maps_to f s t) (x : s) :
(h.restrict f s t x : β) = f x := rfl

lemma maps_to_iff_exists_map_subtype : maps_to f s t ↔ ∃ g : s → t, ∀ x : s, f x = g x :=
⟨λ h, ⟨h.restrict f s t, λ _, rfl⟩,
λ ⟨g, hg⟩ x hx, by { erw [hg ⟨x, hx⟩], apply subtype.coe_prop }⟩

theorem maps_to' : maps_to f s t ↔ f '' s ⊆ t :=
image_subset_iff.symm

Expand Down Expand Up @@ -165,9 +169,16 @@ theorem maps_to_image (f : α → β) (s : set α) : maps_to f s (f '' s) := by

theorem maps_to_preimage (f : α → β) (t : set β) : maps_to f (f ⁻¹' t) t := subset.refl _

theorem maps_to_range (f : set α) (s : set α) : maps_to f s (range f) :=
theorem maps_to_range (f : α → β) (s : set α) : maps_to f s (range f) :=
(maps_to_image f s).mono (subset.refl s) (image_subset_range _ _)

theorem surjective_maps_to_image_restrict (f : α → β) (s : set α) :
surjective ((maps_to_image f s).restrict f s (f '' s)) :=
λ ⟨y, x, hs, hxy⟩, ⟨⟨x, hs⟩, subtype.ext hxy⟩

theorem maps_to.mem_iff (h : maps_to f s t) (hc : maps_to f sᶜ tᶜ) {x} : f x ∈ t ↔ x ∈ s :=
⟨λ ht, by_contra $ λ hs, hc hs ht, λ hx, h hx⟩

/-! ### Injectivity on a set -/

/-- `f` is injective on `a` if the restriction of `f` to `a` is injective. -/
Expand Down Expand Up @@ -202,6 +213,11 @@ theorem inj_on_insert {f : α → β} {s : set α} {a : α} (has : a ∉ s) :
lemma injective_iff_inj_on_univ : injective f ↔ inj_on f univ :=
⟨λ h x hx y hy hxy, h hxy, λ h _ _ heq, h trivial trivial heq⟩

lemma inj_on_of_injective (h : injective f) (s : set α) : inj_on f s :=
λ x hx y hy hxy, h hxy

alias inj_on_of_injective ← function.injective.inj_on

theorem inj_on.comp (hg : inj_on g t) (hf: inj_on f s) (h : maps_to f s t) :
inj_on (g ∘ f) s :=
λ x hx y hy heq, hf hx hy $ hg (h hx) (h hy) heq
Expand Down Expand Up @@ -229,6 +245,12 @@ lemma inj_on_preimage {B : set (set β)} (hB : B ⊆ powerset (range f)) :
theorem surj_on.subset_range (h : surj_on f s t) : t ⊆ range f :=
subset.trans h $ image_subset_range f s

lemma surj_on_iff_exists_map_subtype :
surj_on f s t ↔ ∃ (t' : set β) (g : s → t'), t ⊆ t' ∧ surjective g ∧ ∀ x : s, f x = g x :=
⟨λ h, ⟨_, (maps_to_image f s).restrict f s _, h, surjective_maps_to_image_restrict _ _, λ _, rfl⟩,
λ ⟨t', g, htt', hg, hfg⟩ y hy, let ⟨x, hx⟩ := hg ⟨y, htt' hy⟩ in
⟨x, x.2, by rw [hfg, hx, subtype.coe_mk]⟩⟩

theorem surj_on_empty (f : α → β) (s : set α) : surj_on f s ∅ := empty_subset _

theorem surj_on.comap_nonempty (h : surj_on f s t) (ht : t.nonempty) : s.nonempty :=
Expand Down Expand Up @@ -280,6 +302,12 @@ lemma surj_on.image_eq_of_maps_to (h₁ : surj_on f s t) (h₂ : maps_to f s t)
f '' s = t :=
eq_of_subset_of_subset h₂.image_subset h₁

lemma surj_on.maps_to_compl (h : surj_on f s t) (h' : injective f) : maps_to f sᶜ tᶜ :=
λ x hs ht, let ⟨x', hx', heq⟩ := h ht in hs $ h' heq ▸ hx'

lemma maps_to.surj_on_compl (h : maps_to f s t) (h' : surjective f) : surj_on f sᶜ tᶜ :=
h'.forall.2 $ λ x ht, mem_image_of_mem _ $ λ hs, ht (h hs)

/-! ### Bijectivity -/

/-- `f` is bijective from `s` to `t` if `f` is injective on `s` and `f '' s = t`. -/
Expand Down Expand Up @@ -332,10 +360,13 @@ bij_on.mk (hg.maps_to.comp hf.maps_to) (hg.inj_on.comp hf.inj_on hf.maps_to)
lemma bijective_iff_bij_on_univ : bijective f ↔ bij_on f univ univ :=
iff.intro
(λ h, let ⟨inj, surj⟩ := h in
⟨maps_to_univ f _, iff.mp injective_iff_inj_on_univ inj, iff.mp surjective_iff_surj_on_univ surj⟩)
⟨maps_to_univ f _, inj.inj_on _, iff.mp surjective_iff_surj_on_univ surj⟩)
(λ h, let ⟨map, inj, surj⟩ := h in
⟨iff.mpr injective_iff_inj_on_univ inj, iff.mpr surjective_iff_surj_on_univ surj⟩)

lemma bij_on.compl (hst : bij_on f s t) (hf : bijective f) : bij_on f sᶜ tᶜ :=
⟨hst.surj_on.maps_to_compl hf.1, hf.1.inj_on _, hst.maps_to.surj_on_compl hf.2

/-! ### left inverse -/

/-- `g` is a left inverse to `f` on `a` means that `g (f x) = x` for all `x ∈ a`. -/
Expand All @@ -361,16 +392,22 @@ calc
... = f₁' (f x₂) : congr_arg f₁' heq
... = x₂ : h h₂

theorem left_inv_on.surj_on (h : left_inv_on f' f s) (hf : maps_to f s t) : surj_on f' t s :=
theorem left_inv_on.surj_on (h : left_inv_on f' f s) (hf : maps_to f s t) : surj_on f' t s :=
λ x hx, ⟨f x, hf hx, h hx⟩

theorem left_inv_on.maps_to (h : left_inv_on f' f s) (hf : surj_on f s t) : maps_to f' t s :=
λ y hy, let ⟨x, hs, hx⟩ := hf hy in by rwa [← hx, h hs]

theorem left_inv_on.comp (hf' : left_inv_on f' f s) (hg' : left_inv_on g' g t) (hf : maps_to f s t) :
left_inv_on (f' ∘ g') (g ∘ f) s :=
λ x h,
calc
(f' ∘ g') ((g ∘ f) x) = f' (f x) : congr_arg f' (hg' (hf h))
... = x : hf' h

theorem left_inv_on.mono (hf : left_inv_on f' f s) (ht : s₁ ⊆ s) : left_inv_on f' f s₁ :=
λ x hx, hf (ht hx)

/-! ### Right inverse -/

/-- `g` is a right inverse to `f` on `b` if `f (g x) = x` for all `x ∈ b`. -/
Expand All @@ -393,10 +430,16 @@ theorem right_inv_on.surj_on (hf : right_inv_on f' f t) (hf' : maps_to f' t s) :
surj_on f s t :=
hf.surj_on hf'

theorem right_inv_on.maps_to (h : right_inv_on f' f t) (hf : surj_on f' t s) : maps_to f s t :=
h.maps_to hf

theorem right_inv_on.comp (hf : right_inv_on f' f t) (hg : right_inv_on g' g p)
(g'pt : maps_to g' p t) : right_inv_on (f' ∘ g') (g ∘ f) p :=
hg.comp hf g'pt

theorem right_inv_on.mono (hf : right_inv_on f' f t) (ht : t₁ ⊆ t) : right_inv_on f' f t₁ :=
hf.mono ht

theorem inj_on.right_inv_on_of_left_inv_on (hf : inj_on f s) (hf' : left_inv_on f f' t)
(h₁ : maps_to f s t) (h₂ : maps_to f' t s) :
right_inv_on f f' s :=
Expand All @@ -420,6 +463,12 @@ left_inv_on g f s ∧ right_inv_on g f t

lemma inv_on.symm (h : inv_on f' f s t) : inv_on f f' t s := ⟨h.right, h.left⟩

lemma inv_on.mono (h : inv_on f' f s t) (hs : s₁ ⊆ s) (ht : t₁ ⊆ t) : inv_on f' f s₁ t₁ :=
⟨h.1.mono hs, h.2.mono ht⟩

/-- If functions `f'` and `f` are inverse on `s` and `t`, `f` maps `s` into `t`, and `f'` maps `t`
into `s`, then `f` is a bijection between `s` and `t`. The `maps_to` arguments can be deduced from
`surj_on` statements using `left_inv_on.maps_to` and `right_inv_on.maps_to`. -/
theorem inv_on.bij_on (h : inv_on f' f s t) (hf : maps_to f s t) (hf' : maps_to f' t s) :
bij_on f s t :=
⟨hf, h.left.inj_on, h.right.surj_on hf'⟩
Expand Down Expand Up @@ -567,9 +616,6 @@ open set

variables {fa : α → α} {fb : β → β} {f : α → β} {g : β → γ} {s t : set α}

lemma injective.inj_on (h : injective f) (s : set α) : s.inj_on f :=
λ _ _ _ _ heq, h heq

lemma injective.comp_inj_on (hg : injective g) (hf : s.inj_on f) : s.inj_on (g ∘ f) :=
(hg.inj_on univ).comp hf (maps_to_univ _ _)

Expand Down

0 comments on commit dca1393

Please sign in to comment.