Skip to content

Commit eb0c005

Browse files
committed
feat: port Logic.Equiv.Fintype (#2524)
1 parent daa9ead commit eb0c005

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,7 @@ import Mathlib.Logic.Equiv.Basic
892892
import Mathlib.Logic.Equiv.Defs
893893
import Mathlib.Logic.Equiv.Embedding
894894
import Mathlib.Logic.Equiv.Fin
895+
import Mathlib.Logic.Equiv.Fintype
895896
import Mathlib.Logic.Equiv.List
896897
import Mathlib.Logic.Equiv.LocalEquiv
897898
import Mathlib.Logic.Equiv.MfldSimpsAttr

Mathlib/Logic/Equiv/Fintype.lean

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/-
2+
Copyright (c) 2021 Yakov Pechersky. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Yakov Pechersky
5+
6+
! This file was ported from Lean 3 source module logic.equiv.fintype
7+
! leanprover-community/mathlib commit 9407b03373c8cd201df99d6bc5514fc2db44054f
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Data.Fintype.Basic
12+
import Mathlib.GroupTheory.Perm.Sign
13+
import Mathlib.Logic.Equiv.Defs
14+
15+
/-! # Equivalence between fintypes
16+
17+
This file contains some basic results on equivalences where one or both
18+
sides of the equivalence are `Fintype`s.
19+
20+
# Main definitions
21+
22+
- `Function.Embedding.toEquivRange`: computably turn an embedding of a
23+
fintype into an `Equiv` of the domain to its range
24+
- `Equiv.Perm.viaFintypeEmbedding : Perm α → (α ↪ β) → Perm β` extends the domain of
25+
a permutation, fixing everything outside the range of the embedding
26+
27+
# Implementation details
28+
29+
- `Function.Embedding.toEquivRange` uses a computable inverse, but one that has poor
30+
computational performance, since it operates by exhaustive search over the input `Fintype`s.
31+
-/
32+
33+
34+
variable {α β : Type _} [Fintype α] [DecidableEq β] (e : Equiv.Perm α) (f : α ↪ β)
35+
36+
/-- Computably turn an embedding `f : α ↪ β` into an equiv `α ≃ Set.range f`,
37+
if `α` is a `Fintype`. Has poor computational performance, due to exhaustive searching in
38+
constructed inverse. When a better inverse is known, use `Equiv.ofLeftInverse'` or
39+
`Equiv.ofLeftInverse` instead. This is the computable version of `Equiv.ofInjective`.
40+
-/
41+
def Function.Embedding.toEquivRange : α ≃ Set.range f :=
42+
fun a => ⟨f a, Set.mem_range_self a⟩, f.invOfMemRange, fun _ => by simp, fun _ => by simp⟩
43+
#align function.embedding.to_equiv_range Function.Embedding.toEquivRange
44+
45+
@[simp]
46+
theorem Function.Embedding.toEquivRange_apply (a : α) :
47+
f.toEquivRange a = ⟨f a, Set.mem_range_self a⟩ :=
48+
rfl
49+
#align function.embedding.to_equiv_range_apply Function.Embedding.toEquivRange_apply
50+
51+
@[simp]
52+
theorem Function.Embedding.toEquivRange_symm_apply_self (a : α) :
53+
f.toEquivRange.symm ⟨f a, Set.mem_range_self a⟩ = a := by simp [Equiv.symm_apply_eq]
54+
#align function.embedding.to_equiv_range_symm_apply_self Function.Embedding.toEquivRange_symm_apply_self
55+
56+
theorem Function.Embedding.toEquivRange_eq_ofInjective :
57+
f.toEquivRange = Equiv.ofInjective f f.injective := by
58+
ext
59+
simp
60+
#align function.embedding.to_equiv_range_eq_of_injective Function.Embedding.toEquivRange_eq_ofInjective
61+
62+
/-- Extend the domain of `e : Equiv.Perm α`, mapping it through `f : α ↪ β`.
63+
Everything outside of `Set.range f` is kept fixed. Has poor computational performance,
64+
due to exhaustive searching in constructed inverse due to using `Function.Embedding.toEquivRange`.
65+
When a better `α ≃ Set.range f` is known, use `Equiv.Perm.viaSetRange`.
66+
When `[Fintype α]` is not available, a noncomputable version is available as
67+
`Equiv.Perm.viaEmbedding`.
68+
-/
69+
def Equiv.Perm.viaFintypeEmbedding : Equiv.Perm β :=
70+
e.extendDomain f.toEquivRange
71+
#align equiv.perm.via_fintype_embedding Equiv.Perm.viaFintypeEmbedding
72+
73+
@[simp]
74+
theorem Equiv.Perm.viaFintypeEmbedding_apply_image (a : α) :
75+
e.viaFintypeEmbedding f (f a) = f (e a) := by
76+
rw [Equiv.Perm.viaFintypeEmbedding]
77+
convert Equiv.Perm.extendDomain_apply_image e (Function.Embedding.toEquivRange f) a
78+
#align equiv.perm.via_fintype_embedding_apply_image Equiv.Perm.viaFintypeEmbedding_apply_image
79+
80+
theorem Equiv.Perm.viaFintypeEmbedding_apply_mem_range {b : β} (h : b ∈ Set.range f) :
81+
e.viaFintypeEmbedding f b = f (e (f.invOfMemRange ⟨b, h⟩)) := by
82+
simp only [viaFintypeEmbedding, Function.Embedding.invOfMemRange]
83+
rw [Equiv.Perm.extendDomain_apply_subtype]
84+
congr
85+
#align equiv.perm.via_fintype_embedding_apply_mem_range Equiv.Perm.viaFintypeEmbedding_apply_mem_range
86+
87+
theorem Equiv.Perm.viaFintypeEmbedding_apply_not_mem_range {b : β} (h : b ∉ Set.range f) :
88+
e.viaFintypeEmbedding f b = b := by
89+
rwa [Equiv.Perm.viaFintypeEmbedding, Equiv.Perm.extendDomain_apply_not_subtype]
90+
#align equiv.perm.via_fintype_embedding_apply_not_mem_range Equiv.Perm.viaFintypeEmbedding_apply_not_mem_range
91+
92+
@[simp]
93+
theorem Equiv.Perm.viaFintypeEmbedding_sign [DecidableEq α] [Fintype β] :
94+
Equiv.Perm.sign (e.viaFintypeEmbedding f) = Equiv.Perm.sign e := by
95+
simp [Equiv.Perm.viaFintypeEmbedding]
96+
#align equiv.perm.via_fintype_embedding_sign Equiv.Perm.viaFintypeEmbedding_sign
97+
98+
namespace Equiv
99+
100+
variable {p q : α → Prop} [DecidablePred p] [DecidablePred q]
101+
102+
/-- If `e` is an equivalence between two subtypes of a fintype `α`, `e.toCompl`
103+
is an equivalence between the complement of those subtypes.
104+
105+
See also `Equiv.compl`, for a computable version when a term of type
106+
`{e' : α ≃ α // ∀ x : {x // p x}, e' x = e x}` is known. -/
107+
noncomputable def toCompl (e : { x // p x } ≃ { x // q x }) : { x // ¬p x } ≃ { x // ¬q x } :=
108+
Classical.choice
109+
(Fintype.card_eq.mp (Fintype.card_compl_eq_card_compl _ _ (Fintype.card_congr e)))
110+
#align equiv.to_compl Equiv.toCompl
111+
112+
/-- If `e` is an equivalence between two subtypes of a fintype `α`, `e.extendSubtype`
113+
is a permutation of `α` acting like `e` on the subtypes and doing something arbitrary outside.
114+
115+
Note that when `p = q`, `Equiv.Perm.subtypeCongr e (Equiv.refl _)` can be used instead. -/
116+
noncomputable abbrev extendSubtype (e : { x // p x } ≃ { x // q x }) : Perm α :=
117+
subtypeCongr e e.toCompl
118+
#align equiv.extend_subtype Equiv.extendSubtype
119+
120+
theorem extendSubtype_apply_of_mem (e : { x // p x } ≃ { x // q x }) (x) (hx : p x) :
121+
e.extendSubtype x = e ⟨x, hx⟩ := by
122+
dsimp only [extendSubtype]
123+
simp only [subtypeCongr, Equiv.trans_apply, Equiv.sumCongr_apply]
124+
rw [sumCompl_apply_symm_of_pos _ _ hx, Sum.map_inl, sumCompl_apply_inl]
125+
#align equiv.extend_subtype_apply_of_mem Equiv.extendSubtype_apply_of_mem
126+
127+
theorem extendSubtype_mem (e : { x // p x } ≃ { x // q x }) (x) (hx : p x) :
128+
q (e.extendSubtype x) := by
129+
convert (e ⟨x, hx⟩).2
130+
rw [e.extendSubtype_apply_of_mem _ hx]
131+
#align equiv.extend_subtype_mem Equiv.extendSubtype_mem
132+
133+
theorem extendSubtype_apply_of_not_mem (e : { x // p x } ≃ { x // q x }) (x) (hx : ¬p x) :
134+
e.extendSubtype x = e.toCompl ⟨x, hx⟩ := by
135+
dsimp only [extendSubtype]
136+
simp only [subtypeCongr, Equiv.trans_apply, Equiv.sumCongr_apply]
137+
rw [sumCompl_apply_symm_of_neg _ _ hx, Sum.map_inr, sumCompl_apply_inr]
138+
#align equiv.extend_subtype_apply_of_not_mem Equiv.extendSubtype_apply_of_not_mem
139+
140+
theorem extendSubtype_not_mem (e : { x // p x } ≃ { x // q x }) (x) (hx : ¬p x) :
141+
¬q (e.extendSubtype x) := by
142+
convert (e.toCompl ⟨x, hx⟩).2
143+
rw [e.extendSubtype_apply_of_not_mem _ hx]
144+
#align equiv.extend_subtype_not_mem Equiv.extendSubtype_not_mem
145+
146+
end Equiv

0 commit comments

Comments
 (0)