Skip to content

Commit 304a3ec

Browse files
committed
feat(Combinatorics): generating function for partitions
1 parent 2c2d756 commit 304a3ec

File tree

8 files changed

+427
-181
lines changed

8 files changed

+427
-181
lines changed

Archive/Wiedijk100Theorems/Partition.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Authors: Bhavik Mehta, Aaron Anderson
55
-/
66
import Mathlib.Algebra.Order.Antidiag.Finsupp
77
import Mathlib.Algebra.Order.Ring.Abs
8-
import Mathlib.Combinatorics.Enumerative.Partition
8+
import Mathlib.Combinatorics.Enumerative.Partition.Basic
99
import Mathlib.Data.Finset.NatAntidiagonal
1010
import Mathlib.Data.Fin.Tuple.NatAntidiagonal
1111
import Mathlib.RingTheory.PowerSeries.Inverse

Mathlib.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2951,6 +2951,8 @@ import Mathlib.Combinatorics.Enumerative.DyckWord
29512951
import Mathlib.Combinatorics.Enumerative.IncidenceAlgebra
29522952
import Mathlib.Combinatorics.Enumerative.InclusionExclusion
29532953
import Mathlib.Combinatorics.Enumerative.Partition
2954+
import Mathlib.Combinatorics.Enumerative.Partition.Basic
2955+
import Mathlib.Combinatorics.Enumerative.Partition.GenFun
29542956
import Mathlib.Combinatorics.Enumerative.Stirling
29552957
import Mathlib.Combinatorics.Extremal.RuzsaSzemeredi
29562958
import Mathlib.Combinatorics.Graph.Basic

Mathlib/Algebra/Order/Antidiag/Finsupp.lean

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ theorem finsuppAntidiag_insert {a : ι} {s : Finset ι}
102102
simp_rw [mem_map, mem_attach, true_and, Subtype.exists, Embedding.coeFn_mk, exists_prop, and_comm,
103103
eq_comm]
104104

105+
theorem finsuppAntidiag_mono {s t : Finset ι} (h : s ⊆ t) (n : μ) :
106+
finsuppAntidiag s n ⊆ finsuppAntidiag t n := by
107+
intro a
108+
simp_rw [mem_finsuppAntidiag']
109+
rintro ⟨hsum, hmem⟩
110+
exact ⟨hsum, hmem.trans h⟩
111+
105112
variable [AddCommMonoid μ'] [HasAntidiagonal μ'] [DecidableEq μ']
106113

107114
-- This should work under the assumption that e is an embedding and an AddHom
Lines changed: 2 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -1,179 +1,3 @@
1-
/-
2-
Copyright (c) 2020 Bhavik Mehta. All rights reserved.
3-
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: Bhavik Mehta
5-
-/
6-
import Mathlib.Combinatorics.Enumerative.Composition
7-
import Mathlib.Tactic.ApplyFun
1+
import Mathlib.Combinatorics.Enumerative.Partition.Basic
82

9-
/-!
10-
# Partitions
11-
12-
A partition of a natural number `n` is a way of writing `n` as a sum of positive integers, where the
13-
order does not matter: two sums that differ only in the order of their summands are considered the
14-
same partition. This notion is closely related to that of a composition of `n`, but in a composition
15-
of `n` the order does matter.
16-
A summand of the partition is called a part.
17-
18-
## Main functions
19-
20-
* `p : Partition n` is a structure, made of a multiset of integers which are all positive and
21-
add up to `n`.
22-
23-
## Implementation details
24-
25-
The main motivation for this structure and its API is to show Euler's partition theorem, and
26-
related results.
27-
28-
The representation of a partition as a multiset is very handy as multisets are very flexible and
29-
already have a well-developed API.
30-
31-
## TODO
32-
33-
Link this to Young diagrams.
34-
35-
## Tags
36-
37-
Partition
38-
39-
## References
40-
41-
<https://en.wikipedia.org/wiki/Partition_(number_theory)>
42-
-/
43-
44-
assert_not_exists Field
45-
46-
open Multiset
47-
48-
namespace Nat
49-
50-
/-- A partition of `n` is a multiset of positive integers summing to `n`. -/
51-
@[ext]
52-
structure Partition (n : ℕ) where
53-
/-- positive integers summing to `n` -/
54-
parts : Multiset ℕ
55-
/-- proof that the `parts` are positive -/
56-
parts_pos : ∀ {i}, i ∈ parts → 0 < i
57-
/-- proof that the `parts` sum to `n` -/
58-
parts_sum : parts.sum = n
59-
deriving DecidableEq
60-
61-
namespace Partition
62-
63-
/-- A composition induces a partition (just convert the list to a multiset). -/
64-
@[simps]
65-
def ofComposition (n : ℕ) (c : Composition n) : Partition n where
66-
parts := c.blocks
67-
parts_pos hi := c.blocks_pos hi
68-
parts_sum := by rw [Multiset.sum_coe, c.blocks_sum]
69-
70-
theorem ofComposition_surj {n : ℕ} : Function.Surjective (ofComposition n) := by
71-
rintro ⟨b, hb₁, hb₂⟩
72-
induction b using Quotient.inductionOn with | _ b => ?_
73-
exact ⟨⟨b, hb₁, by simpa using hb₂⟩, Partition.ext rfl⟩
74-
75-
-- The argument `n` is kept explicit here since it is useful in tactic mode proofs to generate the
76-
-- proof obligation `l.sum = n`.
77-
/-- Given a multiset which sums to `n`, construct a partition of `n` with the same multiset, but
78-
without the zeros.
79-
-/
80-
@[simps]
81-
def ofSums (n : ℕ) (l : Multiset ℕ) (hl : l.sum = n) : Partition n where
82-
parts := l.filter (· ≠ 0)
83-
parts_pos hi := (of_mem_filter hi).bot_lt
84-
parts_sum := by
85-
have lz : (l.filter (· = 0)).sum = 0 := by simp [sum_eq_zero_iff]
86-
rwa [← filter_add_not (· = 0) l, sum_add, lz, zero_add] at hl
87-
88-
/-- A `Multiset ℕ` induces a partition on its sum. -/
89-
@[simps!]
90-
def ofMultiset (l : Multiset ℕ) : Partition l.sum := ofSums _ l rfl
91-
92-
/-- An element `s` of `Sym σ n` induces a partition given by its multiplicities. -/
93-
def ofSym {n : ℕ} {σ : Type*} (s : Sym σ n) [DecidableEq σ] : n.Partition where
94-
parts := s.1.dedup.map s.1.count
95-
parts_pos := by simp [Multiset.count_pos]
96-
parts_sum := by
97-
change ∑ a ∈ s.1.toFinset, count a s.1 = n
98-
rw [toFinset_sum_count_eq]
99-
exact s.2
100-
101-
variable {n : ℕ} {σ τ : Type*} [DecidableEq σ] [DecidableEq τ]
102-
103-
@[simp] lemma ofSym_map (e : σ ≃ τ) (s : Sym σ n) :
104-
ofSym (s.map e) = ofSym s := by
105-
simp only [ofSym, Sym.val_eq_coe, Sym.coe_map, mk.injEq]
106-
rw [Multiset.dedup_map_of_injective e.injective]
107-
simp only [map_map, Function.comp_apply]
108-
congr; funext i
109-
rw [← Multiset.count_map_eq_count' e _ e.injective]
110-
111-
/-- An equivalence between `σ` and `τ` induces an equivalence between the subtypes of `Sym σ n` and
112-
`Sym τ n` corresponding to a given partition. -/
113-
def ofSymShapeEquiv (μ : Partition n) (e : σ ≃ τ) :
114-
{x : Sym σ n // ofSym x = μ} ≃ {x : Sym τ n // ofSym x = μ} where
115-
toFun := fun x => ⟨Sym.equivCongr e x, by simp [ofSym_map, x.2]⟩
116-
invFun := fun x => ⟨Sym.equivCongr e.symm x, by simp [ofSym_map, x.2]⟩
117-
left_inv := by intro x; simp
118-
right_inv := by intro x; simp
119-
120-
/-- The partition of exactly one part. -/
121-
def indiscrete (n : ℕ) : Partition n := ofSums n {n} rfl
122-
123-
instance {n : ℕ} : Inhabited (Partition n) := ⟨indiscrete n⟩
124-
125-
@[simp] lemma indiscrete_parts {n : ℕ} (hn : n ≠ 0) : (indiscrete n).parts = {n} := by
126-
simp [indiscrete, filter_eq_self, hn]
127-
128-
@[simp] lemma partition_zero_parts (p : Partition 0) : p.parts = 0 :=
129-
eq_zero_of_forall_notMem fun _ h => (p.parts_pos h).ne' <| sum_eq_zero_iff.1 p.parts_sum _ h
130-
131-
instance UniquePartitionZero : Unique (Partition 0) where
132-
uniq _ := Partition.ext <| by simp
133-
134-
@[simp] lemma partition_one_parts (p : Partition 1) : p.parts = {1} := by
135-
have h : p.parts = replicate (card p.parts) 1 := eq_replicate_card.2 fun x hx =>
136-
((le_sum_of_mem hx).trans_eq p.parts_sum).antisymm (p.parts_pos hx)
137-
have h' : card p.parts = 1 := by simpa using (congrArg sum h.symm).trans p.parts_sum
138-
rw [h, h', replicate_one]
139-
140-
instance UniquePartitionOne : Unique (Partition 1) where
141-
uniq _ := Partition.ext <| by simp
142-
143-
@[simp] lemma ofSym_one (s : Sym σ 1) : ofSym s = indiscrete 1 := by
144-
ext; simp
145-
146-
/-- The number of times a positive integer `i` appears in the partition `ofSums n l hl` is the same
147-
as the number of times it appears in the multiset `l`.
148-
(For `i = 0`, `Partition.non_zero` combined with `Multiset.count_eq_zero_of_notMem` gives that
149-
this is `0` instead.)
150-
-/
151-
theorem count_ofSums_of_ne_zero {n : ℕ} {l : Multiset ℕ} (hl : l.sum = n) {i : ℕ} (hi : i ≠ 0) :
152-
(ofSums n l hl).parts.count i = l.count i :=
153-
count_filter_of_pos hi
154-
155-
theorem count_ofSums_zero {n : ℕ} {l : Multiset ℕ} (hl : l.sum = n) :
156-
(ofSums n l hl).parts.count 0 = 0 :=
157-
count_filter_of_neg fun h => h rfl
158-
159-
/-- Show there are finitely many partitions by considering the surjection from compositions to
160-
partitions.
161-
-/
162-
instance (n : ℕ) : Fintype (Partition n) :=
163-
Fintype.ofSurjective (ofComposition n) ofComposition_surj
164-
165-
/-- The finset of those partitions in which every part is odd. -/
166-
def odds (n : ℕ) : Finset (Partition n) :=
167-
Finset.univ.filter fun c => ∀ i ∈ c.parts, ¬Even i
168-
169-
/-- The finset of those partitions in which each part is used at most once. -/
170-
def distincts (n : ℕ) : Finset (Partition n) :=
171-
Finset.univ.filter fun c => c.parts.Nodup
172-
173-
/-- The finset of those partitions in which every part is odd and used at most once. -/
174-
def oddDistincts (n : ℕ) : Finset (Partition n) :=
175-
odds n ∩ distincts n
176-
177-
end Partition
178-
179-
end Nat
3+
deprecated_module (since := "2025-10-18")
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/-
2+
Copyright (c) 2020 Bhavik Mehta. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Bhavik Mehta
5+
-/
6+
import Mathlib.Combinatorics.Enumerative.Composition
7+
import Mathlib.Tactic.ApplyFun
8+
9+
/-!
10+
# Partitions
11+
12+
A partition of a natural number `n` is a way of writing `n` as a sum of positive integers, where the
13+
order does not matter: two sums that differ only in the order of their summands are considered the
14+
same partition. This notion is closely related to that of a composition of `n`, but in a composition
15+
of `n` the order does matter.
16+
A summand of the partition is called a part.
17+
18+
## Main functions
19+
20+
* `p : Partition n` is a structure, made of a multiset of integers which are all positive and
21+
add up to `n`.
22+
23+
## Implementation details
24+
25+
The main motivation for this structure and its API is to show Euler's partition theorem, and
26+
related results.
27+
28+
The representation of a partition as a multiset is very handy as multisets are very flexible and
29+
already have a well-developed API.
30+
31+
## TODO
32+
33+
Link this to Young diagrams.
34+
35+
## Tags
36+
37+
Partition
38+
39+
## References
40+
41+
<https://en.wikipedia.org/wiki/Partition_(number_theory)>
42+
-/
43+
44+
assert_not_exists Field
45+
46+
open Multiset
47+
48+
namespace Nat
49+
50+
/-- A partition of `n` is a multiset of positive integers summing to `n`. -/
51+
@[ext]
52+
structure Partition (n : ℕ) where
53+
/-- positive integers summing to `n` -/
54+
parts : Multiset ℕ
55+
/-- proof that the `parts` are positive -/
56+
parts_pos : ∀ {i}, i ∈ parts → 0 < i
57+
/-- proof that the `parts` sum to `n` -/
58+
parts_sum : parts.sum = n
59+
deriving DecidableEq
60+
61+
namespace Partition
62+
63+
theorem le_of_mem_parts {n : ℕ} {p : Partition n} {m : ℕ} (h : m ∈ p.parts) : m ≤ n := by
64+
simpa [p.parts_sum] using Multiset.le_sum_of_mem h
65+
66+
/-- A composition induces a partition (just convert the list to a multiset). -/
67+
@[simps]
68+
def ofComposition (n : ℕ) (c : Composition n) : Partition n where
69+
parts := c.blocks
70+
parts_pos hi := c.blocks_pos hi
71+
parts_sum := by rw [Multiset.sum_coe, c.blocks_sum]
72+
73+
theorem ofComposition_surj {n : ℕ} : Function.Surjective (ofComposition n) := by
74+
rintro ⟨b, hb₁, hb₂⟩
75+
induction b using Quotient.inductionOn with | _ b => ?_
76+
exact ⟨⟨b, hb₁, by simpa using hb₂⟩, Partition.ext rfl⟩
77+
78+
-- The argument `n` is kept explicit here since it is useful in tactic mode proofs to generate the
79+
-- proof obligation `l.sum = n`.
80+
/-- Given a multiset which sums to `n`, construct a partition of `n` with the same multiset, but
81+
without the zeros.
82+
-/
83+
@[simps]
84+
def ofSums (n : ℕ) (l : Multiset ℕ) (hl : l.sum = n) : Partition n where
85+
parts := l.filter (· ≠ 0)
86+
parts_pos hi := (of_mem_filter hi).bot_lt
87+
parts_sum := by
88+
have lz : (l.filter (· = 0)).sum = 0 := by simp [sum_eq_zero_iff]
89+
rwa [← filter_add_not (· = 0) l, sum_add, lz, zero_add] at hl
90+
91+
/-- A `Multiset ℕ` induces a partition on its sum. -/
92+
@[simps!]
93+
def ofMultiset (l : Multiset ℕ) : Partition l.sum := ofSums _ l rfl
94+
95+
/-- An element `s` of `Sym σ n` induces a partition given by its multiplicities. -/
96+
def ofSym {n : ℕ} {σ : Type*} (s : Sym σ n) [DecidableEq σ] : n.Partition where
97+
parts := s.1.dedup.map s.1.count
98+
parts_pos := by simp [Multiset.count_pos]
99+
parts_sum := by
100+
change ∑ a ∈ s.1.toFinset, count a s.1 = n
101+
rw [toFinset_sum_count_eq]
102+
exact s.2
103+
104+
variable {n : ℕ} {σ τ : Type*} [DecidableEq σ] [DecidableEq τ]
105+
106+
@[simp] lemma ofSym_map (e : σ ≃ τ) (s : Sym σ n) :
107+
ofSym (s.map e) = ofSym s := by
108+
simp only [ofSym, Sym.val_eq_coe, Sym.coe_map, mk.injEq]
109+
rw [Multiset.dedup_map_of_injective e.injective]
110+
simp only [map_map, Function.comp_apply]
111+
congr; funext i
112+
rw [← Multiset.count_map_eq_count' e _ e.injective]
113+
114+
/-- An equivalence between `σ` and `τ` induces an equivalence between the subtypes of `Sym σ n` and
115+
`Sym τ n` corresponding to a given partition. -/
116+
def ofSymShapeEquiv (μ : Partition n) (e : σ ≃ τ) :
117+
{x : Sym σ n // ofSym x = μ} ≃ {x : Sym τ n // ofSym x = μ} where
118+
toFun := fun x => ⟨Sym.equivCongr e x, by simp [ofSym_map, x.2]⟩
119+
invFun := fun x => ⟨Sym.equivCongr e.symm x, by simp [ofSym_map, x.2]⟩
120+
left_inv := by intro x; simp
121+
right_inv := by intro x; simp
122+
123+
/-- The partition of exactly one part. -/
124+
def indiscrete (n : ℕ) : Partition n := ofSums n {n} rfl
125+
126+
instance {n : ℕ} : Inhabited (Partition n) := ⟨indiscrete n⟩
127+
128+
@[simp] lemma indiscrete_parts {n : ℕ} (hn : n ≠ 0) : (indiscrete n).parts = {n} := by
129+
simp [indiscrete, filter_eq_self, hn]
130+
131+
@[simp] lemma partition_zero_parts (p : Partition 0) : p.parts = 0 :=
132+
eq_zero_of_forall_notMem fun _ h => (p.parts_pos h).ne' <| sum_eq_zero_iff.1 p.parts_sum _ h
133+
134+
instance UniquePartitionZero : Unique (Partition 0) where
135+
uniq _ := Partition.ext <| by simp
136+
137+
@[simp] lemma partition_one_parts (p : Partition 1) : p.parts = {1} := by
138+
have h : p.parts = replicate (card p.parts) 1 := eq_replicate_card.2 fun x hx =>
139+
((le_sum_of_mem hx).trans_eq p.parts_sum).antisymm (p.parts_pos hx)
140+
have h' : card p.parts = 1 := by simpa using (congrArg sum h.symm).trans p.parts_sum
141+
rw [h, h', replicate_one]
142+
143+
instance UniquePartitionOne : Unique (Partition 1) where
144+
uniq _ := Partition.ext <| by simp
145+
146+
@[simp] lemma ofSym_one (s : Sym σ 1) : ofSym s = indiscrete 1 := by
147+
ext; simp
148+
149+
/-- The number of times a positive integer `i` appears in the partition `ofSums n l hl` is the same
150+
as the number of times it appears in the multiset `l`.
151+
(For `i = 0`, `Partition.non_zero` combined with `Multiset.count_eq_zero_of_notMem` gives that
152+
this is `0` instead.)
153+
-/
154+
theorem count_ofSums_of_ne_zero {n : ℕ} {l : Multiset ℕ} (hl : l.sum = n) {i : ℕ} (hi : i ≠ 0) :
155+
(ofSums n l hl).parts.count i = l.count i :=
156+
count_filter_of_pos hi
157+
158+
theorem count_ofSums_zero {n : ℕ} {l : Multiset ℕ} (hl : l.sum = n) :
159+
(ofSums n l hl).parts.count 0 = 0 :=
160+
count_filter_of_neg fun h => h rfl
161+
162+
/-- Show there are finitely many partitions by considering the surjection from compositions to
163+
partitions.
164+
-/
165+
instance (n : ℕ) : Fintype (Partition n) :=
166+
Fintype.ofSurjective (ofComposition n) ofComposition_surj
167+
168+
/-- The finset of those partitions in which every part is odd. -/
169+
def odds (n : ℕ) : Finset (Partition n) :=
170+
Finset.univ.filter fun c => ∀ i ∈ c.parts, ¬Even i
171+
172+
/-- The finset of those partitions in which each part is used at most once. -/
173+
def distincts (n : ℕ) : Finset (Partition n) :=
174+
Finset.univ.filter fun c => c.parts.Nodup
175+
176+
/-- The finset of those partitions in which every part is odd and used at most once. -/
177+
def oddDistincts (n : ℕ) : Finset (Partition n) :=
178+
odds n ∩ distincts n
179+
180+
end Partition
181+
182+
end Nat

0 commit comments

Comments
 (0)