Skip to content

Commit 564ced7

Browse files
committed
feat(Combinatorics): Glaisher's theorem
1 parent b8d4bc6 commit 564ced7

5 files changed

Lines changed: 164 additions & 4 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3026,6 +3026,7 @@ import Mathlib.Combinatorics.Enumerative.IncidenceAlgebra
30263026
import Mathlib.Combinatorics.Enumerative.InclusionExclusion
30273027
import Mathlib.Combinatorics.Enumerative.Partition.Basic
30283028
import Mathlib.Combinatorics.Enumerative.Partition.GenFun
3029+
import Mathlib.Combinatorics.Enumerative.Partition.Glaisher
30293030
import Mathlib.Combinatorics.Enumerative.Stirling
30303031
import Mathlib.Combinatorics.Extremal.RuzsaSzemeredi
30313032
import Mathlib.Combinatorics.Graph.Basic

Mathlib/Combinatorics/Enumerative/Partition/Basic.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,14 @@ def distincts (n : ℕ) : Finset (Partition n) :=
213213
def oddDistincts (n : ℕ) : Finset (Partition n) :=
214214
odds n ∩ distincts n
215215

216+
/-- The finset of those partitions in which every part satisfies a certain condition. -/
217+
def restricted (n : ℕ) (p : ℕ → Prop) [DecidablePred p] : Finset (n.Partition) :=
218+
Finset.univ.filter fun x ↦ ∀ i ∈ x.parts, p i
219+
220+
/-- The finset of those partitions in which every part is used less than `m` times. -/
221+
def countRestricted (n : ℕ) (m : ℕ) : Finset (n.Partition) :=
222+
Finset.univ.filter fun x ↦ ∀ i ∈ x.parts, x.parts.count i < m
223+
216224
end Partition
217225

218226
end Nat

Mathlib/Combinatorics/Enumerative/Partition/GenFun.lean

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@ We give the definition `Nat.Partition.genFun` using the first equation, and prov
2020
equation in `Nat.Partition.hasProd_genFun` (with shifted indices).
2121
2222
This generating function can be specialized to
23-
* When $f(i, c) = 1$, this is the generating function for partition function $p(n)$.
23+
* When $f(i, c) = 1$, this is the generating function for partition function $p(n)$
24+
(TODO: prove this).
2425
* When $f(i, 1) = 1$ and $f(i, c) = 0$ for $c > 1$, this is the generating function for
25-
`#(Nat.Partition.distincts n)`.
26+
`#(Nat.Partition.distincts n)`. More generally, setting $f(i, c) = 1$ only for $c < m$ gives
27+
the generating function for `#(Nat.Partition.countRestricted n m)`.
28+
(See `Nat.Partition.hasProd_powerSeriesMk_card_countRestricted`).
2629
* When $f(i, c) = 1$ for odd $i$ and $f(i, c) = 0$ for even $i$, this is the generating function for
27-
`#(Nat.Partition.odds n)`.
28-
(TODO: prove these)
30+
`#(Nat.Partition.odds n)`. More generally, setting $f(i, c) = 1$ only for $i$ satisfying certain
31+
`p : Prop` gives the generating function for `#(Nat.Partition.restricted p)`.
32+
(See `Nat.Partition.hasProd_powerSeriesMk_card_restricted`)
2933
3034
The definition of `Nat.Partition.genFun` ignores the value of $f(0, c)$ and $f(i, 0)$. The formula
3135
can be interpreted as assuming $f(i, 0) = 1$ and $f(0, c) = 0$ for $c \ne 0$. In theory we could
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
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 (R) [TopologicalSpace R] [T2Space R]
24+
25+
namespace PowerSeries.WithPiTopology
26+
variable [CommRing R]
27+
28+
omit [T2Space R] in
29+
theorem multipliable_one_sub_X_pow : Multipliable fun n ↦ (1 : R⟦X⟧) - X ^ (n + 1) := by
30+
nontriviality R
31+
simp_rw [sub_eq_add_neg]
32+
apply multipliable_one_add_of_tendsto_order_atTop_nhds_top
33+
refine ENat.tendsto_nhds_top_iff_natCast_lt.mpr (fun n ↦ Filter.eventually_atTop.mpr ⟨n, ?_⟩)
34+
intro m hm
35+
rw [order_neg, order_X_pow]
36+
norm_cast
37+
exact Nat.lt_add_one_iff.mpr hm
38+
39+
theorem tprod_one_sub_X_pow_ne_zero [Nontrivial R] : ∏' i, (1 - X ^ (i + 1)) ≠ (0 : R⟦X⟧) := by
40+
by_contra! h
41+
obtain h := PowerSeries.ext_iff.mp h 0
42+
simp [coeff_zero_eq_constantCoeff, Multipliable.map_tprod (multipliable_one_sub_X_pow R) _
43+
(continuous_constantCoeff R)] at h
44+
45+
end PowerSeries.WithPiTopology
46+
47+
namespace Nat.Partition
48+
open PowerSeries PowerSeries.WithPiTopology Finset
49+
50+
section Semiring
51+
variable [CommSemiring R]
52+
53+
/-- The generating function of `Nat.Partition.restricted n p` is
54+
$$
55+
\prod_{i \mem p} \sum_{j = 0}^{\infty} X^{ij}
56+
$$ -/
57+
theorem hasProd_powerSeriesMk_card_restricted [IsTopologicalSemiring R]
58+
(p : ℕ → Prop) [DecidablePred p] :
59+
HasProd (fun i ↦ if p (i + 1) then ∑' j : ℕ, X ^ ((i + 1) * j) else 1)
60+
(PowerSeries.mk fun n ↦ (#(restricted n p) : R)) := by
61+
convert hasProd_genFun (fun i c ↦ if p i then (1 : R) else 0) using 1
62+
· ext1 i
63+
split_ifs
64+
· rw [tsum_eq_zero_add' ?_]
65+
· simp
66+
simp_rw [pow_mul, pow_add]
67+
apply Summable.mul_right
68+
exact summable_pow_of_constantCoeff_eq_zero (by simp)
69+
· simp
70+
· simp_rw [genFun, restricted, card_filter, Finsupp.prod, prod_boole]
71+
simp
72+
73+
/-- The generating function of `Nat.Partition.countRestricted n m` is
74+
$$
75+
\prod_{i = 1}^{\infty} \sum_{j = 0}^{m - 1} X^{ij}
76+
$$ -/
77+
theorem hasProd_powerSeriesMk_card_countRestricted {m : ℕ} (hm : 0 < m) :
78+
HasProd (fun i ↦ ∑ j ∈ range m, X ^ ((i + 1) * j))
79+
(PowerSeries.mk fun n ↦ (#(countRestricted n m) : R)) := by
80+
nontriviality R using Subsingleton.eq_one
81+
convert hasProd_genFun (fun i c ↦ if c < m then (1 : R) else 0) using 1
82+
· ext1 i
83+
rw [sum_range_eq_add_Ico _ hm, sum_Ico_eq_sum_range]
84+
congrm $(by simp) + ?_
85+
trans ∑ k ∈ range (m - 1), (if k + 1 < m then (1 : R) else 0) • X ^ ((i + 1) * (k + 1))
86+
· refine sum_congr rfl fun b hn ↦ ?_
87+
rw [add_comm 1 b]
88+
have : b + 1 < m := by grind
89+
simp [this]
90+
· exact (tsum_eq_sum (fun b hb ↦ smul_eq_zero_of_left (by simpa using hb) _)).symm
91+
· simp_rw [genFun, countRestricted, card_filter, Finsupp.prod, prod_boole]
92+
simp
93+
94+
end Semiring
95+
96+
section Ring
97+
variable [CommRing R] [NoZeroDivisors R]
98+
99+
private theorem aux_mul_one_sub_X_pow [IsTopologicalRing R] {m : ℕ} (hm : 0 < m) :
100+
(∏' i, if ¬m ∣ i + 1 then ∑' j, (X : R⟦X⟧) ^ ((i + 1) * j) else 1) * ∏' i, (1 - X ^ (i + 1)) =
101+
∏' i, (1 - X ^ ((i + 1) * m)) := by
102+
nontriviality R
103+
rw [← Multipliable.tprod_mul (hasProd_powerSeriesMk_card_restricted R (¬ m ∣ ·)).multipliable
104+
(multipliable_one_sub_X_pow _)]
105+
simp_rw [ite_not, ite_mul, pow_mul]
106+
conv in fun b ↦ _ =>
107+
ext b
108+
rw [tsum_pow_mul_one_sub_of_constantCoeff_eq_zero (by simp)]
109+
refine tprod_eq_tprod_of_ne_one_bij (fun i ↦ (i.val + 1) * m - 1) ?_ ?_ ?_
110+
· intro a b h
111+
rw [tsub_left_inj (by nlinarith) (by nlinarith), mul_left_inj' (hm.ne.symm), add_left_inj] at h
112+
exact SetCoe.ext h
113+
· suffices ∀ (i : ℕ), m ∣ i + 1 → ∃ j ≠ 0, j * m - 1 = i by simpa
114+
intro i hi
115+
obtain ⟨j, hj⟩ := dvd_def.mp hi
116+
refine ⟨j, by grind, Nat.sub_eq_of_eq_add ?_⟩
117+
rw [hj, mul_comm m j]
118+
· intro i
119+
have : (i + 1) * m - 1 + 1 = (i + 1) * m := by grind
120+
simp [this, pow_mul]
121+
122+
omit [TopologicalSpace R] in
123+
theorem powerSeriesMk_card_restricted_eq_powerSeriesMk_card_countRestricted {m : ℕ} (hm : 0 < m) :
124+
(PowerSeries.mk fun n ↦ (#(restricted n (¬ m ∣ ·)) : R)) =
125+
PowerSeries.mk fun n ↦ (#(countRestricted n m) : R) := by
126+
nontriviality R
127+
let _ : TopologicalSpace R := ⊥
128+
have _ : DiscreteTopology R := ⟨rfl⟩
129+
rw [← (hasProd_powerSeriesMk_card_restricted R (¬ m ∣ ·)).tprod_eq]
130+
rw [← (hasProd_powerSeriesMk_card_countRestricted R hm).tprod_eq]
131+
apply mul_right_cancel₀ (tprod_one_sub_X_pow_ne_zero R)
132+
rw [aux_mul_one_sub_X_pow R hm]
133+
rw [← Multipliable.tprod_mul (hasProd_powerSeriesMk_card_countRestricted R hm).multipliable
134+
(multipliable_one_sub_X_pow _)]
135+
exact tprod_congr (fun i ↦ by simp_rw [pow_mul, geom_sum_mul_neg])
136+
137+
end Ring
138+
139+
theorem card_restricted_eq_card_countRestricted (n : ℕ) {m : ℕ} (hm : 0 < m) :
140+
#(restricted n (¬ m ∣ ·)) = #(countRestricted n m) := by
141+
simpa using PowerSeries.ext_iff.mp
142+
(powerSeriesMk_card_restricted_eq_powerSeriesMk_card_countRestricted ℤ hm) n
143+
144+
end Nat.Partition

docs/1000.yaml

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

31793179
Q5566491:
31803180
title: Glaisher's theorem
3181+
decl: Nat.Partition.card_restricted_eq_card_countRestricted
3182+
authors: Weiyi Wang
3183+
date: 2025
31813184

31823185
Q5567394:
31833186
title: Gleason's theorem

0 commit comments

Comments
 (0)