Skip to content
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Archive/Wiedijk100Theorems/Partition.lean
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Authors: Bhavik Mehta, Aaron Anderson
-/
import Mathlib.Algebra.Order.Antidiag.Finsupp
import Mathlib.Algebra.Order.Ring.Abs
import Mathlib.Combinatorics.Enumerative.Partition
import Mathlib.Combinatorics.Enumerative.Partition.Basic
import Mathlib.Data.Finset.NatAntidiagonal
import Mathlib.Data.Fin.Tuple.NatAntidiagonal
import Mathlib.RingTheory.PowerSeries.Inverse
Expand Down
3 changes: 2 additions & 1 deletion Mathlib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -3024,7 +3024,8 @@ import Mathlib.Combinatorics.Enumerative.DoubleCounting
import Mathlib.Combinatorics.Enumerative.DyckWord
import Mathlib.Combinatorics.Enumerative.IncidenceAlgebra
import Mathlib.Combinatorics.Enumerative.InclusionExclusion
import Mathlib.Combinatorics.Enumerative.Partition
import Mathlib.Combinatorics.Enumerative.Partition.Basic
import Mathlib.Combinatorics.Enumerative.Partition.GenFun
import Mathlib.Combinatorics.Enumerative.Stirling
import Mathlib.Combinatorics.Extremal.RuzsaSzemeredi
import Mathlib.Combinatorics.Graph.Basic
Expand Down
8 changes: 8 additions & 0 deletions Mathlib/Algebra/Order/Antidiag/Finsupp.lean
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ theorem finsuppAntidiag_insert {a : ι} {s : Finset ι}
simp_rw [mem_map, mem_attach, true_and, Subtype.exists, Embedding.coeFn_mk, exists_prop, and_comm,
eq_comm]

@[gcongr]
theorem finsuppAntidiag_mono {s t : Finset ι} (h : s ⊆ t) (n : μ) :
finsuppAntidiag s n ⊆ finsuppAntidiag t n := by
Comment thread
wwylele marked this conversation as resolved.
intro a
simp_rw [mem_finsuppAntidiag']
rintro ⟨hsum, hmem⟩
exact ⟨hsum, hmem.trans h⟩

variable [AddCommMonoid μ'] [HasAntidiagonal μ'] [DecidableEq μ']

-- This should work under the assumption that e is an embedding and an AddHom
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Copyright (c) 2020 Bhavik Mehta. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Bhavik Mehta
-/
import Mathlib.Algebra.Order.Antidiag.Finsupp
import Mathlib.Combinatorics.Enumerative.Composition
import Mathlib.Tactic.ApplyFun

Expand Down Expand Up @@ -60,6 +61,10 @@ deriving DecidableEq

namespace Partition
Comment thread
wwylele marked this conversation as resolved.

@[grind →]
theorem le_of_mem_parts {n : ℕ} {p : Partition n} {m : ℕ} (h : m ∈ p.parts) : m ≤ n := by
simpa [p.parts_sum] using Multiset.le_sum_of_mem h

/-- A composition induces a partition (just convert the list to a multiset). -/
@[simps]
def ofComposition (n : ℕ) (c : Composition n) : Partition n where
Expand Down Expand Up @@ -117,6 +122,38 @@ def ofSymShapeEquiv (μ : Partition n) (e : σ ≃ τ) :
left_inv := by intro x; simp
right_inv := by intro x; simp

/-- Convert a `Partition n` to a member of `(Finset.Icc 1 n).finsuppAntidiag n`
(see `Nat.Partition.toFinsuppAntidiag_mem_finsuppAntidiag` for the proof).
`p.toFinsuppAntidiag i` is defined as `i` times the number of occurrence of `i` in `p`. -/
def toFinsuppAntidiag {n : ℕ} (p : Partition n) : ℕ →₀ ℕ where
Comment thread
b-mehta marked this conversation as resolved.
toFun m := p.parts.count m * m
support := p.parts.toFinset
mem_support_toFun m := by
suffices m ∈ p.parts → m ≠ 0 by simpa
grind [→ parts_pos]
Comment thread
wwylele marked this conversation as resolved.
Outdated

theorem toFinsuppAntidiag_injective (n : ℕ) : Function.Injective (toFinsuppAntidiag (n := n)) := by
unfold toFinsuppAntidiag
intro p q h
rw [Finsupp.mk.injEq] at h
obtain ⟨hfinset, hcount⟩ := h
rw [Nat.Partition.ext_iff, Multiset.ext]
intro m
obtain rfl | h0 := Nat.eq_zero_or_pos m
· grind [Multiset.count_eq_zero, → parts_pos]
· exact Nat.eq_of_mul_eq_mul_right h0 <| funext_iff.mp hcount m

theorem toFinsuppAntidiag_mem_finsuppAntidiag {n : ℕ} (p : Partition n) :
p.toFinsuppAntidiag ∈ (Finset.Icc 1 n).finsuppAntidiag n := by
have hp : p.parts.toFinset ⊆ Finset.Icc 1 n := by
grind [Multiset.mem_toFinset, Finset.mem_Icc, → parts_pos]
suffices ∑ m ∈ Finset.Icc 1 n, Multiset.count m p.parts * m = n by simpa [toFinsuppAntidiag, hp]
convert ← p.parts_sum
rw [Finset.sum_multiset_count]
apply Finset.sum_subset hp
suffices ∀ (x : ℕ), 1 ≤ x → x ≤ n → x ∉ p.parts → x ∉ p.parts ∨ x = 0 by simpa
grind [→ parts_pos]

/-- The partition of exactly one part. -/
def indiscrete (n : ℕ) : Partition n := ofSums n {n} rfl

Expand Down
178 changes: 178 additions & 0 deletions Mathlib/Combinatorics/Enumerative/Partition/GenFun.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/-
Copyright (c) 2025 Weiyi Wang. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Weiyi Wang
-/
import Mathlib.Combinatorics.Enumerative.Partition.Basic
import Mathlib.RingTheory.PowerSeries.PiTopology

/-!
# Generating functions for partitions

This file defines generating functions related to partitions. Given a character function $f(i, c)$
of a part $i$ and the number of occurrences of the part $c$, the related generating function is
$$
G_f(X) = \sum_{n = 0}^{\infty} \left(\sum_{p \in P_{n}} \prod_{i \in p} f(i, \#i)\right) X^n
= \prod_{i = 1}^{\infty}\left(1 + \sum_{j = 1}^{\infty} f(i, j) X^{ij}\right)
$$
where $P_n$ is all partitions of $n$, $\#i$ is the count of $i$ in the partition $p$.
We give the definition `Nat.Partition.genFun` using the first equation, and prove the second
equation in `Nat.Partition.hasProd_genFun` (with shifted indices).

This generating function can be specialized to
* When $f(i, c) = 1$, this is the generating function for partition function $p(n)$.
* When $f(i, 1) = 1$ and $f(i, c) = 0$ for $c > 1$, this is the generating function for
`#(Nat.Partition.distincts n)`.
* When $f(i, c) = 1$ for odd $i$ and $f(i, c) = 0$ for even $i$, this is the generating function for
`#(Nat.Partition.odds n)`.
(TODO: prove these)

The definition of `Nat.Partition.genFun` ignores the value of $f(0, c)$ and $f(i, 0)$. The formula
can be interpreted as assuming $f(i, 0) = 1$ and $f(0, c) = 0$ for $c \ne 0$. In theory we could
respect the actual value of $f(0, c)$ and $f(i, 0)$, but it makes the otherwise finite sum and
product potentially infinite.
-/

open Finset PowerSeries
open scoped PowerSeries.WithPiTopology

namespace Nat.Partition
variable {R : Type*} [CommSemiring R]

/-- Generating function associated with character $f(i, c)$ for partition functions, where $i$ is a
part of the partition, and $c$ is the count of that part in the partition. The character function is
multiplied within one `n.Partition`, and summed among all `n.Partition` for a fixed `n`. This way,
each `n` is assigned a value, which we use as the coefficients of the power series.

See the module docstring of `Combinatorics.Enumerative.Partition.GenFun` for more details. -/
def genFun (f : ℕ → ℕ → R) : R⟦X⟧ :=
PowerSeries.mk fun n ↦ ∑ p : n.Partition, p.parts.toFinsupp.prod f
Comment thread
wwylele marked this conversation as resolved.

variable [TopologicalSpace R]

/-- The infinite sum in the formula `Nat.Partition.hasProd_genFun` always converges. -/
theorem summable_genFun_term (f : ℕ → ℕ → R) (i : ℕ) :
Summable fun j ↦ f (i + 1) (j + 1) • (X : R⟦X⟧) ^ ((i + 1) * (j + 1)) := by
nontriviality R
apply WithPiTopology.summable_of_tendsto_order_atTop_nhds_top
refine ENat.tendsto_nhds_top_iff_natCast_lt.mpr (fun n ↦ Filter.eventually_atTop.mpr ⟨n, ?_⟩)
intro m hm
grw [PowerSeries.smul_eq_C_mul, ← le_order_mul]
refine lt_add_of_nonneg_of_lt (by simp) ?_
rw [order_X_pow]
norm_cast
grind

/-- Alternative form of `summable_genFun_term` that unshifts the first index. -/
theorem summable_genFun_term' (f : ℕ → ℕ → R) {i : ℕ} (hi : i ≠ 0) :
Summable fun j ↦ f i (j + 1) • (X : R⟦X⟧) ^ (i * (j + 1)) := by
obtain ⟨a, rfl⟩ := Nat.exists_eq_add_one_of_ne_zero hi
apply summable_genFun_term

variable [T2Space R]

private theorem aux_dvd_of_coeff_ne_zero {f : ℕ → ℕ → R} {d : ℕ} {s : Finset ℕ} (hs0 : 0 ∉ s)
{g : ℕ →₀ ℕ} (hg : g ∈ s.finsuppAntidiag d)
(hprod : ∀ i ∈ s, (coeff (g i)) (1 + ∑' j, f i (j + 1) • X ^ (i * (j + 1))) ≠ (0 : R)) (x : ℕ) :
x ∣ g x := by
by_cases hx : x ∈ s
· specialize hprod x hx
contrapose! hprod
have hx0 : x ≠ 0 := fun h ↦ hs0 (h ▸ hx)
rw [map_add, (summable_genFun_term' f hx0).map_tsum _ (WithPiTopology.continuous_coeff _ _)]
rw [show (0 : R) = 0 + ∑' (i : ℕ), 0 by simp]
congrm (?_ + ∑' (i : ℕ), ?_)
· suffices g x ≠ 0 by simp [this]
contrapose! hprod
simp [hprod]
· rw [map_smul, coeff_X_pow]
apply smul_eq_zero_of_right
suffices g x ≠ x * (i + 1) by simp [this]
contrapose! hprod
simp [hprod]
· suffices g x = 0 by simp [this]
contrapose! hx
exact mem_of_subset (mem_finsuppAntidiag.mp hg).2 <| by simpa using hx

private theorem aux_prod_coeff_eq_zero_of_notMem_range (f : ℕ → ℕ → R) {d : ℕ} {s : Finset ℕ}
(hs0 : 0 ∉ s) {g : ℕ →₀ ℕ} (hg : g ∈ s.finsuppAntidiag d)
(hg' : g ∉ Set.range (toFinsuppAntidiag (n := d))) :
∏ i ∈ s, (coeff (g i)) (1 + ∑' j, f i (j + 1) • X ^ (i * (j + 1)) : R⟦X⟧) = 0 := by
suffices ∃ i ∈ s, (coeff (g i)) ((1 : R⟦X⟧) + ∑' j, f i (j + 1) • X ^ (i * (j + 1))) = 0 by
obtain ⟨i, hi, hi'⟩ := this
apply prod_eq_zero hi hi'
contrapose! hg' with hprod
rw [Set.mem_range]
have hgne0 (i : ℕ) : g i ≠ 0 ↔ i ≠ 0 ∧ i ≤ g i := by
refine ⟨fun h ↦ ⟨?_, ?_⟩, by grind⟩
· contrapose! hs0 with rfl
exact mem_of_subset (mem_finsuppAntidiag.mp hg).2 (by simpa using h)
· exact Nat.le_of_dvd (Nat.pos_of_ne_zero h) <| aux_dvd_of_coeff_ne_zero hs0 hg hprod _
refine ⟨Nat.Partition.mk (Finsupp.mk g.support (fun i ↦ g i / i) ?_).toMultiset ?_ ?_, ?_⟩
· simpa using hgne0
· suffices ∀ i, g i ≠ 0 → i ≠ 0 by simpa [Nat.pos_iff_ne_zero]
exact fun i h ↦ ((hgne0 i).mp h).1
· obtain ⟨h1, h2⟩ := mem_finsuppAntidiag.mp hg
refine Eq.trans ?_ h1
suffices ∑ x ∈ g.support, g x / x * x = ∑ x ∈ s, g x by simpa [Finsupp.sum]
apply sum_subset_zero_on_sdiff h2 (by simp)
exact fun x hx ↦ Nat.div_mul_cancel <| aux_dvd_of_coeff_ne_zero hs0 hg hprod x
· ext x
simpa [toFinsuppAntidiag] using Nat.div_mul_cancel <| aux_dvd_of_coeff_ne_zero hs0 hg hprod x

private theorem aux_prod_f_eq_prod_coeff (f : ℕ → ℕ → R) {n : ℕ} (p : Partition n) {s : Finset ℕ}
(hs : Icc 1 n ⊆ s) (hs0 : 0 ∉ s) :
p.parts.toFinsupp.prod f =
∏ i ∈ s, coeff (p.toFinsuppAntidiag i) (1 + ∑' j, f i (j + 1) • X ^ (i * (j + 1))) := by
simp_rw [Finsupp.prod, Multiset.toFinsupp_support, Multiset.toFinsupp_apply]
apply prod_subset_one_on_sdiff
· grind [Multiset.mem_toFinset, mem_Icc, → parts_pos]
· intro x hx
rw [mem_sdiff, Multiset.mem_toFinset] at hx
have hx0 : x ≠ 0 := fun h ↦ hs0 (h ▸ hx.1)
have hsum := (summable_genFun_term' f hx0).map_tsum _
(WithPiTopology.continuous_constantCoeff R)
simp [toFinsuppAntidiag, hsum, hx.2, hx0]
· intro i hi
rw [Multiset.mem_toFinset] at hi
have hi0 : i ≠ 0 := (p.parts_pos hi).ne.symm
rw [map_add, (summable_genFun_term' f hi0).map_tsum _ (WithPiTopology.continuous_coeff _ _)]
suffices f i (Multiset.count i p.parts) =
∑' j, if Multiset.count i p.parts * i = i * (j + 1) then f i (j + 1) else 0 by
simpa [toFinsuppAntidiag, hi, hi0, coeff_X_pow]
rw [tsum_eq_single (Multiset.count i p.parts - 1) ?_]
· rw [mul_comm]
simp [Nat.sub_add_cancel (Multiset.one_le_count_iff_mem.mpr hi)]
intro b hb
suffices Multiset.count i p.parts * i ≠ i * (b + 1) by simp [this]
rw [mul_comm i, (mul_left_inj' (Nat.ne_zero_of_lt (p.parts_pos hi))).ne]
grind

theorem hasProd_genFun (f : ℕ → ℕ → R) :
HasProd (fun i ↦ 1 + ∑' j, f (i + 1) (j + 1) • X ^ ((i + 1) * (j + 1))) (genFun f) := by
Comment thread
wwylele marked this conversation as resolved.
rw [HasProd, WithPiTopology.tendsto_iff_coeff_tendsto]
refine fun d ↦ tendsto_atTop_of_eventually_const (fun s (hs : s ≥ range d) ↦ ?_)
have : ∏ i ∈ s, ((1 : R⟦X⟧) + ∑' j, f (i + 1) (j + 1) • X ^ ((i + 1) * (j + 1)))
= ∏ i ∈ s.map (addRightEmbedding 1), (1 + ∑' j, f i (j + 1) • X ^ (i * (j + 1))) := by simp
rw [this]
have hs : Icc 1 d ⊆ s.map (addRightEmbedding 1) := by
intro i
suffices 1 ≤ i → i ≤ d → ∃ a ∈ s, a + 1 = i by simpa
intro h1 h2
refine ⟨i - 1, mem_of_subset hs ?_, ?_⟩ <;> grind
rw [genFun, coeff_mk, coeff_prod]
refine (sum_of_injOn toFinsuppAntidiag (toFinsuppAntidiag_injective d).injOn ?_ ?_ ?_).symm
· intro p _
exact mem_of_subset (finsuppAntidiag_mono hs.le _) p.toFinsuppAntidiag_mem_finsuppAntidiag
· exact fun g hg hg' ↦ aux_prod_coeff_eq_zero_of_notMem_range f (by simp) hg (by simpa using hg')
· exact fun p _ ↦ aux_prod_f_eq_prod_coeff f p hs.le (by simp)

theorem multipliable_genFun (f : ℕ → ℕ → R) :
Multipliable fun i ↦ (1 : R⟦X⟧) + ∑' j, f (i + 1) (j + 1) • X ^ ((i + 1) * (j + 1)) :=
(hasProd_genFun f).multipliable

theorem genFun_eq_tprod (f : ℕ → ℕ → R) :
genFun f = ∏' i, (1 + ∑' j, f (i + 1) (j + 1) • X ^ ((i + 1) * (j + 1))) :=
(hasProd_genFun f).tprod_eq.symm

end Nat.Partition
2 changes: 1 addition & 1 deletion Mathlib/GroupTheory/Perm/Cycle/Type.lean
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Authors: Thomas Browning
import Mathlib.Algebra.GCDMonoid.Multiset
import Mathlib.Algebra.GCDMonoid.Nat
import Mathlib.Algebra.Group.TypeTags.Finite
import Mathlib.Combinatorics.Enumerative.Partition
import Mathlib.Combinatorics.Enumerative.Partition.Basic
import Mathlib.Data.List.Rotate
import Mathlib.GroupTheory.Perm.Closure
import Mathlib.GroupTheory.Perm.Cycle.Factors
Expand Down
2 changes: 1 addition & 1 deletion Mathlib/RingTheory/MvPolynomial/Symmetric/Defs.lean
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Authors: Hanting Zhang, Johan Commelin
-/
import Mathlib.Algebra.Algebra.Subalgebra.Basic
import Mathlib.Algebra.MvPolynomial.CommRing
import Mathlib.Combinatorics.Enumerative.Partition
import Mathlib.Combinatorics.Enumerative.Partition.Basic

/-!
# Symmetric Polynomials and Elementary Symmetric Polynomials
Expand Down
Loading