Skip to content

Commit 3eed349

Browse files
committed
feat(Combinatorics): Glaisher's theorem
1 parent bae412c commit 3eed349

File tree

4 files changed

+180
-0
lines changed

4 files changed

+180
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2948,6 +2948,7 @@ import Mathlib.Combinatorics.Enumerative.IncidenceAlgebra
29482948
import Mathlib.Combinatorics.Enumerative.InclusionExclusion
29492949
import Mathlib.Combinatorics.Enumerative.Partition
29502950
import Mathlib.Combinatorics.Enumerative.Partition.GenFun
2951+
import Mathlib.Combinatorics.Enumerative.Partition.Glaisher
29512952
import Mathlib.Combinatorics.Enumerative.Stirling
29522953
import Mathlib.Combinatorics.Extremal.RuzsaSzemeredi
29532954
import Mathlib.Combinatorics.Graph.Basic

Mathlib/Combinatorics/Enumerative/Partition.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ def distincts (n : ℕ) : Finset (Partition n) :=
177177
def oddDistincts (n : ℕ) : Finset (Partition n) :=
178178
odds n ∩ distincts n
179179

180+
/-- The finset of those partitions in which every part satisfies a certain condition. -/
181+
def restricted (n : ℕ) (p : ℕ → Prop) [DecidablePred p] : Finset (n.Partition) :=
182+
Finset.univ.filter fun x ↦ ∀ i ∈ x.parts, p i
183+
184+
/-- The finset of those partitions in which every part is used less than `m` times. -/
185+
def countRestricted (n : ℕ) (m : ℕ) : Finset (n.Partition) :=
186+
Finset.univ.filter fun x ↦ ∀ i ∈ x.parts, x.parts.count i < m
187+
180188
end Partition
181189

182190
end Nat
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/-
2+
Copyright (c) 2025 Weiyi Wang. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Weiyi Wang
5+
-/
6+
import Mathlib.Combinatorics.Enumerative.Partition.GenFun
7+
import Mathlib.RingTheory.PowerSeries.NoZeroDivisors
8+
9+
/-!
10+
# Glaisher's theorem
11+
12+
This file proves Glaisher's theorem: the number of partitions of an integer $n$ into parts not
13+
divisible by $d$ is equal to the number of partitions in which no part is repeated $d$ or more
14+
times.
15+
16+
## Main declarations
17+
* `Nat.Partition.card_restricted_eq_card_countRestricted`: Glaisher's theorem.
18+
19+
## References
20+
https://en.wikipedia.org/wiki/Glaisher%27s_theorem
21+
-/
22+
23+
variable (M) [TopologicalSpace M]
24+
25+
namespace PowerSeries.WithPiTopology
26+
27+
section Semiring
28+
variable [Semiring M]
29+
30+
theorem summable_X_pow_add_one_mul_add (i : ℕ) (k : ℕ) :
31+
Summable fun j ↦ (X : M⟦X⟧) ^ ((i + 1) * (j + k)) := by
32+
rcases subsingleton_or_nontrivial M with h | h
33+
· simpa [Subsingleton.eq_zero] using summable_zero
34+
apply summable_of_tendsto_order_atTop_nhds_top
35+
refine ENat.tendsto_nhds_top_iff_natCast_lt.mpr (fun n ↦ Filter.eventually_atTop.mpr ⟨n + 1, ?_⟩)
36+
intro m hm
37+
rw [order_X_pow]
38+
norm_cast
39+
nlinarith
40+
41+
end Semiring
42+
43+
section CommRing
44+
variable [CommRing M]
45+
46+
theorem multipliable_one_sub_X_pow : Multipliable fun n ↦ (1 : M⟦X⟧) - X ^ (n + 1) := by
47+
rcases subsingleton_or_nontrivial M with h | h
48+
· simpa [Subsingleton.eq_one] using multipliable_one
49+
simp_rw [sub_eq_add_neg]
50+
apply multipliable_one_add_of_tendsto_order_atTop_nhds_top
51+
refine ENat.tendsto_nhds_top_iff_natCast_lt.mpr (fun n ↦ Filter.eventually_atTop.mpr ⟨n, ?_⟩)
52+
intro m hm
53+
rw [order_neg, order_X_pow]
54+
norm_cast
55+
nlinarith
56+
57+
theorem tprod_one_sub_X_pow_ne_zero [T2Space M] [Nontrivial M] :
58+
∏' i, (1 - X ^ (i + 1)) ≠ (0 : M⟦X⟧) := by
59+
by_contra! h
60+
obtain h := PowerSeries.ext_iff.mp h 0
61+
simp [coeff_zero_eq_constantCoeff, Multipliable.map_tprod (multipliable_one_sub_X_pow M) _
62+
(WithPiTopology.continuous_constantCoeff M)] at h
63+
64+
end CommRing
65+
66+
end PowerSeries.WithPiTopology
67+
68+
namespace Nat.Partition
69+
open PowerSeries Finset
70+
open scoped PowerSeries.WithPiTopology
71+
72+
section Semiring
73+
variable [CommSemiring M]
74+
75+
/-- The generating function of `Nat.Partition.restricted n p` is
76+
$$
77+
\prod_{i \mem p} \sum_{j = 0}^{\infty} X^{ij}
78+
$$ -/
79+
theorem hasProd_powerSeriesMk_card_restricted [T2Space M] [IsTopologicalSemiring M]
80+
(p : ℕ → Prop) [DecidablePred p] :
81+
HasProd (fun i ↦ if p (i + 1) then ∑' j : ℕ, X ^ ((i + 1) * j) else 1)
82+
(PowerSeries.mk fun n ↦ (#(restricted n p) : M)) := by
83+
convert hasProd_genFun (fun i c ↦ if p i then (1 : M) else 0) using 1
84+
· ext1 i
85+
split_ifs
86+
· rw [tsum_eq_zero_add' ?_]
87+
· simp
88+
exact (WithPiTopology.summable_X_pow_add_one_mul_add M i 1)
89+
· simp
90+
· simp_rw [genFun, restricted, Finset.card_filter, Finset.prod_boole]
91+
simp
92+
93+
/-- The generating function of `Nat.Partition.countRestricted n m` is
94+
$$
95+
\prod_{i = 1}^{\infty} \sum_{j = 0}^{m - 1} X^{ij}
96+
$$ -/
97+
theorem hasProd_powerSeriesMk_card_countRestricted [T2Space M] {m : ℕ} (hm : 0 < m) :
98+
HasProd (fun i ↦ ∑ j ∈ Finset.range m, X ^ ((i + 1) * j))
99+
(PowerSeries.mk fun n ↦ (#(countRestricted n m) : M)) := by
100+
rcases subsingleton_or_nontrivial M with h | h
101+
· simp [Subsingleton.eq_one, HasProd]
102+
convert hasProd_genFun (fun i c ↦ if c < m then (1 : M) else 0) using 1
103+
· ext1 i
104+
rw [Finset.sum_range_eq_add_Ico _ hm, Finset.sum_Ico_eq_sum_range]
105+
congrm $(by simp) + ?_
106+
trans ∑ k ∈ range (m - 1), (if k + 1 < m then (1 : M) else 0) • X ^ ((i + 1) * (k + 1))
107+
· refine Finset.sum_congr rfl fun b hn ↦ ?_
108+
rw [add_comm 1 b]
109+
have : b + 1 < m := by grind
110+
simp [this]
111+
· exact (tsum_eq_sum (fun b hb ↦ smul_eq_zero_of_left (by simpa using hb) _)).symm
112+
· simp_rw [genFun, countRestricted, Finset.card_filter, Finset.prod_boole]
113+
simp
114+
115+
end Semiring
116+
117+
section Ring
118+
variable [CommRing M] [NoZeroDivisors M]
119+
120+
private theorem aux_mul_one_sub_X_pow [T2Space M] [IsTopologicalRing M] {m : ℕ} (hm : 0 < m) :
121+
(∏' i, if ¬m ∣ i + 1 then ∑' j, (X : M⟦X⟧) ^ ((i + 1) * j) else 1) *
122+
∏' i, (1 - X ^ (i + 1)) = ∏' i, (1 - X ^ ((i + 1) * m)) := by
123+
rcases subsingleton_or_nontrivial M with h | h
124+
· simp [Subsingleton.eq_one]
125+
rw [← Multipliable.tprod_mul (hasProd_powerSeriesMk_card_restricted M (¬ m ∣ ·)).multipliable
126+
(WithPiTopology.multipliable_one_sub_X_pow _)]
127+
simp_rw [ite_not, ite_mul, pow_mul]
128+
conv in fun b ↦ _ =>
129+
ext b
130+
rw [WithPiTopology.tsum_pow_mul_one_sub_of_constantCoeff_eq_zero (by simp)]
131+
refine tprod_eq_tprod_of_ne_one_bij (fun i ↦ (i.val + 1) * m - 1) ?_ ?_ ?_
132+
· intro a b h
133+
rw [tsub_left_inj (by nlinarith) (by nlinarith), mul_left_inj' (hm.ne.symm), add_left_inj] at h
134+
exact SetCoe.ext h
135+
· suffices ∀ (i : ℕ), m ∣ i + 1 → ∃ a, (a + 1) * m - 1 = i by simpa
136+
intro i hi
137+
obtain ⟨j, hj⟩ := dvd_def.mp hi
138+
refine ⟨j - 1, Nat.sub_eq_of_eq_add ?_⟩
139+
rw [hj, mul_comm m j, Nat.sub_add_cancel (by grind)]
140+
· intro i
141+
have : (i + 1) * m - 1 + 1 = (i + 1) * m := Nat.sub_add_cancel (by nlinarith)
142+
simp [this, pow_mul]
143+
144+
omit [TopologicalSpace M] in
145+
theorem powerSeriesMk_card_restricted_eq_powerSeriesMk_card_countRestricted
146+
{m : ℕ} (hm : 0 < m) :
147+
(PowerSeries.mk fun n ↦ (#(restricted n (¬ m ∣ ·)) : M)) =
148+
PowerSeries.mk fun n ↦ (#(countRestricted n m) : M) := by
149+
let _ : TopologicalSpace M := ⊥
150+
have _ : DiscreteTopology M := ⟨rfl⟩
151+
refine ((hasProd_powerSeriesMk_card_restricted M (¬ m ∣ ·)).tprod_eq.symm.trans ?_).trans
152+
(hasProd_powerSeriesMk_card_countRestricted M hm).tprod_eq
153+
rcases subsingleton_or_nontrivial M with h | h
154+
· simp [Subsingleton.eq_one]
155+
apply mul_right_cancel₀ (WithPiTopology.tprod_one_sub_X_pow_ne_zero M)
156+
apply (aux_mul_one_sub_X_pow M hm).trans
157+
rw [← Multipliable.tprod_mul (hasProd_powerSeriesMk_card_countRestricted M hm).multipliable
158+
(WithPiTopology.multipliable_one_sub_X_pow _)]
159+
exact tprod_congr (fun i ↦ by simp_rw [pow_mul, geom_sum_mul_neg])
160+
161+
end Ring
162+
163+
theorem card_restricted_eq_card_countRestricted (n : ℕ) {m : ℕ} (hm : 0 < m) :
164+
#(restricted n (¬ m ∣ ·)) = #(countRestricted n m) := by
165+
simpa using PowerSeries.ext_iff.mp
166+
(powerSeriesMk_card_restricted_eq_powerSeriesMk_card_countRestricted ℤ hm) n
167+
168+
end Nat.Partition

docs/1000.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3148,6 +3148,9 @@ Q5552370:
31483148

31493149
Q5566491:
31503150
title: Glaisher's theorem
3151+
decl: Nat.Partition.card_restricted_eq_card_countRestricted
3152+
authors: Weiyi Wang
3153+
date: 2025
31513154

31523155
Q5567394:
31533156
title: Gleason's theorem

0 commit comments

Comments
 (0)