Skip to content

Commit bd32ed2

Browse files
authored
refactor: thin exists_perm_extending_strictMono via mathlib API (−46 lines) (#18)
* refactor: thin exists_perm_extending_strictMono via mathlib API Reduces the local proof from 58 lines of hand-built subtype equivalences + `Equiv.extendSubtype` to a 13-line wrapper around `Equiv.Perm.exists_extending_pair` (landed in mathlib via PR #34599) plus `Fin.castLE` / `Fin.castLE_injective` for the initial-segment inclusion. Statement is unchanged; only the proof body is touched. The single call site (`contractable_of_exchangeable`) is unaffected. - Exchangeability/Contractability.lean: -44 net lines. * docs: update Contractability docstrings to match refactored proof Two docstrings still described the old subtype-equivalence construction, which no longer matches the refactored proof body. - Module header (lines 55-58): "uses `Equiv.extendSubtype` to extend a bijection between subtypes" -> "thin wrapper around mathlib's `Equiv.Perm.exists_extending_pair`". - `exists_perm_extending_strictMono` docstring: 4-step "Construction outline" describing domain/codomain partition + manual `extendSubtype` -> short note pointing at `Equiv.Perm.exists_extending_pair` with the choice of `f` and `g`. Statement, signature, and behavior are unchanged.
1 parent 8ab88df commit bd32ed2

1 file changed

Lines changed: 15 additions & 61 deletions

File tree

Exchangeability/Contractability.lean

Lines changed: 15 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ extension argument.
5454
5555
The key technical challenge is constructing permutations that extend strictly monotone
5656
selections. Given `k : Fin m → ℕ` with `k(0) < k(1) < ... < k(m-1)`, we construct
57-
a permutation `σ : Perm (Fin n)` such that `σ(i) = k(i)` for `i < m`. This uses
58-
`Equiv.extendSubtype` to extend a bijection between subtypes to a full permutation.
57+
a permutation `σ : Perm (Fin n)` such that `σ(i) = k(i)` for `i < m`. This is a thin
58+
wrapper around mathlib's `Equiv.Perm.exists_extending_pair`.
5959
6060
## References
6161
@@ -301,11 +301,9 @@ as the image of the first `m` positions. Since `k` is strictly increasing, it's
301301
injective, so its image has cardinality `m`. We can extend this to a full
302302
permutation by arbitrarily pairing up the remaining elements.
303303
304-
**Construction outline:**
305-
1. **Domain partition:** `{0,...,m-1}` ∪ `{m,...,n-1}` = `Fin n`
306-
2. **Codomain partition:** `{k(0),...,k(m-1)}` ∪ `complement` = `Fin n`
307-
3. Map first `m` positions to `k`-values: `σ(i) = k(i)` for `i < m`
308-
4. Extend arbitrarily to remaining positions using `Equiv.extendSubtype`
304+
**Construction:** Thin wrapper around mathlib's `Equiv.Perm.exists_extending_pair`,
305+
applied to `f = Fin.castLE hmn` (initial-segment inclusion) and
306+
`g i = ⟨k i, hk_bound i⟩` (strictly monotone embedding via `k`).
309307
310308
This is the key combinatorial lemma enabling `contractable_of_exchangeable`:
311309
any strictly increasing subsequence can be realized via a permutation.
@@ -314,60 +312,16 @@ lemma exists_perm_extending_strictMono {m n : ℕ} (k : Fin m → ℕ)
314312
(hk_mono : StrictMono k) (hk_bound : ∀ i, k i < n) (hmn : m ≤ n) :
315313
∃ (σ : Equiv.Perm (Fin n)), ∀ (i : Fin m),
316314
(σ ⟨i.val, Nat.lt_of_lt_of_le i.isLt hmn⟩).val = k i := by
317-
classical
318-
-- Embed `Fin m` into `Fin n` via the initial segment.
319-
let ι : Fin m → Fin n := fun i => ⟨i.val, Nat.lt_of_lt_of_le i.isLt hmn⟩
320-
let p : Fin n → Prop := fun x => x.val < m
321-
let q : Fin n → Prop := fun x => ∃ i : Fin m, x = ⟨k i, hk_bound i⟩
322-
have hι_mem : ∀ i : Fin m, p (ι i) := fun i => i.isLt
323-
let kFin : Fin m → Fin n := fun i => ⟨k i, hk_bound i⟩
324-
have hk_mem : ∀ i : Fin m, q (kFin i) := fun i => ⟨i, rfl⟩
325-
haveI : DecidablePred p := fun x => inferInstance
326-
haveI : DecidablePred q := fun x => inferInstance
327-
-- Equivalence between the first `m` coordinates and `Fin m`.
328-
let e_dom : {x : Fin n // p x} ≃ Fin m :=
329-
{ toFun := fun x => ⟨x.1.val, x.2
330-
, invFun := fun i => ⟨ι i, by
331-
dsimp [p, ι]
332-
exact i.isLt⟩
333-
, left_inv := by
334-
rintro ⟨x, hx⟩
335-
ext; simp [ι]
336-
, right_inv := by
337-
intro i
338-
cases i with
339-
| mk i hi =>
340-
simp [ι] }
341-
-- Equivalence between the image of `k` and `Fin m`.
342-
-- For injectivity of k, we use that it's strictly monotone
343-
have hk_inj : Function.Injective kFin :=
344-
fun i j hij => hk_mono.injective (Fin.ext_iff.mp hij)
345-
let e_cod : Fin m ≃ {x : Fin n // q x} :=
346-
{ toFun := fun i => ⟨kFin i, hk_mem i⟩
347-
, invFun := fun y => Classical.choose y.2
348-
, left_inv := by
349-
intro i
350-
have h_spec := Classical.choose_spec (hk_mem i)
351-
have : k (Classical.choose (hk_mem i)) = k i := by
352-
simpa [kFin] using (Fin.ext_iff.mp h_spec).symm
353-
exact hk_mono.injective this
354-
, right_inv := by
355-
rintro ⟨y, hy⟩
356-
apply Subtype.ext
357-
simp only [kFin]
358-
exact (Classical.choose_spec hy).symm }
359-
-- Equivalence between the subtypes describing the first `m` coordinates and the image of `k`.
360-
let e : {x : Fin n // p x} ≃ {x : Fin n // q x} := e_dom.trans e_cod
361-
-- Extend this equivalence to a permutation of `Fin n`.
362-
let σ : Equiv.Perm (Fin n) := Equiv.extendSubtype e
363-
have hσ_apply : ∀ i : Fin m, σ (ι i) = kFin i := by
364-
intro i
365-
have h_apply := Equiv.extendSubtype_apply_of_mem (e:=e) (x:=ι i) (hι_mem i)
366-
dsimp [σ, e, Equiv.trans, e_dom, e_cod, ι, Fin.castLEEmb, kFin] at h_apply
367-
simpa using h_apply
368-
refine ⟨σ, fun i => ?_⟩
369-
have hσ_val : (σ (ι i)).val = k i := by simpa [kFin] using congrArg Fin.val (hσ_apply i)
370-
simpa [ι] using hσ_val
315+
-- Wrap mathlib's `Equiv.Perm.exists_extending_pair`: given injective `f g : Fin m → Fin n`,
316+
-- there is a permutation of `Fin n` sending `f` to `g`. Take `f` = initial-segment inclusion
317+
-- and `g` = the strictly monotone embedding via `k`.
318+
let f : Fin m → Fin n := Fin.castLE hmn
319+
let g : Fin m → Fin n := fun i => ⟨k i, hk_bound i⟩
320+
have hf : Function.Injective f := Fin.castLE_injective hmn
321+
have hg : Function.Injective g := fun i j hij =>
322+
hk_mono.injective (Fin.mk.inj hij)
323+
obtain ⟨σ, hσ⟩ := Equiv.Perm.exists_extending_pair f g hf hg
324+
exact ⟨σ, fun i => congrArg Fin.val (hσ i)⟩
371325

372326
/- Helper: relabeling coordinates by a finite permutation is measurable as a map
373327
from (Fin n → α) to itself (with product σ-algebra). -/

0 commit comments

Comments
 (0)