|
| 1 | +/- |
| 2 | +Copyright (c) 2022 Yaël Dillies, Bhavik Mehta. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Yaël Dillies, Bhavik Mehta |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module combinatorics.simple_graph.regularity.bound |
| 7 | +! leanprover-community/mathlib commit bf7ef0e83e5b7e6c1169e97f055e58a2e4e9d52d |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.Algebra.Order.Chebyshev |
| 12 | +import Mathlib.Analysis.SpecialFunctions.Pow.Real |
| 13 | +import Mathlib.Order.Partition.Equipartition |
| 14 | + |
| 15 | +/-! |
| 16 | +# Numerical bounds for Szemerédi Regularity Lemma |
| 17 | +
|
| 18 | +This file gathers the numerical facts required by the proof of Szemerédi's regularity lemma. |
| 19 | +
|
| 20 | +This entire file is internal to the proof of Szemerédi Regularity Lemma. |
| 21 | +
|
| 22 | +## Main declarations |
| 23 | +
|
| 24 | +* `SzemerediRegularity.stepBound`: During the inductive step, a partition of size `n` is blown to |
| 25 | + size at most `stepBound n`. |
| 26 | +* `SzemerediRegularity.initialBound`: The size of the partition we start the induction with. |
| 27 | +* `SzemerediRegularity.bound`: The upper bound on the size of the partition produced by our version |
| 28 | + of Szemerédi's regularity lemma. |
| 29 | +
|
| 30 | +## References |
| 31 | +
|
| 32 | +[Yaël Dillies, Bhavik Mehta, *Formalising Szemerédi’s Regularity Lemma in Lean*][srl_itp] |
| 33 | +-/ |
| 34 | + |
| 35 | + |
| 36 | +open Finset Fintype Function Real |
| 37 | + |
| 38 | +local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue #2220 |
| 39 | + |
| 40 | +open BigOperators |
| 41 | + |
| 42 | +namespace SzemerediRegularity |
| 43 | + |
| 44 | +/-- Auxiliary function for Szemerédi's regularity lemma. Blowing up a partition of size `n` during |
| 45 | +the induction results in a partition of size at most `stepBound n`. -/ |
| 46 | +def stepBound (n : ℕ) : ℕ := |
| 47 | + n * 4 ^ n |
| 48 | +#align szemeredi_regularity.step_bound SzemerediRegularity.stepBound |
| 49 | + |
| 50 | +theorem le_stepBound : id ≤ stepBound := fun n => Nat.le_mul_of_pos_right <| pow_pos (by norm_num) n |
| 51 | +#align szemeredi_regularity.le_step_bound SzemerediRegularity.le_stepBound |
| 52 | + |
| 53 | +theorem stepBound_mono : Monotone stepBound := fun a b h => |
| 54 | + Nat.mul_le_mul h <| Nat.pow_le_pow_of_le_right (by norm_num) h |
| 55 | +#align szemeredi_regularity.step_bound_mono SzemerediRegularity.stepBound_mono |
| 56 | + |
| 57 | +theorem stepBound_pos_iff {n : ℕ} : 0 < stepBound n ↔ 0 < n := |
| 58 | + zero_lt_mul_right <| by positivity |
| 59 | +#align szemeredi_regularity.step_bound_pos_iff SzemerediRegularity.stepBound_pos_iff |
| 60 | + |
| 61 | +alias stepBound_pos_iff ↔ _ stepBound_pos |
| 62 | +#align szemeredi_regularity.step_bound_pos SzemerediRegularity.stepBound_pos |
| 63 | + |
| 64 | +end SzemerediRegularity |
| 65 | + |
| 66 | +open SzemerediRegularity |
| 67 | + |
| 68 | +variable {α : Type _} [DecidableEq α] [Fintype α] {P : Finpartition (univ : Finset α)} |
| 69 | + {u : Finset α} {ε : ℝ} |
| 70 | + |
| 71 | +local notation3 (prettyPrint := false) |
| 72 | + "m" => (card α / stepBound P.parts.card : ℕ) |
| 73 | + |
| 74 | +local notation3 (prettyPrint := false) |
| 75 | + "a" => (card α / P.parts.card - m * 4 ^ P.parts.card : ℕ) |
| 76 | + |
| 77 | +namespace SzemerediRegularity.Positivity |
| 78 | + |
| 79 | +private theorem eps_pos {ε : ℝ} {n : ℕ} (h : 100 ≤ (4 : ℝ) ^ n * ε ^ 5) : 0 < ε := |
| 80 | + (Odd.pow_pos_iff (by norm_num)).mp |
| 81 | + (pos_of_mul_pos_right ((show 0 < (100 : ℝ) by norm_num).trans_le h) (by positivity)) |
| 82 | + |
| 83 | +private theorem m_pos [Nonempty α] (hPα : P.parts.card * 16 ^ P.parts.card ≤ card α) : 0 < m := |
| 84 | + Nat.div_pos ((Nat.mul_le_mul_left _ <| Nat.pow_le_pow_of_le_left (by norm_num) _).trans hPα) <| |
| 85 | + stepBound_pos (P.parts_nonempty <| univ_nonempty.ne_empty).card_pos |
| 86 | + |
| 87 | +/-- Local extension for the `positivity` tactic: A few facts that are needed many times for the |
| 88 | +proof of Szemerédi's regularity lemma. -/ |
| 89 | +-- Porting note: positivity extensions must now be global, and this did not seem like a good |
| 90 | +-- match for positivity anymore, so I wrote a new tactic (kmill) |
| 91 | +scoped macro "sz_positivity" : tactic => |
| 92 | + `(tactic| |
| 93 | + { try have := m_pos ‹_› |
| 94 | + try have := eps_pos ‹_› |
| 95 | + positivity }) |
| 96 | + |
| 97 | +-- Original meta code |
| 98 | +/- meta def positivity_szemeredi_regularity : expr → tactic strictness |
| 99 | +| `(%%n / step_bound (finpartition.parts %%P).card) := do |
| 100 | + p ← to_expr |
| 101 | + ``((finpartition.parts %%P).card * 16^(finpartition.parts %%P).card ≤ %%n) |
| 102 | + >>= find_assumption, |
| 103 | + positive <$> mk_app ``m_pos [p] |
| 104 | +| ε := do |
| 105 | + typ ← infer_type ε, |
| 106 | + unify typ `(ℝ), |
| 107 | + p ← to_expr ``(100 ≤ 4 ^ _ * %%ε ^ 5) >>= find_assumption, |
| 108 | + positive <$> mk_app ``eps_pos [p] -/ |
| 109 | + |
| 110 | +end SzemerediRegularity.Positivity |
| 111 | + |
| 112 | +namespace SzemerediRegularity |
| 113 | + |
| 114 | +open scoped SzemerediRegularity.Positivity |
| 115 | + |
| 116 | +theorem m_pos [Nonempty α] (hPα : P.parts.card * 16 ^ P.parts.card ≤ card α) : 0 < m := by |
| 117 | + sz_positivity |
| 118 | +#align szemeredi_regularity.m_pos SzemerediRegularity.m_pos |
| 119 | + |
| 120 | +theorem coe_m_add_one_pos : 0 < (m : ℝ) + 1 := by positivity |
| 121 | +#align szemeredi_regularity.coe_m_add_one_pos SzemerediRegularity.coe_m_add_one_pos |
| 122 | + |
| 123 | +theorem one_le_m_coe [Nonempty α] (hPα : P.parts.card * 16 ^ P.parts.card ≤ card α) : (1 : ℝ) ≤ m := |
| 124 | + Nat.one_le_cast.2 <| m_pos hPα |
| 125 | +#align szemeredi_regularity.one_le_m_coe SzemerediRegularity.one_le_m_coe |
| 126 | + |
| 127 | +theorem eps_pow_five_pos (hPε : 100 ≤ (4 : ℝ) ^ P.parts.card * ε ^ 5) : ↑0 < ε ^ 5 := |
| 128 | + pos_of_mul_pos_right ((by norm_num : (0 : ℝ) < 100).trans_le hPε) <| pow_nonneg (by norm_num) _ |
| 129 | +#align szemeredi_regularity.eps_pow_five_pos SzemerediRegularity.eps_pow_five_pos |
| 130 | + |
| 131 | +theorem eps_pos (hPε : 100 ≤ (4 : ℝ) ^ P.parts.card * ε ^ 5) : 0 < ε := |
| 132 | + (Odd.pow_pos_iff (by norm_num)).mp (eps_pow_five_pos hPε) |
| 133 | +#align szemeredi_regularity.eps_pos SzemerediRegularity.eps_pos |
| 134 | + |
| 135 | +theorem hundred_div_ε_pow_five_le_m [Nonempty α] (hPα : P.parts.card * 16 ^ P.parts.card ≤ card α) |
| 136 | + (hPε : 100 ≤ (4 : ℝ) ^ P.parts.card * ε ^ 5) : 100 / ε ^ 5 ≤ m := |
| 137 | + (div_le_of_nonneg_of_le_mul (eps_pow_five_pos hPε).le (by positivity) hPε).trans |
| 138 | + (by |
| 139 | + norm_cast |
| 140 | + rwa [Nat.le_div_iff_mul_le' (stepBound_pos (P.parts_nonempty <| |
| 141 | + univ_nonempty.ne_empty).card_pos), stepBound, mul_left_comm, ← mul_pow]) |
| 142 | +#align szemeredi_regularity.hundred_div_ε_pow_five_le_m SzemerediRegularity.hundred_div_ε_pow_five_le_m |
| 143 | + |
| 144 | +theorem hundred_le_m [Nonempty α] (hPα : P.parts.card * 16 ^ P.parts.card ≤ card α) |
| 145 | + (hPε : 100 ≤ (4 : ℝ) ^ P.parts.card * ε ^ 5) (hε : ε ≤ 1) : 100 ≤ m := by |
| 146 | + exact_mod_cast |
| 147 | + (hundred_div_ε_pow_five_le_m hPα hPε).trans' |
| 148 | + (le_div_self (by norm_num) (by sz_positivity) <| pow_le_one _ (by sz_positivity) hε) |
| 149 | +#align szemeredi_regularity.hundred_le_m SzemerediRegularity.hundred_le_m |
| 150 | + |
| 151 | +theorem a_add_one_le_four_pow_parts_card : a + 1 ≤ 4 ^ P.parts.card := by |
| 152 | + have h : 1 ≤ 4 ^ P.parts.card := one_le_pow_of_one_le (by norm_num) _ |
| 153 | + rw [stepBound, ← Nat.div_div_eq_div_mul] |
| 154 | + conv_rhs => rw [← Nat.sub_add_cancel h] |
| 155 | + rw [add_le_add_iff_right, tsub_le_iff_left, ← Nat.add_sub_assoc h] |
| 156 | + exact Nat.le_pred_of_lt (Nat.lt_div_mul_add h) |
| 157 | +#align szemeredi_regularity.a_add_one_le_four_pow_parts_card SzemerediRegularity.a_add_one_le_four_pow_parts_card |
| 158 | + |
| 159 | +theorem card_aux₁ (hucard : u.card = m * 4 ^ P.parts.card + a) : |
| 160 | + (4 ^ P.parts.card - a) * m + a * (m + 1) = u.card := by |
| 161 | + rw [hucard, mul_add, mul_one, ← add_assoc, ← add_mul, |
| 162 | + Nat.sub_add_cancel ((Nat.le_succ _).trans a_add_one_le_four_pow_parts_card), mul_comm] |
| 163 | +#align szemeredi_regularity.card_aux₁ SzemerediRegularity.card_aux₁ |
| 164 | + |
| 165 | +theorem card_aux₂ (hP : P.IsEquipartition) (hu : u ∈ P.parts) |
| 166 | + (hucard : ¬u.card = m * 4 ^ P.parts.card + a) : |
| 167 | + (4 ^ P.parts.card - (a + 1)) * m + (a + 1) * (m + 1) = u.card := by |
| 168 | + have : m * 4 ^ P.parts.card ≤ card α / P.parts.card := by |
| 169 | + rw [stepBound, ← Nat.div_div_eq_div_mul] |
| 170 | + exact Nat.div_mul_le_self _ _ |
| 171 | + rw [Nat.add_sub_of_le this] at hucard |
| 172 | + rw [(hP.card_parts_eq_average hu).resolve_left hucard, mul_add, mul_one, ← add_assoc, ← add_mul, |
| 173 | + Nat.sub_add_cancel a_add_one_le_four_pow_parts_card, ← add_assoc, mul_comm, |
| 174 | + Nat.add_sub_of_le this, card_univ] |
| 175 | +#align szemeredi_regularity.card_aux₂ SzemerediRegularity.card_aux₂ |
| 176 | + |
| 177 | +theorem pow_mul_m_le_card_part (hP : P.IsEquipartition) (hu : u ∈ P.parts) : |
| 178 | + (4 : ℝ) ^ P.parts.card * m ≤ u.card := by |
| 179 | + norm_cast |
| 180 | + rw [stepBound, ← Nat.div_div_eq_div_mul] |
| 181 | + exact (Nat.mul_div_le _ _).trans (hP.average_le_card_part hu) |
| 182 | +#align szemeredi_regularity.pow_mul_m_le_card_part SzemerediRegularity.pow_mul_m_le_card_part |
| 183 | + |
| 184 | +variable (P ε) (l : ℕ) |
| 185 | + |
| 186 | +/-- Auxiliary function for Szemerédi's regularity lemma. The size of the partition by which we start |
| 187 | +blowing. -/ |
| 188 | +noncomputable def initialBound : ℕ := |
| 189 | + max 7 <| max l <| ⌊log (100 / ε ^ 5) / log 4⌋₊ + 1 |
| 190 | +#align szemeredi_regularity.initial_bound SzemerediRegularity.initialBound |
| 191 | + |
| 192 | +theorem le_initialBound : l ≤ initialBound ε l := |
| 193 | + (le_max_left _ _).trans <| le_max_right _ _ |
| 194 | +#align szemeredi_regularity.le_initial_bound SzemerediRegularity.le_initialBound |
| 195 | + |
| 196 | +theorem seven_le_initialBound : 7 ≤ initialBound ε l := |
| 197 | + le_max_left _ _ |
| 198 | +#align szemeredi_regularity.seven_le_initial_bound SzemerediRegularity.seven_le_initialBound |
| 199 | + |
| 200 | +theorem initialBound_pos : 0 < initialBound ε l := |
| 201 | + Nat.succ_pos'.trans_le <| seven_le_initialBound _ _ |
| 202 | +#align szemeredi_regularity.initial_bound_pos SzemerediRegularity.initialBound_pos |
| 203 | + |
| 204 | +theorem hundred_lt_pow_initialBound_mul {ε : ℝ} (hε : 0 < ε) (l : ℕ) : |
| 205 | + 100 < ↑4 ^ initialBound ε l * ε ^ 5 := by |
| 206 | + rw [← rpow_nat_cast 4, ← div_lt_iff (pow_pos hε 5), lt_rpow_iff_log_lt _ zero_lt_four, ← |
| 207 | + div_lt_iff, initialBound, Nat.cast_max, Nat.cast_max] |
| 208 | + · push_cast |
| 209 | + exact lt_max_of_lt_right (lt_max_of_lt_right <| Nat.lt_floor_add_one _) |
| 210 | + · exact log_pos (by norm_num) |
| 211 | + · exact div_pos (by norm_num) (pow_pos hε 5) |
| 212 | +#align szemeredi_regularity.hundred_lt_pow_initial_bound_mul SzemerediRegularity.hundred_lt_pow_initialBound_mul |
| 213 | + |
| 214 | +/-- An explicit bound on the size of the equipartition whose existence is given by Szemerédi's |
| 215 | +regularity lemma. -/ |
| 216 | +noncomputable def bound : ℕ := |
| 217 | + (stepBound^[⌊4 / ε ^ 5⌋₊] <| initialBound ε l) * |
| 218 | + 16 ^ (stepBound^[⌊4 / ε ^ 5⌋₊] <| initialBound ε l) |
| 219 | +#align szemeredi_regularity.bound SzemerediRegularity.bound |
| 220 | + |
| 221 | +theorem initialBound_le_bound : initialBound ε l ≤ bound ε l := |
| 222 | + (id_le_iterate_of_id_le le_stepBound _ _).trans <| Nat.le_mul_of_pos_right <| by positivity |
| 223 | +#align szemeredi_regularity.initial_bound_le_bound SzemerediRegularity.initialBound_le_bound |
| 224 | + |
| 225 | +theorem le_bound : l ≤ bound ε l := |
| 226 | + (le_initialBound ε l).trans <| initialBound_le_bound ε l |
| 227 | +#align szemeredi_regularity.le_bound SzemerediRegularity.le_bound |
| 228 | + |
| 229 | +theorem bound_pos : 0 < bound ε l := |
| 230 | + (initialBound_pos ε l).trans_le <| initialBound_le_bound ε l |
| 231 | +#align szemeredi_regularity.bound_pos SzemerediRegularity.bound_pos |
| 232 | + |
| 233 | +variable {ι 𝕜 : Type _} [LinearOrderedField 𝕜] (r : ι → ι → Prop) [DecidableRel r] {s t : Finset ι} |
| 234 | + {x : 𝕜} |
| 235 | + |
| 236 | +theorem mul_sq_le_sum_sq (hst : s ⊆ t) (f : ι → 𝕜) (hs : x ^ 2 ≤ ((∑ i in s, f i) / s.card) ^ 2) |
| 237 | + (hs' : (s.card : 𝕜) ≠ 0) : (s.card : 𝕜) * x ^ 2 ≤ ∑ i in t, f i ^ 2 := |
| 238 | + (mul_le_mul_of_nonneg_left (hs.trans sum_div_card_sq_le_sum_sq_div_card) <| |
| 239 | + Nat.cast_nonneg _).trans <| (mul_div_cancel' _ hs').le.trans <| |
| 240 | + sum_le_sum_of_subset_of_nonneg hst fun _ _ _ => sq_nonneg _ |
| 241 | +#align szemeredi_regularity.mul_sq_le_sum_sq SzemerediRegularity.mul_sq_le_sum_sq |
| 242 | + |
| 243 | +theorem add_div_le_sum_sq_div_card (hst : s ⊆ t) (f : ι → 𝕜) (d : 𝕜) (hx : 0 ≤ x) |
| 244 | + (hs : x ≤ |(∑ i in s, f i) / s.card - (∑ i in t, f i) / t.card|) |
| 245 | + (ht : d ≤ ((∑ i in t, f i) / t.card) ^ 2) : |
| 246 | + d + s.card / t.card * x ^ 2 ≤ (∑ i in t, f i ^ 2) / t.card := by |
| 247 | + obtain hscard | hscard := (s.card.cast_nonneg : (0 : 𝕜) ≤ s.card).eq_or_lt |
| 248 | + · simpa [← hscard] using ht.trans sum_div_card_sq_le_sum_sq_div_card |
| 249 | + have htcard : (0 : 𝕜) < t.card := hscard.trans_le (Nat.cast_le.2 (card_le_of_subset hst)) |
| 250 | + have h₁ : x ^ 2 ≤ ((∑ i in s, f i) / s.card - (∑ i in t, f i) / t.card) ^ 2 := |
| 251 | + sq_le_sq.2 (by rwa [abs_of_nonneg hx]) |
| 252 | + have h₂ : x ^ 2 ≤ ((∑ i in s, (f i - (∑ j in t, f j) / t.card)) / s.card) ^ 2 := by |
| 253 | + apply h₁.trans |
| 254 | + rw [sum_sub_distrib, sum_const, nsmul_eq_mul, sub_div, mul_div_cancel_left _ hscard.ne'] |
| 255 | + apply (add_le_add_right ht _).trans |
| 256 | + rw [← mul_div_right_comm, le_div_iff htcard, add_mul, div_mul_cancel _ htcard.ne'] |
| 257 | + have h₃ := mul_sq_le_sum_sq hst (fun i => (f i - (∑ j in t, f j) / t.card)) h₂ hscard.ne' |
| 258 | + apply (add_le_add_left h₃ _).trans |
| 259 | + -- Porting note: was |
| 260 | + -- `simp [← mul_div_right_comm _ (t.card : 𝕜), sub_div' _ _ _ htcard.ne', ← sum_div, ← add_div,` |
| 261 | + -- ` mul_pow, div_le_iff (sq_pos_of_ne_zero _ htcard.ne'), sub_sq, sum_add_distrib, ← sum_mul, ←` |
| 262 | + -- ` mul_sum]` |
| 263 | + simp_rw [sub_div' _ _ _ htcard.ne'] |
| 264 | + conv_lhs => enter [2, 2, x]; rw [div_pow] |
| 265 | + rw [div_pow, ← sum_div, ← mul_div_right_comm _ (t.card : 𝕜), ← add_div, |
| 266 | + div_le_iff (sq_pos_of_ne_zero _ htcard.ne')] |
| 267 | + simp_rw [sub_sq, sum_add_distrib, sum_const, nsmul_eq_mul, sum_sub_distrib, mul_pow, ← sum_mul, |
| 268 | + ← mul_sum, ← sum_mul] |
| 269 | + ring_nf; rfl |
| 270 | +#align szemeredi_regularity.add_div_le_sum_sq_div_card SzemerediRegularity.add_div_le_sum_sq_div_card |
| 271 | + |
| 272 | +end SzemerediRegularity |
| 273 | + |
| 274 | +namespace Tactic |
| 275 | + |
| 276 | +open Lean.Meta Qq |
| 277 | + |
| 278 | +/-- Extension for the `positivity` tactic: `SzemerediRegularity.initialBound` is always positive. -/ |
| 279 | +@[positivity SzemerediRegularity.initialBound _ _] |
| 280 | +def evalInitialBound : Mathlib.Meta.Positivity.PositivityExt where eval {_ _} _ _ e := do |
| 281 | + let (.app (.app _ (ε : Q(ℝ))) (l : Q(ℕ))) ← whnfR e | throwError "not initialBound" |
| 282 | + pure (.positive (q(SzemerediRegularity.initialBound_pos $ε $l) : Lean.Expr)) |
| 283 | + |
| 284 | +example (ε : ℝ) (l : ℕ) : 0 < SzemerediRegularity.initialBound ε l := by positivity |
| 285 | + |
| 286 | +/-- Extension for the `positivity` tactic: `SzemerediRegularity.bound` is always positive. -/ |
| 287 | +@[positivity SzemerediRegularity.bound _ _] |
| 288 | +def evalBound : Mathlib.Meta.Positivity.PositivityExt where eval {_ _} _ _ e := do |
| 289 | + let (.app (.app _ (ε : Q(ℝ))) (l : Q(ℕ))) ← whnfR e | throwError "not bound" |
| 290 | + pure (.positive (q(SzemerediRegularity.bound_pos $ε $l) : Lean.Expr)) |
| 291 | + |
| 292 | +example (ε : ℝ) (l : ℕ) : 0 < SzemerediRegularity.bound ε l := by positivity |
| 293 | + |
| 294 | +end Tactic |
0 commit comments