|
| 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