@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
4
4
Authors: Yaël Dillies, Bhavik Mehta
5
5
-/
6
6
import Mathlib.Data.Set.Equitable
7
+ import Mathlib.Logic.Equiv.Fin
7
8
import Mathlib.Order.Partition.Finpartition
8
9
9
10
#align_import order.partition.equipartition from "leanprover-community/mathlib" @"b363547b3113d350d053abdf2884e9850a56b205"
@@ -17,6 +18,9 @@ difference of `1`.
17
18
## Main declarations
18
19
19
20
* `Finpartition.IsEquipartition`: Predicate for a `Finpartition` to be an equipartition.
21
+ * `Finpartition.IsEquipartition.exists_partPreservingEquiv`: part-preserving enumeration of a finset
22
+ equipped with an equipartition. Indices of elements in the same part are congruent modulo
23
+ the number of parts.
20
24
-/
21
25
22
26
@@ -41,7 +45,7 @@ theorem isEquipartition_iff_card_parts_eq_average :
41
45
variable {P}
42
46
43
47
lemma not_isEquipartition :
44
- ¬P.IsEquipartition ↔ ∃ a ∈ P.parts, ∃ b ∈ P.parts, Finset .card b + 1 < Finset .card a :=
48
+ ¬P.IsEquipartition ↔ ∃ a ∈ P.parts, ∃ b ∈ P.parts, b .card + 1 < a .card :=
45
49
Set.not_equitableOn
46
50
47
51
theorem _root_.Set.Subsingleton.isEquipartition (h : (P.parts : Set (Finset α)).Subsingleton) :
@@ -54,6 +58,13 @@ theorem IsEquipartition.card_parts_eq_average (hP : P.IsEquipartition) (ht : t
54
58
P.isEquipartition_iff_card_parts_eq_average.1 hP _ ht
55
59
#align finpartition.is_equipartition.card_parts_eq_average Finpartition.IsEquipartition.card_parts_eq_average
56
60
61
+ theorem IsEquipartition.card_part_eq_average_iff (hP : P.IsEquipartition) (ht : t ∈ P.parts) :
62
+ t.card = s.card / P.parts.card ↔ t.card ≠ s.card / P.parts.card + 1 := by
63
+ have a := hP.card_parts_eq_average ht
64
+ have b : ¬(t.card = s.card / P.parts.card ∧ t.card = s.card / P.parts.card + 1 ) := by
65
+ by_contra h; exact absurd (h.1 ▸ h.2 ) (lt_add_one _).ne
66
+ tauto
67
+
57
68
theorem IsEquipartition.average_le_card_part (hP : P.IsEquipartition) (ht : t ∈ P.parts) :
58
69
s.card / P.parts.card ≤ t.card := by
59
70
rw [← P.sum_card_parts]
@@ -66,7 +77,94 @@ theorem IsEquipartition.card_part_le_average_add_one (hP : P.IsEquipartition) (h
66
77
exact Finset.EquitableOn.le_add_one hP ht
67
78
#align finpartition.is_equipartition.card_part_le_average_add_one Finpartition.IsEquipartition.card_part_le_average_add_one
68
79
69
- /-! ### Discrete and indiscrete finpartition -/
80
+ theorem IsEquipartition.filter_ne_average_add_one_eq_average (hP : P.IsEquipartition) :
81
+ P.parts.filter (fun p ↦ ¬p.card = s.card / P.parts.card + 1 ) =
82
+ P.parts.filter (fun p ↦ p.card = s.card / P.parts.card) := by
83
+ ext p
84
+ simp only [mem_filter, and_congr_right_iff]
85
+ exact fun hp ↦ (hP.card_part_eq_average_iff hp).symm
86
+
87
+ /-- An equipartition of a finset with `n` elements into `k` parts has
88
+ `n % k` parts of size `n / k + 1`. -/
89
+ theorem IsEquipartition.card_large_parts_eq_mod (hP : P.IsEquipartition) :
90
+ (P.parts.filter fun p ↦ p.card = s.card / P.parts.card + 1 ).card = s.card % P.parts.card := by
91
+ have z := P.sum_card_parts
92
+ rw [← sum_filter_add_sum_filter_not (s := P.parts)
93
+ (p := fun x ↦ x.card = s.card / P.parts.card + 1 ),
94
+ hP.filter_ne_average_add_one_eq_average,
95
+ sum_const_nat (m := s.card / P.parts.card + 1 ) (by simp),
96
+ sum_const_nat (m := s.card / P.parts.card) (by simp),
97
+ ← hP.filter_ne_average_add_one_eq_average,
98
+ mul_add, add_comm, ← add_assoc, ← add_mul, mul_one, add_comm (Finset.card _),
99
+ filter_card_add_filter_neg_card_eq_card, add_comm] at z
100
+ rw [← add_left_inj, Nat.mod_add_div, z]
101
+
102
+ /-- An equipartition of a finset with `n` elements into `k` parts has
103
+ `n - n % k` parts of size `n / k`. -/
104
+ theorem IsEquipartition.card_small_parts_eq_mod (hP : P.IsEquipartition) :
105
+ (P.parts.filter fun p ↦ p.card = s.card / P.parts.card).card =
106
+ P.parts.card - s.card % P.parts.card := by
107
+ conv_rhs =>
108
+ arg 1
109
+ rw [← filter_card_add_filter_neg_card_eq_card (p := fun p ↦ p.card = s.card / P.parts.card + 1 )]
110
+ rw [hP.card_large_parts_eq_mod, add_tsub_cancel_left, hP.filter_ne_average_add_one_eq_average]
111
+
112
+ /-- There exists an enumeration of an equipartition's parts where
113
+ larger parts map to smaller numbers and vice versa. -/
114
+ theorem IsEquipartition.exists_partsEquiv (hP : P.IsEquipartition) :
115
+ ∃ f : P.parts ≃ Fin P.parts.card,
116
+ ∀ t, t.1 .card = s.card / P.parts.card + 1 ↔ f t < s.card % P.parts.card := by
117
+ let el := (P.parts.filter fun p ↦ p.card = s.card / P.parts.card + 1 ).equivFin
118
+ let es := (P.parts.filter fun p ↦ p.card = s.card / P.parts.card).equivFin
119
+ simp_rw [mem_filter, hP.card_large_parts_eq_mod] at el
120
+ simp_rw [mem_filter, hP.card_small_parts_eq_mod] at es
121
+ let sneg : { x // x ∈ P.parts ∧ ¬x.card = s.card / P.parts.card + 1 } ≃
122
+ { x // x ∈ P.parts ∧ x.card = s.card / P.parts.card } := by
123
+ apply Equiv.subtypeEquiv (by rfl)
124
+ simp only [Equiv.refl_apply, and_congr_right_iff]
125
+ exact fun _ ha ↦ by rw [hP.card_part_eq_average_iff ha, ne_eq]
126
+ replace el : { x : P.parts // x.1 .card = s.card / P.parts.card + 1 } ≃
127
+ Fin (s.card % P.parts.card) := (Equiv.Set.sep ..).symm.trans el
128
+ replace es : { x : P.parts // ¬x.1 .card = s.card / P.parts.card + 1 } ≃
129
+ Fin (P.parts.card - s.card % P.parts.card) := (Equiv.Set.sep ..).symm.trans (sneg.trans es)
130
+ let f := (Equiv.sumCompl _).symm.trans ((el.sumCongr es).trans finSumFinEquiv)
131
+ use f.trans (finCongr (Nat.add_sub_of_le P.card_mod_card_parts_le))
132
+ intro ⟨p, _⟩
133
+ simp_rw [f, Equiv.trans_apply, Equiv.sumCongr_apply, finCongr_apply, Fin.coe_cast]
134
+ by_cases hc : p.card = s.card / P.parts.card + 1 <;> simp [hc]
135
+
136
+ /-- Given a finset equipartitioned into `k` parts, its elements can be enumerated such that
137
+ elements in the same part have congruent indices modulo `k`. -/
138
+ theorem IsEquipartition.exists_partPreservingEquiv (hP : P.IsEquipartition) : ∃ f : s ≃ Fin s.card,
139
+ ∀ a b : s, P.part a = P.part b ↔ f a % P.parts.card = f b % P.parts.card := by
140
+ obtain ⟨f, hf⟩ := P.exists_enumeration
141
+ obtain ⟨g, hg⟩ := hP.exists_partsEquiv
142
+ let z := fun a ↦ P.parts.card * (f a).2 + g (f a).1
143
+ have gl := fun a ↦ (g (f a).1 ).2
144
+ have less : ∀ a, z a < s.card := fun a ↦ by
145
+ rcases hP.card_parts_eq_average (f a).1 .2 with (c | c)
146
+ · calc
147
+ _ < P.parts.card * ((f a).2 + 1 ) := add_lt_add_left (gl a) _
148
+ _ ≤ P.parts.card * (s.card / P.parts.card) := mul_le_mul_left' (c ▸ (f a).2 .2 ) _
149
+ _ ≤ P.parts.card * (s.card / P.parts.card) + s.card % P.parts.card := Nat.le_add_right ..
150
+ _ = _ := Nat.div_add_mod ..
151
+ · rw [← Nat.div_add_mod s.card P.parts.card]
152
+ exact add_lt_add_of_le_of_lt (mul_le_mul_left' (by omega) _) ((hg (f a).1 ).mp c)
153
+ let z' : s → Fin s.card := fun a ↦ ⟨z a, less a⟩
154
+ have bij : z'.Bijective := by
155
+ refine (bijective_iff_injective_and_card z').mpr ⟨fun a b e ↦ ?_, by simp⟩
156
+ simp_rw [z', z, Fin.mk.injEq, mul_comm P.parts.card] at e
157
+ haveI : NeZero P.parts.card := ⟨((Nat.zero_le _).trans_lt (gl a)).ne'⟩
158
+ change P.parts.card.divModEquiv.symm (_, _) = P.parts.card.divModEquiv.symm (_, _) at e
159
+ simp only [Equiv.apply_eq_iff_eq, Prod.mk.injEq] at e
160
+ apply_fun f
161
+ exact Sigma.ext e.2 <| (Fin.heq_ext_iff (by rw [e.2 ])).mpr e.1
162
+ use Equiv.ofBijective _ bij
163
+ intro a b
164
+ simp_rw [Equiv.ofBijective_apply, z, hf a b, Nat.mul_add_mod,
165
+ Nat.mod_eq_of_lt (gl a), Nat.mod_eq_of_lt (gl b), Fin.val_eq_val, g.apply_eq_iff_eq]
166
+
167
+ /-! ### Discrete and indiscrete finpartitions -/
70
168
71
169
72
170
variable (s) -- [Decidable (a = ⊥)]
0 commit comments