|
| 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 |
| 7 | +import Mathlib.RingTheory.PowerSeries.PiTopology |
| 8 | + |
| 9 | +/-! |
| 10 | +# Generating functions for partition functions |
| 11 | +
|
| 12 | +This file defines generating functions related to partitions. Given a character function $f(i, c)$ |
| 13 | +of a part $i$ and the number of the part $c$, the related generating function is |
| 14 | +$$ |
| 15 | +G_f(X) = \sum_{n = 0}^{\infty} \left(\sum_{p \in P_{n}} \prod_{i \in p} f(i, \#i)\right) X^n |
| 16 | += \prod_{i = 0}^{\infty}\left(1 + \sum_{j=0}^{\infty} f(i + 1, j + 1) X ^ {(i + 1)(j + 1)}\right) |
| 17 | +$$ |
| 18 | +where $P_n$ is all partitions of $n$, $\#i$ is the times $i$ appears in the partition $p$. |
| 19 | +We give the definition `Nat.Partition.genFun` using the first equation, and prove the second |
| 20 | +equation in `Nat.Partition.hasProd_genFun`. |
| 21 | +
|
| 22 | +This generating function can be specialized to |
| 23 | +* When $f(i, c) = 1$, this is the generating function for partition function $p(n)$. |
| 24 | +* 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 | +* 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) |
| 29 | +
|
| 30 | +The definition of `Nat.Partition.genFun` ignores the value of $f(0, c)$ and $f(i, 0)$. The formula |
| 31 | +can be interpreted as assuming $f(i, 0) = 1$ and $f(0, c) = 0$ for $c \ne 0$. In theory we could |
| 32 | +respect the actual value of $f(0, c)$ and $f(i, 0)$, but it makes the otherwise finite sum and |
| 33 | +product potentially infinite. |
| 34 | +-/ |
| 35 | + |
| 36 | +open PowerSeries |
| 37 | +open scoped PowerSeries.WithPiTopology |
| 38 | + |
| 39 | +namespace Nat.Partition |
| 40 | +variable {M : Type*} [CommSemiring M] |
| 41 | + |
| 42 | +/-- Generating function associated with character $f(i, c)$ for partition functions. The character |
| 43 | +function is multiplied within one `n.Partition`, and summed among all `n.Partition` for |
| 44 | +a fixed `n`. -/ |
| 45 | +def genFun (f : ℕ → ℕ → M) : M⟦X⟧ := |
| 46 | + PowerSeries.mk fun n ↦ ∑ p : n.Partition, ∏ i ∈ p.parts.toFinset, f i (p.parts.count i) |
| 47 | + |
| 48 | +variable [TopologicalSpace M] |
| 49 | + |
| 50 | +/-- The infinite sum in the formula `Nat.Partition.hasProd_genFun` always converges. -/ |
| 51 | +theorem summable_genFun_term (f : ℕ → ℕ → M) (i : ℕ) : |
| 52 | + Summable fun j ↦ f (i + 1) (j + 1) • (X : M⟦X⟧) ^ ((i + 1) * (j + 1)) := by |
| 53 | + rcases subsingleton_or_nontrivial M with h | h |
| 54 | + · simpa [Subsingleton.eq_zero] using summable_zero |
| 55 | + apply WithPiTopology.summable_of_tendsto_order_atTop_nhds_top |
| 56 | + refine ENat.tendsto_nhds_top_iff_natCast_lt.mpr (fun n ↦ Filter.eventually_atTop.mpr ⟨n, ?_⟩) |
| 57 | + intro m hm |
| 58 | + rw [PowerSeries.smul_eq_C_mul] |
| 59 | + refine (lt_of_lt_of_le (lt_add_of_nonneg_of_lt (by simp) ?_) (le_order_mul _ _)) |
| 60 | + rw [order_X_pow] |
| 61 | + norm_cast |
| 62 | + grind |
| 63 | + |
| 64 | +variable [T2Space M] |
| 65 | + |
| 66 | +private theorem aux_injOn_sub_one_parts {n : ℕ} (p : Partition n) : |
| 67 | + Set.InjOn (fun x ↦ x - 1) p.parts.toFinset := by |
| 68 | + intro a ha b hb |
| 69 | + exact tsub_inj_left (p.parts_pos (by simpa using ha)) (p.parts_pos (by simpa using hb)) |
| 70 | + |
| 71 | +private theorem aux_map_sub_one_parts_subset {n : ℕ} (p : Partition n) : |
| 72 | + (Multiset.map (fun x ↦ x - 1) p.parts).toFinset ⊆ Finset.range n := by |
| 73 | + intro m |
| 74 | + rw [Multiset.mem_toFinset, Finset.mem_range] |
| 75 | + suffices ∀ x ∈ p.parts, x - 1 = m → m < n by simpa |
| 76 | + rintro x h1 rfl |
| 77 | + exact Nat.sub_one_lt_of_le (p.parts_pos h1) (le_of_mem_parts h1) |
| 78 | + |
| 79 | +private theorem aux_mapsTo_sub_one_parts {n : ℕ} (p : Partition n) : |
| 80 | + Set.MapsTo (fun x ↦ x - 1) p.parts.toFinset (Finset.range n) := by |
| 81 | + intro a ha |
| 82 | + apply Finset.mem_of_subset (aux_map_sub_one_parts_subset p) |
| 83 | + rw [Multiset.mem_toFinset, Multiset.mem_map] |
| 84 | + exact ⟨a, by simpa using ha⟩ |
| 85 | + |
| 86 | +private def aux_toFinsuppAntidiag {n : ℕ} (p : Partition n) : ℕ →₀ ℕ where |
| 87 | + toFun m := p.parts.count (m + 1) * (m + 1) |
| 88 | + support := (p.parts.map (· - 1)).toFinset |
| 89 | + mem_support_toFun m := by |
| 90 | + suffices (∃ a ∈ p.parts, a - 1 = m) ↔ m + 1 ∈ p.parts by simpa |
| 91 | + trans (∃ a ∈ p.parts, a = m + 1) |
| 92 | + · refine ⟨fun ⟨a, h1, h2⟩ ↦ ⟨a, h1, ?_⟩, fun ⟨a, h1, h2⟩ ↦ ⟨a, h1, Nat.sub_eq_of_eq_add h2⟩⟩ |
| 93 | + exact Nat.eq_add_of_sub_eq (Nat.one_le_of_lt (p.parts_pos h1)) h2 |
| 94 | + · simp |
| 95 | + |
| 96 | +private theorem aux_toFinsuppAntidiag_injective (n : ℕ) : |
| 97 | + Function.Injective (aux_toFinsuppAntidiag (n := n)) := by |
| 98 | + unfold aux_toFinsuppAntidiag |
| 99 | + intro p q h |
| 100 | + rw [Finsupp.mk.injEq] at h |
| 101 | + obtain ⟨hfinset, hcount⟩ := h |
| 102 | + rw [Nat.Partition.ext_iff, Multiset.ext] |
| 103 | + intro m |
| 104 | + obtain rfl | h0 := Nat.eq_zero_or_pos m |
| 105 | + · trans 0 |
| 106 | + · rw [Multiset.count_eq_zero] |
| 107 | + exact fun h ↦ (lt_self_iff_false _).mp <| p.parts_pos h |
| 108 | + · symm |
| 109 | + rw [Multiset.count_eq_zero] |
| 110 | + exact fun h ↦ (lt_self_iff_false _).mp <| q.parts_pos h |
| 111 | + · refine Nat.eq_of_mul_eq_mul_right h0 <| ?_ |
| 112 | + convert funext_iff.mp hcount (m - 1) <;> exact (Nat.sub_eq_iff_eq_add h0).mp rfl |
| 113 | + |
| 114 | +private theorem aux_range_toFinsuppAntidiag (n : ℕ) : |
| 115 | + Set.range (aux_toFinsuppAntidiag (n := n)) ⊆ (Finset.range n).finsuppAntidiag n := by |
| 116 | + unfold aux_toFinsuppAntidiag |
| 117 | + rw [Set.range_subset_iff] |
| 118 | + intro p |
| 119 | + suffices ∑ m ∈ Finset.range n, Multiset.count (m + 1) p.parts * (m + 1) = n by |
| 120 | + simpa [aux_map_sub_one_parts_subset p] |
| 121 | + refine Eq.trans ?_ p.parts_sum |
| 122 | + simp_rw [Finset.sum_multiset_count, smul_eq_mul] |
| 123 | + refine (Finset.sum_of_injOn (· - 1) (aux_injOn_sub_one_parts p) |
| 124 | + (aux_mapsTo_sub_one_parts p) ?_ ?_).symm |
| 125 | + · suffices ∀ i ∈ Finset.range n, (∀ x ∈ p.parts, x - 1 ≠ i) → i + 1 ∉ p.parts by simpa |
| 126 | + intro i hi h |
| 127 | + contrapose! h |
| 128 | + exact ⟨i + 1, by simpa using h⟩ |
| 129 | + · intro i hi |
| 130 | + suffices i - 1 + 1 = i by simp [this] |
| 131 | + rw [Nat.sub_add_cancel (Nat.one_le_of_lt (p.parts_pos (by simpa using hi)))] |
| 132 | + |
| 133 | +private theorem aux_dvd_of_coeff_ne_zero {f : ℕ → ℕ → M} {d : ℕ} {s : Finset ℕ} |
| 134 | + {g : ℕ →₀ ℕ} (hg : g ∈ s.finsuppAntidiag d) |
| 135 | + (hprod : ∀ x ∈ s, |
| 136 | + (coeff (g x)) (1 + ∑' (j : ℕ), f (x + 1) (j + 1) • X ^ ((x + 1) * (j + 1))) ≠ (0 : M)) |
| 137 | + (x : ℕ) : x + 1 ∣ g x := by |
| 138 | + by_cases hx : x ∈ s |
| 139 | + · specialize hprod x hx |
| 140 | + contrapose! hprod |
| 141 | + rw [map_add, (summable_genFun_term f x).map_tsum _ (WithPiTopology.continuous_coeff _ _)] |
| 142 | + rw [show (0 : M) = 0 + ∑' (i : ℕ), 0 by simp] |
| 143 | + congrm (?_ + ∑' (i : ℕ), ?_) |
| 144 | + · suffices g x ≠ 0 by simp [this] |
| 145 | + contrapose! hprod |
| 146 | + simp [hprod] |
| 147 | + · rw [map_smul, coeff_X_pow] |
| 148 | + apply smul_eq_zero_of_right |
| 149 | + suffices g x ≠ (x + 1) * (i + 1) by simp [this] |
| 150 | + contrapose! hprod |
| 151 | + simp [hprod] |
| 152 | + · suffices g x = 0 by simp [this] |
| 153 | + contrapose! hx |
| 154 | + exact Finset.mem_of_subset (Finset.mem_finsuppAntidiag.mp hg).2 <| by simpa using hx |
| 155 | + |
| 156 | +private theorem aux_prod_coeff_eq_zero_of_notMem_range (f : ℕ → ℕ → M) {d : ℕ} {s : Finset ℕ} |
| 157 | + {g : ℕ →₀ ℕ} (hg : g ∈ s.finsuppAntidiag d) |
| 158 | + (hg' : g ∉ Set.range (aux_toFinsuppAntidiag (n := d))) : |
| 159 | + ∏ i ∈ s, (coeff (g i)) (1 + ∑' (j : ℕ), |
| 160 | + f (i + 1) (j + 1) • X ^ ((i + 1) * (j + 1)) : M⟦X⟧) = 0 := by |
| 161 | + suffices ∃ i ∈ s, (coeff (g i)) ((1 : M⟦X⟧) + |
| 162 | + ∑' (j : ℕ), f (i + 1) (j + 1) • X ^ ((i + 1) * (j + 1))) = 0 by |
| 163 | + obtain ⟨i, hi, hi'⟩ := this |
| 164 | + apply Finset.prod_eq_zero hi hi' |
| 165 | + contrapose! hg' with hprod |
| 166 | + rw [Set.mem_range] |
| 167 | + refine ⟨Nat.Partition.mk (Finsupp.toMultiset |
| 168 | + (Finsupp.mk (g.support.map (Function.Embedding.mk (· + 1) (add_left_injective 1))) |
| 169 | + (fun i ↦ if i = 0 then 0 else g (i - 1) / i) ?_)) (by simp) ?_, ?_⟩ |
| 170 | + · intro a |
| 171 | + suffices (∃ b, g b ≠ 0 ∧ b + 1 = a) ↔ a ≠ 0 ∧ a ≤ g (a - 1) by simpa |
| 172 | + constructor |
| 173 | + · rintro ⟨b, h1, rfl⟩ |
| 174 | + simpa using Nat.le_of_dvd (Nat.pos_of_ne_zero h1) <| aux_dvd_of_coeff_ne_zero hg hprod b |
| 175 | + · rintro ⟨h1, h2⟩ |
| 176 | + exact ⟨a - 1, by grind⟩ |
| 177 | + · obtain ⟨h1, h2⟩ := Finset.mem_finsuppAntidiag.mp hg |
| 178 | + refine Eq.trans ?_ h1 |
| 179 | + suffices ∑ x ∈ g.support, g x / (x + 1) * (x + 1) = ∑ x ∈ s, g x by simpa [Finsupp.sum] |
| 180 | + rw [Finset.sum_subset h2 (by |
| 181 | + intro x _ |
| 182 | + suffices g x = 0 → g x < x + 1 by simpa; |
| 183 | + grind)] |
| 184 | + exact Finset.sum_congr rfl fun x _ ↦ Nat.div_mul_cancel <| aux_dvd_of_coeff_ne_zero hg hprod x |
| 185 | + · ext x |
| 186 | + simpa [aux_toFinsuppAntidiag] using Nat.div_mul_cancel <| aux_dvd_of_coeff_ne_zero hg hprod x |
| 187 | + |
| 188 | +private theorem aux_prod_f_eq_prod_coeff |
| 189 | + (f : ℕ → ℕ → M) {n : ℕ} (p : Partition n) {s : Finset ℕ} (hs : Finset.range n ≤ s) : |
| 190 | + ∏ i ∈ p.parts.toFinset, f i (Multiset.count i p.parts) = |
| 191 | + ∏ i ∈ s, coeff (p.aux_toFinsuppAntidiag i) |
| 192 | + (1 + ∑' j : ℕ, f (i + 1) (j + 1) • X ^ ((i + 1) * (j + 1))) := by |
| 193 | + refine Finset.prod_of_injOn (· - 1) (aux_injOn_sub_one_parts _) |
| 194 | + ((aux_mapsTo_sub_one_parts p).mono_right hs) ?_ ?_ |
| 195 | + · intro x hx h |
| 196 | + have hx : x + 1 ∉ p.parts := by |
| 197 | + contrapose! h |
| 198 | + exact ⟨x + 1, by simpa using h⟩ |
| 199 | + have hsum := (summable_genFun_term f x).map_tsum _ (WithPiTopology.continuous_constantCoeff M) |
| 200 | + simp [aux_toFinsuppAntidiag, hx, hsum] |
| 201 | + · intro i hi |
| 202 | + have hi : i ∈ p.parts := by simpa using hi |
| 203 | + have hicancel : i - 1 + 1 = i := by |
| 204 | + rw [Nat.sub_add_cancel (Nat.one_le_of_lt (p.parts_pos hi))] |
| 205 | + rw [map_add, (summable_genFun_term f _).map_tsum _ (WithPiTopology.continuous_coeff _ _)] |
| 206 | + suffices f i (Multiset.count i p.parts) = |
| 207 | + ∑' j : ℕ, if Multiset.count i p.parts * i = i * (j + 1) then f i (j + 1) else 0 by |
| 208 | + simpa [hicancel, aux_toFinsuppAntidiag, hi, Nat.ne_zero_of_lt (p.parts_pos hi), coeff_X_pow] |
| 209 | + rw [tsum_eq_single (Multiset.count i p.parts - 1) ?_] |
| 210 | + · rw [mul_comm] |
| 211 | + simp [Nat.sub_add_cancel (Multiset.one_le_count_iff_mem.mpr hi)] |
| 212 | + intro b hb |
| 213 | + suffices Multiset.count i p.parts * i ≠ i * (b + 1) by simp [this] |
| 214 | + rw [mul_comm i, (mul_left_inj' (Nat.ne_zero_of_lt (p.parts_pos hi))).ne] |
| 215 | + grind |
| 216 | + |
| 217 | +theorem hasProd_genFun (f : ℕ → ℕ → M) : |
| 218 | + HasProd (fun i ↦ (1 : M⟦X⟧) + ∑' j : ℕ, f (i + 1) (j + 1) • X ^ ((i + 1) * (j + 1))) |
| 219 | + (genFun f) := by |
| 220 | + rw [HasProd, WithPiTopology.tendsto_iff_coeff_tendsto] |
| 221 | + refine fun d ↦ tendsto_atTop_of_eventually_const (fun s (hs : s ≥ Finset.range d) ↦ ?_) |
| 222 | + rw [genFun, coeff_mk, coeff_prod] |
| 223 | + refine (Finset.sum_of_injOn aux_toFinsuppAntidiag |
| 224 | + (aux_toFinsuppAntidiag_injective d).injOn ?_ ?_ ?_).symm |
| 225 | + · refine Set.MapsTo.mono_right (Set.mapsTo_range _ _) ((aux_range_toFinsuppAntidiag d).trans ?_) |
| 226 | + simpa using Finset.finsuppAntidiag_mono hs.le _ |
| 227 | + · exact fun g hg hg' ↦ aux_prod_coeff_eq_zero_of_notMem_range f hg (by simpa using hg') |
| 228 | + · exact fun p _ ↦ aux_prod_f_eq_prod_coeff f p hs.le |
| 229 | + |
| 230 | +end Nat.Partition |
0 commit comments