|
| 1 | +/- |
| 2 | +Copyright (c) 2025 Beibei Xiong. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Beibei Xiong |
| 5 | +-/ |
| 6 | +import Mathlib.Algebra.Order.Ring.Star |
| 7 | +import Mathlib.Analysis.Normed.Ring.Lemmas |
| 8 | +import Mathlib.Combinatorics.Enumerative.Partition |
| 9 | +import Mathlib.Data.Int.Star |
| 10 | +import Mathlib.RingTheory.PowerSeries.Basic |
| 11 | + |
| 12 | +/-! |
| 13 | +# Pentagonal numbers, parity of strict partitions, and a finite product cut-off |
| 14 | +
|
| 15 | +This file introduces: |
| 16 | +* the (integer-valued) generalized pentagonal numbers `generalizedPentagonalZ`, |
| 17 | +* the parity difference of strict partitions of `n`: |
| 18 | + `strict_partitions_parity_diff n = p_even_distinct n - p_odd_distinct n`, |
| 19 | +* a finite product `E n` approximating Euler's generating function, and a simple lemma about its |
| 20 | + coefficient extraction being a restatement with the same cut-off. |
| 21 | +
|
| 22 | +These pieces are intended to support proofs around Euler's pentagonal number theorem and |
| 23 | +related identities. |
| 24 | +
|
| 25 | +## Main definitions |
| 26 | +
|
| 27 | +* `p_even_distinct n` : number of partitions of `n` into distinct parts with an even |
| 28 | + number of parts. |
| 29 | +* `p_odd_distinct n` : number of partitions of `n` into distinct parts with an odd |
| 30 | + number of parts. |
| 31 | +* `generalizedPentagonalZ j` : the (possibly negative-indexed) generalized pentagonal numbers |
| 32 | + `j*(3*j - 1)/2` as integers. |
| 33 | +* `generalizedPentagonalNum j` : the same, coerced to `ℕ` by `Int.toNat`. |
| 34 | +* `error_term_e n` : the Euler error-term `eₙ`, which is `(-1)^{|j|}` if `n` equals a generalized |
| 35 | + pentagonal number for some `j : ℤ`, and `0` otherwise. |
| 36 | +* `strict_partitions_parity_diff n` : `(p_even_distinct n : ℤ) - (p_odd_distinct n : ℤ)`. |
| 37 | +* `E n` : a finite product `∏_{k=1}^{n+1} (1 - X^k)` seen as a `PowerSeries ℤ`. |
| 38 | +
|
| 39 | +## Implementation details |
| 40 | +
|
| 41 | +* We keep an integer-valued definition `generalizedPentagonalZ : ℤ → ℤ` for convenience in |
| 42 | + arithmetic facts and sign arguments. The natural-number version `generalizedPentagonalNum` |
| 43 | + is just `Int.toNat` of the integer-valued one. |
| 44 | +* A bounded search for witnesses `j` such that `n = generalizedPentagonalZ j` is provided by |
| 45 | + `exists_j_iff_exists_j_in_range`. |
| 46 | +
|
| 47 | +## TODO |
| 48 | +
|
| 49 | +* Connect `error_term_e` and `strict_partitions_parity_diff` via Euler's pentagonal theorem. |
| 50 | +* Provide API lemmas for coefficients of the infinite product and its finite truncations. |
| 51 | +
|
| 52 | +## Tags |
| 53 | +
|
| 54 | +partition, pentagonal number, Euler, generating function |
| 55 | +
|
| 56 | +## References |
| 57 | +
|
| 58 | +* <https://en.wikipedia.org/wiki/Pentagonal_number_theorem> |
| 59 | +-/ |
| 60 | + |
| 61 | +open Finset Nat Int Partition PowerSeries Polynomial |
| 62 | +open scoped BigOperators |
| 63 | + |
| 64 | +/-- |
| 65 | +`p_even_distinct n`: number of partitions of `n` into distinct parts with an even number of parts. |
| 66 | +-/ |
| 67 | +def p_even_distinct (n : ℕ) : ℕ := |
| 68 | + ((Nat.Partition.distincts n).filter (fun p => Even p.parts.card)).card |
| 69 | + |
| 70 | +/-- |
| 71 | +`p_odd_distinct n`: number of partitions of `n` into distinct parts with an odd number of parts. |
| 72 | +-/ |
| 73 | +def p_odd_distinct (n : ℕ) : ℕ := |
| 74 | + ((Nat.Partition.distincts n).filter (fun p => Odd p.parts.card)).card |
| 75 | + |
| 76 | +/-! |
| 77 | +### Generalized pentagonal numbers and the error term `eₙ` |
| 78 | +-/ |
| 79 | + |
| 80 | +/-- |
| 81 | +Generalized pentagonal number (integer-valued): `j ↦ j * (3*j - 1) / 2`. |
| 82 | +-/ |
| 83 | +def generalizedPentagonalZ (j : ℤ) : ℤ := j * (3 * j - 1) / 2 |
| 84 | + |
| 85 | +lemma gpn_nonneg (j : ℤ) : 0 ≤ generalizedPentagonalZ j := by |
| 86 | + -- Show `0 ≤ j * (3*j - 1)` and then apply `Int.ediv_nonneg`. |
| 87 | + have : 0 ≤ j * (3 * j - 1) := by |
| 88 | + rcases le_or_gt j 0 with hle | hgt |
| 89 | + · exact mul_nonneg_of_nonpos_of_nonpos hle (by linarith) |
| 90 | + · exact mul_nonneg hgt.le (by linarith) |
| 91 | + exact Int.ediv_nonneg this (by decide) |
| 92 | + |
| 93 | +/-- |
| 94 | +Natural-number version of generalized pentagonal numbers. |
| 95 | +-/ |
| 96 | +def generalizedPentagonalNum (j : ℤ) : ℕ := |
| 97 | + Int.toNat (generalizedPentagonalZ j) |
| 98 | + |
| 99 | +lemma gpn_coe (j : ℤ) : |
| 100 | + (generalizedPentagonalNum j : ℤ) = generalizedPentagonalZ j := by |
| 101 | + simp [generalizedPentagonalNum, generalizedPentagonalZ] |
| 102 | + refine (ediv_nonneg_iff_of_pos ?_).mpr ?_ |
| 103 | + · norm_num |
| 104 | + · by_cases hj : j > 0 |
| 105 | + · refine Int.mul_nonneg ?_ ?_ |
| 106 | + · linarith |
| 107 | + · linarith |
| 108 | + · have hle : j ≤ 0 := by linarith |
| 109 | + refine Int.mul_nonneg_of_nonpos_of_nonpos hle ?_ |
| 110 | + linarith |
| 111 | +/-- |
| 112 | +`2 ∣ (-j + 3*j^2)`. |
| 113 | +-/ |
| 114 | +theorem even_neg_j_add_three_j_sq (j : ℤ) : 2 ∣ (-j + 3 * j ^ 2) := by |
| 115 | + -- Factorization: `-j + 3*j^2 = j*(3*j - 1)`. |
| 116 | + have h : -j + 3 * j ^ 2 = j * (3 * j - 1) := by ring |
| 117 | + rw [h] |
| 118 | + -- Rewrite as `j*(j-1) + 2*j^2`. |
| 119 | + have h' : j * (3 * j - 1) = j * (j - 1) + 2 * j ^ 2 := by ring |
| 120 | + rw [h'] |
| 121 | + -- `2 ∣ j*(j-1)` since product of consecutive integers is even. |
| 122 | + have h_consec : 2 ∣ j * (j - 1) := by |
| 123 | + rcases Int.even_or_odd j with ⟨k, rfl⟩ | ⟨k, rfl⟩ |
| 124 | + · use k * (2 * k - 1); ring |
| 125 | + · use k * (2 * k + 1); ring |
| 126 | + -- `2 ∣ 2*j^2` trivially. |
| 127 | + have h_twice : 2 ∣ 2 * j ^ 2 := by use j ^ 2 |
| 128 | + -- Sum of two even numbers is even. |
| 129 | + exact dvd_add h_consec h_twice |
| 130 | + |
| 131 | +theorem even_neg_j_add_three_j_sq' (j : ℤ) : Even (-j + 3 * j ^ 2) := by |
| 132 | + have := even_neg_j_add_three_j_sq j |
| 133 | + exact (even_iff_exists_two_nsmul (-j + 3 * j ^ 2)).mpr this |
| 134 | + |
| 135 | +/-- |
| 136 | +Existence of `j` with `n = generalizedPentagonalZ j` can be restricted to a bounded interval |
| 137 | +`j ∈ [-(n+1), n+1]`. |
| 138 | +-/ |
| 139 | +theorem exists_j_iff_exists_j_in_range (n : ℕ) : |
| 140 | + (∃ j : ℤ, n = generalizedPentagonalZ j) ↔ |
| 141 | + (∃ j ∈ Finset.Icc (-(n+1 : ℤ)) ((n+1 : ℤ)), n = generalizedPentagonalZ j) := by |
| 142 | + constructor |
| 143 | + · rintro ⟨j, hn⟩ |
| 144 | + use j |
| 145 | + constructor |
| 146 | + · refine mem_Icc.mpr ?_ |
| 147 | + rw [hn, generalizedPentagonalZ] |
| 148 | + have h_bound1 : -(j * (3 * j - 1) / 2 + 1) ≤ j := by |
| 149 | + have h_nezero : (2 : ℤ) ≠ 0 := by norm_num |
| 150 | + refine Int.add_nonneg_iff_neg_le.mp ?_ |
| 151 | + · by_cases hj : j > 0 |
| 152 | + · refine Int.add_nonneg ?_ ?_ |
| 153 | + linarith |
| 154 | + refine Int.add_nonneg ?_ ?_ |
| 155 | + refine (ediv_nonneg_iff_of_pos ?_).mpr ?_ |
| 156 | + linarith |
| 157 | + refine Int.mul_nonneg ?_ ?_ |
| 158 | + linarith |
| 159 | + linarith |
| 160 | + linarith |
| 161 | + · have hle : j ≤ 0 := by linarith |
| 162 | + by_cases hj1 : j = 0 |
| 163 | + · rw [hj1] |
| 164 | + norm_num |
| 165 | + · have hj2 : j < 0 := by omega |
| 166 | + have h_bound1 : j + j * (3 * j - 1) / 2 = j * (3 * j + 1) / 2 := by |
| 167 | + have h_nezero : (2 : ℤ) ≠ 0 := by norm_num |
| 168 | + refine Int.eq_ediv_of_mul_eq_right h_nezero ?_ |
| 169 | + ring_nf |
| 170 | + rw [mul_two ,add_assoc] |
| 171 | + congr 1 |
| 172 | + rw [mul_comm _ 3] |
| 173 | + have h_aux : (-j + 3 * j ^ 2) / 2 * 2 = -j + 3 * j ^ 2 := by |
| 174 | + apply Int.ediv_two_mul_two_of_even (even_neg_j_add_three_j_sq' j) |
| 175 | + rw [h_aux] |
| 176 | + ring |
| 177 | + |
| 178 | + rw [← add_assoc, h_bound1] |
| 179 | + refine Int.add_nonneg ?_ ?_ |
| 180 | + refine (ediv_nonneg_iff_of_pos ?_).mpr ?_ |
| 181 | + omega |
| 182 | + have h: 0 < j * (3 * j + 1) := by |
| 183 | + refine Int.mul_pos_of_neg_of_neg hj2 ?_ |
| 184 | + linarith |
| 185 | + linarith |
| 186 | + omega |
| 187 | + |
| 188 | + have h_bound2 : j ≤ j * (3 * j - 1) / 2 + 1 := by |
| 189 | + have h_nezero : (2 : ℤ) ≠ 0 := by norm_num |
| 190 | + refine Int.sub_nonneg.mp ?_ |
| 191 | + have h_aux : j * (3 * j - 1) / 2 + 1 - j = 3 * j * (j - 1) / 2 + 1 := by |
| 192 | + |
| 193 | + ring_nf |
| 194 | + rw [sub_add] |
| 195 | + rw [sub_eq_add_neg] |
| 196 | + congr 1 |
| 197 | + ring_nf |
| 198 | + refine Int.eq_ediv_of_mul_eq_right h_nezero ?_ |
| 199 | + ring_nf |
| 200 | + have h_aux : (-j + 3 * j ^ 2) / 2 * 2 = -j + 3 * j ^ 2 := by |
| 201 | + apply Int.ediv_two_mul_two_of_even (even_neg_j_add_three_j_sq' j) |
| 202 | + rw [mul_comm _ 3, h_aux] |
| 203 | + ring |
| 204 | + |
| 205 | + rw [h_aux] |
| 206 | + refine Int.add_nonneg ?_ ?_ |
| 207 | + refine (ediv_nonneg_iff_of_pos ?_).mpr ?_ |
| 208 | + omega |
| 209 | + by_cases hj : j < 0 |
| 210 | + · have hj1 : j - 1 < 0 := by linarith |
| 211 | + have h_mul_neg : j * (j - 1) > 0 := by |
| 212 | + refine Int.mul_pos_of_neg_of_neg hj hj1 |
| 213 | + linarith |
| 214 | + · have hle : j ≥ 0 := by linarith |
| 215 | + by_cases hj1 : j = 0 |
| 216 | + · rw [hj1] |
| 217 | + norm_num |
| 218 | + · have hj2 : j > 0 := by omega |
| 219 | + have h_mul_pos : 3 * j * (j - 1) ≥ 0 := by |
| 220 | + refine Int.mul_nonneg ?_ ?_ |
| 221 | + linarith |
| 222 | + linarith |
| 223 | + linarith |
| 224 | + linarith |
| 225 | + exact ⟨h_bound1, h_bound2⟩ |
| 226 | + |
| 227 | + · exact hn |
| 228 | + · rintro ⟨j, _, hn⟩ |
| 229 | + use j, hn |
| 230 | + |
| 231 | +/-- |
| 232 | +Decidability of `∃ j : ℤ, n = generalizedPentagonalZ j` via a bounded search window. |
| 233 | +-/ |
| 234 | +instance (n : ℕ) : Decidable (∃ j : ℤ, n = generalizedPentagonalZ j) := |
| 235 | + decidable_of_iff' |
| 236 | + (∃ j ∈ Finset.Icc (-(n + 1 : ℤ)) (n + 1 : ℤ), n = generalizedPentagonalZ j) |
| 237 | + (exists_j_iff_exists_j_in_range n) |
| 238 | + |
| 239 | +/-- |
| 240 | +Euler's error term `eₙ`. It is `(-1)^{|j|}` if `n` is a generalized pentagonal number |
| 241 | +`generalizedPentagonalZ j` for some `j : ℤ`, and `0` otherwise. |
| 242 | +-/ |
| 243 | +noncomputable def error_term_e (n : ℕ) : ℤ := |
| 244 | + if h : ∃ j : ℤ, n = generalizedPentagonalZ j then |
| 245 | + let j := Classical.choose h |
| 246 | + (-1 : ℤ) ^ j.natAbs |
| 247 | + else |
| 248 | + 0 |
| 249 | + |
| 250 | +/-- |
| 251 | +Difference between the numbers of strict partitions with even vs. odd number of parts. |
| 252 | +-/ |
| 253 | +def strict_partitions_parity_diff (n : ℕ) : ℤ := |
| 254 | + (p_even_distinct n : ℤ) - (p_odd_distinct n : ℤ) |
| 255 | + |
| 256 | +/-- |
| 257 | +Finite product `E(n) = ∏_{k=1}^{n+1} (1 - X^k)` as a `PowerSeries ℤ`. |
| 258 | +-/ |
| 259 | +noncomputable def E (n : ℕ) : PowerSeries ℤ := |
| 260 | + ∏ k ∈ Finset.range (n + 1), (1 - (PowerSeries.X : PowerSeries ℤ) ^ (k + 1)) |
| 261 | + |
| 262 | +lemma coeff_E_eq_coeff_cutoff (n : ℕ) : |
| 263 | + (PowerSeries.coeff n) (E n) = |
| 264 | + (PowerSeries.coeff n) |
| 265 | + (∏ k ∈ Finset.range (n + 1), (1 - (PowerSeries.X : PowerSeries ℤ) ^ (k + 1))) := by |
| 266 | + simp [E] |
| 267 | + |
| 268 | + |
0 commit comments