Skip to content

Commit 5903e2b

Browse files
committed
feat(AlgebraicTopology/SimplexCategory/GeneratorsRelations/NormalForms): Normal forms for P_σs (#25736)
We prove that admissible lists introduced in #21744 indeed provide a suitable normal form for morphisms of `SimplexCategoryGenRel` satisfying `P_σ` (i.e that are compositions of degeneracies). To this end, we introduce `standardσ`, a construction that takes a list and turn it into a composition of `σ i`s in `SimplexCategoryGenRel`. We then prove that, thanks to the fifth simplicial identity, composition on the right by some `σ i` corresponds to simplicial insertion of `i` in the list. This gives existence of a normal form for every morphism satisfying `P_σ`, i.e exhibits such morphism as some `standardσ`. For unicity, we introduce an auxiliary function `simplicialEvalσ : (List ℕ) → ℕ → ℕ` and show that for admissible lists, it lifts to `ℕ` the `orderHom` attached to `toSimplexCategory.map standardσ` and that we can recover elements of the list only by looking at values of this function. Since admissible lists are sorted, this fully characterizes the list, and thus shows that the list only depends on the morphism `standardσ` attached to it. Part of a series of PR formalising that `SimplexCategoryGenRel` is equivalent to `SimplexCategory`.
1 parent 08f5cd2 commit 5903e2b

File tree

1 file changed

+190
-7
lines changed

1 file changed

+190
-7
lines changed

Mathlib/AlgebraicTopology/SimplexCategory/GeneratorsRelations/NormalForms.lean

Lines changed: 190 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@ Copyright (c) 2025 Robin Carlier. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Robin Carlier
55
-/
6-
import Mathlib.Tactic.Zify
7-
import Mathlib.Data.List.Sort
8-
import Mathlib.Tactic.Linarith
9-
import Mathlib.Tactic.NormNum.Ineq
10-
import Mathlib.Tactic.Ring.Basic
11-
6+
import Mathlib.AlgebraicTopology.SimplexCategory.GeneratorsRelations.EpiMono
127
/-! # Normal forms for morphisms in `SimplexCategoryGenRel`.
138
149
In this file, we establish that `P_δ` and `P_σ` morphisms in `SimplexCategoryGenRel`
@@ -34,12 +29,13 @@ stones towards proving that the canonical functor
3429
* [Kerodon Tag 04FT](https://kerodon.net/tag/04FT)
3530
3631
## TODOs:
37-
- Show that every `P_σ` admits a unique normal form.
3832
- Show that every `P_δ` admits a unique normal form.
3933
-/
4034

4135
namespace SimplexCategoryGenRel
4236

37+
open CategoryTheory
38+
4339
section AdmissibleLists
4440
-- Impl. note: We are not bundling admissible lists as a subtype of `List ℕ` so that it remains
4541
-- easier to perform inductive constructions and proofs on such lists, and we instead bundle
@@ -155,4 +151,191 @@ theorem simplicialInsert_isAdmissible (L : List ℕ) (hL : IsAdmissible (m + 1)
155151

156152
end AdmissibleLists
157153

154+
section NormalFormsP_σ
155+
156+
-- Impl note.: The definition is a bit awkward with the extra parameters, but this
157+
-- is necessary in order to avoid some type theory hell when proving that `orderedInsert`
158+
-- behaves as expected...
159+
160+
/-- Given a sequence `L = [ i 0, ..., i b ]`, `standardσ m L` i is the morphism
161+
`σ (i b) ≫ … ≫ σ (i 0)`. The construction is provided for any list of natural numbers,
162+
but it is intended to behave well only when the list is admissible. -/
163+
def standardσ (L : List ℕ) {m₁ m₂ : ℕ} (h : m₂ + L.length = m₁) : mk m₁ ⟶ mk m₂ :=
164+
match L with
165+
| .nil => eqToHom (by grind)
166+
| .cons a t => standardσ t (by grind) ≫ σ (Fin.ofNat _ a)
167+
168+
@[simp]
169+
lemma standardσ_nil (m : ℕ) : standardσ .nil (by grind) = 𝟙 (mk m) := rfl
170+
171+
@[simp, reassoc]
172+
lemma standardσ_cons (L : List ℕ) (a : ℕ) {m₁ m₂ : ℕ} (h : m₂ + (a :: L).length = m₁) :
173+
standardσ (L.cons a) h = standardσ L (by grind) ≫ σ (Fin.ofNat _ a) := rfl
174+
175+
@[reassoc]
176+
lemma standardσ_comp_standardσ (L₁ L₂ : List ℕ) {m₁ m₂ m₃ : ℕ}
177+
(h : m₂ + L₁.length = m₁) (h' : m₃ + L₂.length = m₂) :
178+
standardσ L₁ h ≫ standardσ L₂ h' = standardσ (L₂ ++ L₁) (by grind) := by
179+
induction L₂ generalizing L₁ m₁ m₂ m₃ with
180+
| nil =>
181+
obtain rfl : m₃ = m₂ := by grind
182+
simp
183+
| cons a t H =>
184+
dsimp at h' ⊢
185+
obtain rfl : m₂ = (m₃ + t.length) + 1 := by grind
186+
simp [reassoc_of% (H L₁ (m₁ := m₁) (m₂ := m₃ + t.length + 1) (m₃ := m₃ + 1)
187+
(by grind) (by grind))]
188+
189+
variable (m : ℕ) (L : List ℕ)
190+
191+
/-- `simplicialEvalσ` is a lift to ℕ of `(toSimplexCategory.map (standardσ m L _ _)).toOrderHom`.
192+
Rather than defining it as such, we define it inductively for less painful inductive reasoning,
193+
(see `simplicialEvalσ_of_isAdmissible`).
194+
It is expected to produce the correct result only if `L` is admissible, and values for
195+
non-admissible lists should be considered junk values. Similarly, values for out-of-bonds inputs
196+
are junk values. -/
197+
def simplicialEvalσ (L : List ℕ) : ℕ → ℕ :=
198+
fun j ↦ match L with
199+
| [] => j
200+
| a :: L => if a < simplicialEvalσ L j then simplicialEvalσ L j - 1 else simplicialEvalσ L j
201+
202+
lemma simplicialEvalσ_of_lt_mem (j : ℕ) (hj : ∀ k ∈ L, j ≤ k) : simplicialEvalσ L j = j := by
203+
induction L with
204+
| nil => grind [simplicialEvalσ]
205+
| cons _ _ _ =>
206+
simp only [List.mem_cons, forall_eq_or_imp] at hj
207+
grind [simplicialEvalσ]
208+
209+
lemma simplicialEvalσ_monotone (L : List ℕ) : Monotone (simplicialEvalσ L) := by
210+
intro a b hab
211+
induction L generalizing a b with
212+
| nil => exact hab
213+
| cons head tail h_rec => grind [simplicialEvalσ]
214+
215+
variable {m}
216+
/- We prove that `simplicialEvalσ` is indeed a lift of
217+
`(toSimplexCategory.map (standardσ m L _ _)).toOrderHom` when the list is admissible. -/
218+
lemma simplicialEvalσ_of_isAdmissible
219+
(m₁ m₂ : ℕ) (hL : IsAdmissible m₂ L) (hk : m₂ + L.length = m₁)
220+
(j : ℕ) (hj : j < m₁ + 1) :
221+
(toSimplexCategory.map <| standardσ L hk).toOrderHom ⟨j, hj⟩ =
222+
simplicialEvalσ L j := by
223+
induction L generalizing m₁ m₂ with
224+
| nil =>
225+
obtain rfl : m₁ = m₂ := by grind
226+
simp [simplicialEvalσ]
227+
| cons a L h_rec =>
228+
simp only [List.length_cons] at hk
229+
subst hk
230+
set a₀ := hL.head
231+
have aux (t : Fin (m₂ + 2)) :
232+
(a₀.predAbove t : ℕ) = if a < ↑t then (t : ℕ) - 1 else ↑t := by
233+
simp only [Fin.predAbove, a₀]
234+
split_ifs with h₁ h₂ h₂
235+
· rfl
236+
· simp only [Fin.lt_def, Fin.coe_castSucc, IsAdmissible.head_val] at h₁; grind
237+
· simp only [Fin.lt_def, Fin.coe_castSucc, IsAdmissible.head_val, not_lt] at h₁; grind
238+
· rfl
239+
have := h_rec _ _ hL.tail (by grind) hj
240+
have ha₀ : Fin.ofNat (m₂ + 1) a = a₀ := by ext; simpa [a₀] using hL.head.prop
241+
simpa only [toSimplexCategory_obj_mk, SimplexCategory.len_mk, standardσ_cons, Functor.map_comp,
242+
toSimplexCategory_map_σ, SimplexCategory.σ, SimplexCategory.mkHom,
243+
SimplexCategory.comp_toOrderHom, SimplexCategory.Hom.toOrderHom_mk, OrderHom.comp_coe,
244+
Function.comp_apply, Fin.predAboveOrderHom_coe, simplicialEvalσ, ha₀, ← this] using aux _
245+
246+
/-- Performing a simplicial insertion in a list is the same as composition on the right by the
247+
corresponding degeneracy operator. -/
248+
lemma standardσ_simplicialInsert (hL : IsAdmissible (m + 1) L) (j : ℕ) (hj : j < m + 1)
249+
(m₁ : ℕ) (hm₁ : m + L.length + 1 = m₁) :
250+
standardσ (m₂ := m) (simplicialInsert j L) (m₁ := m₁)
251+
(by simpa only [simplicialInsert_length, add_assoc]) =
252+
standardσ (m₂ := m + 1) L (by grind) ≫ σ (Fin.ofNat _ j) := by
253+
induction L generalizing m j with
254+
| nil => simp [standardσ, simplicialInsert]
255+
| cons a L h_rec =>
256+
simp only [simplicialInsert]
257+
split_ifs
258+
· simp
259+
· have : ∀ (j k : ℕ) (h : j < (k + 1)), Fin.ofNat (k + 1) j = j := by simp -- helps grind below
260+
have : a < m + 2 := by grind -- helps grind below
261+
have : σ (Fin.ofNat (m + 2) a) ≫ σ (.ofNat _ j) = σ (.ofNat _ (j + 1)) ≫ σ (.ofNat _ a) := by
262+
convert σ_comp_σ_nat (n := m) a j (by grind) (by grind) (by grind) <;> grind
263+
simp only [standardσ_cons, Category.assoc, this,
264+
h_rec hL.tail (j + 1) (by grind) (by grind)]
265+
266+
attribute [local grind] simplicialInsert_length simplicialInsert_isAdmissible in
267+
/-- Using `standardσ_simplicialInsert`, we can prove that every morphism satisfying `P_σ` is equal
268+
to some `standardσ` for some admissible list of indices. -/
269+
theorem exists_normal_form_P_σ {x y : SimplexCategoryGenRel} (f : x ⟶ y) (hf : P_σ f) :
270+
∃ L : List ℕ,
271+
∃ m : ℕ, ∃ b : ℕ,
272+
∃ h₁ : mk m = y, ∃ h₂ : x = mk (m + b), ∃ h : L.length = b,
273+
IsAdmissible m L ∧ f = standardσ L (by rw [h, h₁.symm, h₂]; rfl) := by
274+
induction hf with
275+
| id n =>
276+
use [], n.len, 0, rfl, rfl, rfl, IsAdmissible.nil _
277+
rfl
278+
| of f hf =>
279+
cases hf with | @σ m k =>
280+
use [k.val], m, 1 , rfl, rfl, rfl
281+
constructor <;> simp [IsAdmissible, Nat.le_of_lt_add_one k.prop, standardσ]
282+
| @comp_of _ j x' g g' hg hg' h_rec =>
283+
cases hg' with | @σ m k =>
284+
obtain ⟨L₁, m₁, b₁, h₁', rfl, h', hL₁, e₁⟩ := h_rec
285+
obtain rfl : m₁ = m + 1 := congrArg (fun x ↦ x.len) h₁'
286+
use simplicialInsert k.val L₁, m, b₁ + 1, rfl, by grind, by grind, by grind
287+
subst_vars
288+
have := standardσ (m₁ := m + 1 + L₁.length) [] (by grind) ≫=
289+
(standardσ_simplicialInsert L₁ hL₁ k k.prop _ rfl).symm
290+
simp_all [Fin.ofNat_eq_cast, Fin.cast_val_eq_self, standardσ_comp_standardσ_assoc,
291+
standardσ_comp_standardσ]
292+
293+
section MemIsAdmissible
294+
295+
lemma mem_isAdmissible_of_lt_and_eval_eq_eval_add_one (hL : IsAdmissible m L)
296+
(j : ℕ) (hj₁ : j < m + L.length) (hj₂ : simplicialEvalσ L j = simplicialEvalσ L (j + 1)) :
297+
j ∈ L := by
298+
induction L generalizing m with
299+
| nil => grind [simplicialEvalσ]
300+
| cons a L h_rec =>
301+
have := h_rec hL.tail (by grind)
302+
suffices ¬j = a → (simplicialEvalσ L j = simplicialEvalσ L (j + 1)) by grind
303+
intro hja
304+
simp only [simplicialEvalσ] at hj₂
305+
have : simplicialEvalσ L j ≤ simplicialEvalσ L (j + 1) :=
306+
simplicialEvalσ_monotone L (by grind)
307+
suffices ¬a < simplicialEvalσ L j → a < simplicialEvalσ L (j + 1) →
308+
simplicialEvalσ L j = simplicialEvalσ L (j + 1) - 1
309+
simplicialEvalσ L j = simplicialEvalσ L (j + 1) by grind
310+
intro h₁ h₂ hj₂
311+
simp only [IsAdmissible, List.sorted_cons, List.length_cons] at hL
312+
obtain h | rfl | h := Nat.lt_trichotomy j a
313+
· grind [simplicialEvalσ_monotone, Monotone, simplicialEvalσ_of_lt_mem]
314+
· grind
315+
· have := simplicialEvalσ_of_lt_mem L (a + 1) <| fun x h ↦ hL.1.1 x h
316+
grind [simplicialEvalσ_monotone, Monotone]
317+
318+
lemma lt_and_eval_eq_eval_add_one_of_mem_isAdmissible (hL : IsAdmissible m L) (j : ℕ) (hj : j ∈ L) :
319+
j < m + L.length ∧ simplicialEvalσ L j = simplicialEvalσ L (j + 1) := by
320+
induction L generalizing m with
321+
| nil => grind
322+
| cons a L h_rec =>
323+
constructor
324+
· grind [List.mem_iff_getElem, IsAdmissible, List.sorted_cons]
325+
· obtain rfl | h := List.mem_cons.mp hj
326+
· grind [simplicialEvalσ_of_lt_mem, simplicialEvalσ, IsAdmissible, List.sorted_cons]
327+
· have := h_rec hL.tail h
328+
grind [simplicialEvalσ]
329+
330+
/-- We can characterize elements in an admissible list as exactly those for which
331+
`simplicialEvalσ` takes the same value twice in a row. -/
332+
lemma mem_isAdmissible_iff (hL : IsAdmissible m L) (j : ℕ) :
333+
j ∈ L ↔ j < m + L.length ∧ simplicialEvalσ L j = simplicialEvalσ L (j + 1) := by
334+
grind [lt_and_eval_eq_eval_add_one_of_mem_isAdmissible,
335+
mem_isAdmissible_of_lt_and_eval_eq_eval_add_one]
336+
337+
end MemIsAdmissible
338+
339+
end NormalFormsP_σ
340+
158341
end SimplexCategoryGenRel

0 commit comments

Comments
 (0)