Skip to content

Commit 6f5bfe8

Browse files
committed
feat(Combinatorics): Glaisher's theorem (#30618)
This proves Glaisher's theorem, one of the 1000+ theorems. It is also a generalization of [Euler's partition theorem](https://github.com/leanprover-community/mathlib4/blob/master/Archive/Wiedijk100Theorems/Partition.lean), which can be rewritten as a collorary of this (will be in a different PR)
1 parent 954f077 commit 6f5bfe8

File tree

7 files changed

+207
-16
lines changed

7 files changed

+207
-16
lines changed

Archive/Wiedijk100Theorems/Partition.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ theorem partialOddGF_prop [Field α] (n m : ℕ) :
269269
/-- If m is big enough, the partial product's coefficient counts the number of odd partitions -/
270270
theorem oddGF_prop [Field α] (n m : ℕ) (h : n < m * 2) :
271271
#(Nat.Partition.odds n) = coeff n (partialOddGF α m) := by
272-
rw [← partialOddGF_prop, Nat.Partition.odds]
272+
rw [← partialOddGF_prop, Nat.Partition.odds, Nat.Partition.restricted]
273273
congr with p
274274
apply forall₂_congr
275275
intro i hi

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3150,6 +3150,7 @@ public import Mathlib.Combinatorics.Enumerative.InclusionExclusion
31503150
public import Mathlib.Combinatorics.Enumerative.Partition
31513151
public import Mathlib.Combinatorics.Enumerative.Partition.Basic
31523152
public import Mathlib.Combinatorics.Enumerative.Partition.GenFun
3153+
public import Mathlib.Combinatorics.Enumerative.Partition.Glaisher
31533154
public import Mathlib.Combinatorics.Enumerative.Stirling
31543155
public import Mathlib.Combinatorics.Extremal.RuzsaSzemeredi
31553156
public import Mathlib.Combinatorics.Graph.Basic

Mathlib/Combinatorics/Enumerative/Partition/Basic.lean

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,16 +205,23 @@ partitions.
205205
instance (n : ℕ) : Fintype (Partition n) :=
206206
Fintype.ofSurjective (ofComposition n) ofComposition_surj
207207

208+
/-- The finset of those partitions in which every part satisfies a certain condition. -/
209+
def restricted (n : ℕ) (p : ℕ → Prop) [DecidablePred p] : Finset n.Partition :=
210+
Finset.univ.filter fun x ↦ ∀ i ∈ x.parts, p i
211+
212+
/-- The finset of those partitions in which every part is used less than `m` times. -/
213+
def countRestricted (n : ℕ) (m : ℕ) : Finset n.Partition :=
214+
Finset.univ.filter fun x ↦ ∀ i ∈ x.parts, x.parts.count i < m
215+
208216
/-- The finset of those partitions in which every part is odd. -/
209-
def odds (n : ℕ) : Finset (Partition n) :=
210-
Finset.univ.filter fun c => ∀ i ∈ c.parts, ¬Even i
217+
def odds (n : ℕ) : Finset n.Partition := restricted n (¬ Even ·)
211218

212219
/-- The finset of those partitions in which each part is used at most once. -/
213-
def distincts (n : ℕ) : Finset (Partition n) :=
220+
def distincts (n : ℕ) : Finset n.Partition :=
214221
Finset.univ.filter fun c => c.parts.Nodup
215222

216223
/-- The finset of those partitions in which every part is odd and used at most once. -/
217-
def oddDistincts (n : ℕ) : Finset (Partition n) :=
224+
def oddDistincts (n : ℕ) : Finset n.Partition :=
218225
odds n ∩ distincts n
219226

220227
end Partition

Mathlib/Combinatorics/Enumerative/Partition/GenFun.lean

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,16 @@ We give the definition `Nat.Partition.genFun` using the first equation, and prov
2222
equation in `Nat.Partition.hasProd_genFun` (with shifted indices).
2323
2424
This generating function can be specialized to
25-
* When $f(i, c) = 1$, this is the generating function for partition function $p(n)$.
25+
* When $f(i, c) = 1$, this is the generating function for partition function $p(n)$
26+
(TODO: prove this).
2627
* When $f(i, 1) = 1$ and $f(i, c) = 0$ for $c > 1$, this is the generating function for
27-
`#(Nat.Partition.distincts n)`.
28+
`#(Nat.Partition.distincts n)`. More generally, setting $f(i, c) = 1$ only for $c < m$ gives
29+
the generating function for `#(Nat.Partition.countRestricted n m)`.
30+
(See `Nat.Partition.hasProd_powerSeriesMk_card_countRestricted`).
2831
* When $f(i, c) = 1$ for odd $i$ and $f(i, c) = 0$ for even $i$, this is the generating function for
29-
`#(Nat.Partition.odds n)`.
30-
(TODO: prove these)
32+
`#(Nat.Partition.odds n)`. More generally, setting $f(i, c) = 1$ only for $i$ satisfying certain
33+
`p : Prop` gives the generating function for `#(Nat.Partition.restricted n p)`.
34+
(See `Nat.Partition.hasProd_powerSeriesMk_card_restricted`)
3135
3236
The definition of `Nat.Partition.genFun` ignores the value of $f(0, c)$ and $f(i, 0)$. The formula
3337
can be interpreted as assuming $f(i, 0) = 1$ and $f(0, c) = 0$ for $c \ne 0$. In theory we could
@@ -57,21 +61,27 @@ lemma coeff_genFun (f : ℕ → ℕ → R) (n : ℕ) :
5761
(genFun f).coeff n = ∑ p : n.Partition, p.parts.toFinsupp.prod f :=
5862
PowerSeries.coeff_mk _ _
5963

60-
variable [TopologicalSpace R]
61-
62-
/-- The infinite sum in the formula `Nat.Partition.hasProd_genFun` always converges. -/
63-
theorem summable_genFun_term (f : ℕ → ℕ → R) (i : ℕ) :
64-
Summable fun j ↦ f (i + 1) (j + 1) • (X : R⟦X⟧) ^ ((i + 1) * (j + 1)) := by
65-
nontriviality R
66-
apply WithPiTopology.summable_of_tendsto_order_atTop_nhds_top
64+
/-- The summands in the formula `Nat.Partition.hasProd_genFun` tends to infinity in their order. -/
65+
theorem tendsto_order_genFun_term_atTop_nhds_top (f : ℕ → ℕ → R) (i : ℕ) :
66+
Filter.Tendsto (fun j ↦ (f (i + 1) (j + 1) • (X : R⟦X⟧) ^ ((i + 1) * (j + 1))).order)
67+
Filter.atTop (nhds ⊤) := by
6768
refine ENat.tendsto_nhds_top_iff_natCast_lt.mpr (fun n ↦ Filter.eventually_atTop.mpr ⟨n, ?_⟩)
6869
intro m hm
6970
grw [PowerSeries.smul_eq_C_mul, ← le_order_mul]
7071
refine lt_add_of_nonneg_of_lt (by simp) ?_
72+
nontriviality R using Subsingleton.eq_zero
7173
rw [order_X_pow]
7274
norm_cast
7375
grind
7476

77+
variable [TopologicalSpace R]
78+
79+
/-- The infinite sum in the formula `Nat.Partition.hasProd_genFun` always converges. -/
80+
theorem summable_genFun_term (f : ℕ → ℕ → R) (i : ℕ) :
81+
Summable fun j ↦ f (i + 1) (j + 1) • (X : R⟦X⟧) ^ ((i + 1) * (j + 1)) := by
82+
apply WithPiTopology.summable_of_tendsto_order_atTop_nhds_top
83+
apply tendsto_order_genFun_term_atTop_nhds_top
84+
7585
/-- Alternative form of `summable_genFun_term` that unshifts the first index. -/
7686
theorem summable_genFun_term' (f : ℕ → ℕ → R) {i : ℕ} (hi : i ≠ 0) :
7787
Summable fun j ↦ f i (j + 1) • (X : R⟦X⟧) ^ (i * (j + 1)) := by
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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+
module
7+
8+
public import Mathlib.Combinatorics.Enumerative.Partition.GenFun
9+
public import Mathlib.RingTheory.PowerSeries.NoZeroDivisors
10+
11+
/-!
12+
# Glaisher's theorem
13+
14+
This file proves Glaisher's theorem: the number of partitions of an integer $n$ into parts not
15+
divisible by $d$ is equal to the number of partitions in which no part is repeated $d$ or more
16+
times.
17+
18+
## Main declarations
19+
* `Nat.Partition.card_restricted_eq_card_countRestricted`: Glaisher's theorem.
20+
21+
## References
22+
https://en.wikipedia.org/wiki/Glaisher%27s_theorem
23+
-/
24+
25+
@[expose] public section
26+
27+
variable (R) [TopologicalSpace R] [T2Space R]
28+
29+
namespace Nat.Partition
30+
open PowerSeries PowerSeries.WithPiTopology Finset
31+
32+
section Semiring
33+
variable [CommSemiring R]
34+
35+
/-- The generating function of `Nat.Partition.restricted n p` is
36+
$$
37+
\prod_{i \mem p} \sum_{j = 0}^{\infty} X^{ij}
38+
$$ -/
39+
theorem hasProd_powerSeriesMk_card_restricted [IsTopologicalSemiring R]
40+
(p : ℕ → Prop) [DecidablePred p] :
41+
HasProd (fun i ↦ if p (i + 1) then ∑' j : ℕ, X ^ ((i + 1) * j) else 1)
42+
(PowerSeries.mk fun n ↦ (#(restricted n p) : R)) := by
43+
convert hasProd_genFun (fun i c ↦ if p i then (1 : R) else 0) using 1
44+
· ext1 i
45+
split_ifs
46+
· rw [tsum_eq_zero_add' ?_]
47+
· simp
48+
simp_rw [pow_mul, pow_add]
49+
apply Summable.mul_right
50+
exact summable_pow_of_constantCoeff_eq_zero (by simp)
51+
· simp
52+
· simp_rw [genFun, restricted, card_filter, Finsupp.prod, prod_boole]
53+
simp
54+
55+
theorem multipliable_powerSeriesMk_card_restricted [IsTopologicalSemiring R]
56+
(p : ℕ → Prop) [DecidablePred p] :
57+
Multipliable (fun i ↦ if p (i + 1) then ∑' j : ℕ, (X ^ ((i + 1) * j) : R⟦X⟧) else 1) :=
58+
(hasProd_powerSeriesMk_card_restricted R p).multipliable
59+
60+
theorem powerSeriesMk_card_restricted_eq_tprod [IsTopologicalSemiring R]
61+
(p : ℕ → Prop) [DecidablePred p] :
62+
PowerSeries.mk (fun n ↦ (#(restricted n p) : R)) =
63+
∏' i, if p (i + 1) then ∑' j : ℕ, X ^ ((i + 1) * j) else 1 :=
64+
(hasProd_powerSeriesMk_card_restricted R p).tprod_eq.symm
65+
66+
/-- The generating function of `Nat.Partition.countRestricted n m` is
67+
$$
68+
\prod_{i = 1}^{\infty} \sum_{j = 0}^{m - 1} X^{ij}
69+
$$ -/
70+
theorem hasProd_powerSeriesMk_card_countRestricted {m : ℕ} (hm : 0 < m) :
71+
HasProd (fun i ↦ ∑ j ∈ range m, X ^ ((i + 1) * j))
72+
(PowerSeries.mk fun n ↦ (#(countRestricted n m) : R)) := by
73+
nontriviality R using Subsingleton.eq_one
74+
convert hasProd_genFun (fun i c ↦ if c < m then (1 : R) else 0) using 1
75+
· ext1 i
76+
rw [sum_range_eq_add_Ico _ hm, sum_Ico_eq_sum_range]
77+
congrm $(by simp) + ?_
78+
trans ∑ k ∈ range (m - 1), (if k + 1 < m then (1 : R) else 0) • X ^ ((i + 1) * (k + 1))
79+
· refine sum_congr rfl fun b hn ↦ ?_
80+
rw [add_comm 1 b]
81+
have : b + 1 < m := by grind
82+
simp [this]
83+
· exact (tsum_eq_sum (fun b hb ↦ smul_eq_zero_of_left (by simpa using hb) _)).symm
84+
· simp_rw [genFun, countRestricted, card_filter, Finsupp.prod, prod_boole]
85+
simp
86+
87+
theorem multipliable_powerSeriesMk_card_countRestricted (m : ℕ) :
88+
Multipliable fun i ↦ ∑ j ∈ range m, (X ^ ((i + 1) * j) : R⟦X⟧) := by
89+
rcases Nat.eq_zero_or_pos m with rfl | hm
90+
· simpa using multipliable_of_exists_eq_zero ⟨0, rfl⟩
91+
· exact (hasProd_powerSeriesMk_card_countRestricted R hm).multipliable
92+
93+
theorem powerSeriesMk_card_countRestricted_eq_tprod {m : ℕ} (hm : 0 < m) :
94+
PowerSeries.mk (fun n ↦ (#(countRestricted n m) : R)) =
95+
∏' i, ∑ j ∈ range m, X ^ ((i + 1) * j) :=
96+
(hasProd_powerSeriesMk_card_countRestricted R hm).tprod_eq.symm
97+
98+
end Semiring
99+
100+
section Ring
101+
variable [CommRing R] [NoZeroDivisors R]
102+
103+
private theorem aux_mul_one_sub_X_pow [IsTopologicalRing R] {m : ℕ} (hm : 0 < m) :
104+
(∏' i, if ¬m ∣ i + 1 then ∑' j, (X : R⟦X⟧) ^ ((i + 1) * j) else 1) * ∏' i, (1 - X ^ (i + 1)) =
105+
∏' i, (1 - X ^ ((i + 1) * m)) := by
106+
nontriviality R
107+
rw [← (multipliable_powerSeriesMk_card_restricted R (¬ m ∣ ·)).tprod_mul
108+
(multipliable_one_sub_X_pow _)]
109+
simp_rw [ite_not, ite_mul, pow_mul]
110+
conv in fun b ↦ _ =>
111+
ext b
112+
rw [tsum_pow_mul_one_sub_of_constantCoeff_eq_zero (by simp)]
113+
refine tprod_eq_tprod_of_ne_one_bij (fun i ↦ (i.val + 1) * m - 1) ?_ ?_ ?_
114+
· intro a b h
115+
rw [tsub_left_inj (by nlinarith) (by nlinarith), mul_left_inj' (hm.ne.symm), add_left_inj] at h
116+
exact SetCoe.ext h
117+
· suffices ∀ (i : ℕ), m ∣ i + 1 → ∃ j ≠ 0, j * m - 1 = i by simpa
118+
intro i hi
119+
obtain ⟨j, hj⟩ := dvd_def.mp hi
120+
refine ⟨j, by grind, Nat.sub_eq_of_eq_add ?_⟩
121+
rw [hj, mul_comm m j]
122+
· intro i
123+
have : (i + 1) * m - 1 + 1 = (i + 1) * m := by grind
124+
simp [this, pow_mul]
125+
126+
omit [TopologicalSpace R] in
127+
theorem powerSeriesMk_card_restricted_eq_powerSeriesMk_card_countRestricted {m : ℕ} (hm : 0 < m) :
128+
(PowerSeries.mk fun n ↦ (#(restricted n (¬ m ∣ ·)) : R)) =
129+
PowerSeries.mk fun n ↦ (#(countRestricted n m) : R) := by
130+
nontriviality R
131+
let _ : TopologicalSpace R := ⊥
132+
have _ : DiscreteTopology R := ⟨rfl⟩
133+
rw [powerSeriesMk_card_restricted_eq_tprod R (¬ m ∣ ·)]
134+
rw [powerSeriesMk_card_countRestricted_eq_tprod R hm]
135+
apply mul_right_cancel₀ (tprod_one_sub_X_pow_ne_zero R)
136+
rw [aux_mul_one_sub_X_pow R hm]
137+
rw [← (multipliable_powerSeriesMk_card_countRestricted R m).tprod_mul
138+
(multipliable_one_sub_X_pow _)]
139+
exact tprod_congr (fun i ↦ by simp_rw [pow_mul, geom_sum_mul_neg])
140+
141+
end Ring
142+
143+
theorem card_restricted_eq_card_countRestricted (n : ℕ) {m : ℕ} (hm : 0 < m) :
144+
#(restricted n (¬ m ∣ ·)) = #(countRestricted n m) := by
145+
simpa using PowerSeries.ext_iff.mp
146+
(powerSeriesMk_card_restricted_eq_powerSeriesMk_card_countRestricted ℤ hm) n
147+
148+
end Nat.Partition

Mathlib/RingTheory/PowerSeries/PiTopology.lean

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,28 @@ theorem multipliable_one_add_of_tendsto_order_atTop_nhds_top
213213

214214
end Prod
215215

216+
section ProdOneSubPow
217+
variable (R : Type*) [CommRing R] [TopologicalSpace R]
218+
219+
theorem multipliable_one_sub_X_pow : Multipliable fun n ↦ (1 : R⟦X⟧) - X ^ (n + 1) := by
220+
nontriviality R
221+
simp_rw [sub_eq_add_neg]
222+
apply multipliable_one_add_of_tendsto_order_atTop_nhds_top
223+
refine ENat.tendsto_nhds_top_iff_natCast_lt.mpr (fun n ↦ Filter.eventually_atTop.mpr ⟨n, ?_⟩)
224+
intro m hm
225+
rw [order_neg, order_X_pow]
226+
norm_cast
227+
exact Nat.lt_add_one_iff.mpr hm
228+
229+
theorem tprod_one_sub_X_pow_ne_zero [T2Space R] [Nontrivial R] :
230+
∏' i, (1 - X ^ (i + 1)) ≠ (0 : R⟦X⟧) := by
231+
by_contra! h
232+
obtain h := PowerSeries.ext_iff.mp h 0
233+
simp [coeff_zero_eq_constantCoeff, (multipliable_one_sub_X_pow R).map_tprod _
234+
(continuous_constantCoeff R)] at h
235+
236+
end ProdOneSubPow
237+
216238
end WithPiTopology
217239

218240
end Topological

docs/1000.yaml

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

31863186
Q5566491:
31873187
title: Glaisher's theorem
3188+
decl: Nat.Partition.card_restricted_eq_card_countRestricted
3189+
authors: Weiyi Wang
3190+
date: 2025
31883191

31893192
Q5567394:
31903193
title: Gleason's theorem

0 commit comments

Comments
 (0)