combinatorics.additive.behrend ⟷ Mathlib.Combinatorics.Additive.Behrend

This file has been ported!

Changes since the initial port

The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(last sync)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -160,7 +160,7 @@ theorem map_zero (d : β„•) (a : Fin 0 β†’ β„•) : map d a = 0 := by simp [map]
 #print Behrend.map_succ /-
 theorem map_succ (a : Fin (n + 1) β†’ β„•) :
     map d a = a 0 + (βˆ‘ x : Fin n, a x.succ * d ^ (x : β„•)) * d := by
-  simp [map, Fin.sum_univ_succ, pow_succ', ← mul_assoc, ← sum_mul]
+  simp [map, Fin.sum_univ_succ, pow_succ, ← mul_assoc, ← sum_mul]
 #align behrend.map_succ Behrend.map_succ
 -/
 
@@ -310,7 +310,7 @@ theorem exists_large_sphere_aux (n d : β„•) :
   refine' exists_le_card_fiber_of_nsmul_le_card_of_maps_to (fun x hx => _) nonempty_range_succ _
   Β· rw [mem_range, lt_succ_iff]
     exact sum_sq_le_of_mem_box hx
-  Β· rw [card_range, _root_.nsmul_eq_mul, mul_div_assoc', cast_add_one, mul_div_cancel_left,
+  Β· rw [card_range, _root_.nsmul_eq_mul, mul_div_assoc', cast_add_one, mul_div_cancel_leftβ‚€,
       card_box]
     exact (cast_add_one_pos _).ne'
 #align behrend.exists_large_sphere_aux Behrend.exists_large_sphere_aux
Diff
@@ -189,7 +189,7 @@ theorem map_eq_iff {x₁ xβ‚‚ : Fin n.succ β†’ β„•} (hx₁ : βˆ€ i, x₁ i < d)
   refine' ⟨fun h => _, fun h => by rw [map_succ', map_succ', h.1, h.2]⟩
   have : x₁ 0 = xβ‚‚ 0 := by
     rw [← mod_eq_of_lt (hx₁ _), ← map_mod, ← mod_eq_of_lt (hxβ‚‚ _), ← map_mod, h]
-  rw [map_succ, map_succ, this, add_right_inj, mul_eq_mul_right_iff] at h 
+  rw [map_succ, map_succ, this, add_right_inj, mul_eq_mul_right_iff] at h
   exact ⟨this, h.resolve_right (pos_of_gt (hx₁ 0)).ne'⟩
 #align behrend.map_eq_iff Behrend.map_eq_iff
 -/
@@ -250,7 +250,7 @@ theorem addSalemSpencer_image_sphere :
 #print Behrend.sum_sq_le_of_mem_box /-
 theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : βˆ‘ i : Fin n, x i ^ 2 ≀ n * (d - 1) ^ 2 :=
   by
-  rw [mem_box] at hx 
+  rw [mem_box] at hx
   have : βˆ€ i, x i ^ 2 ≀ (d - 1) ^ 2 := fun i => Nat.pow_le_pow_left (Nat.le_pred_of_lt (hx i)) _
   exact (sum_le_card_nsmul univ _ _ fun i _ => this i).trans (by rw [card_fin, smul_eq_mul])
 #align behrend.sum_sq_le_of_mem_box Behrend.sum_sq_le_of_mem_box
@@ -326,7 +326,7 @@ theorem exists_large_sphere (n d : β„•) : βˆƒ k, (d ^ n / ↑(n * d ^ 2) : ℝ)
   obtain rfl | hd := d.eq_zero_or_pos
   Β· simp
   rw [← cast_pow]
-  refine' (div_le_div_of_le_left _ _ _).trans hk
+  refine' (div_le_div_of_nonneg_left _ _ _).trans hk
   Β· exact cast_nonneg _
   Β· exact cast_add_one_pos _
   simp only [← le_sub_iff_add_le', cast_mul, ← mul_sub, cast_pow, cast_sub hd, sub_sq, one_pow,
@@ -433,8 +433,8 @@ theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈x
     refine' one_div_le_one_div_of_le (add_pos hx zero_lt_one) _
     apply le_trans _ (add_one_le_exp_of_nonneg <| add_nonneg hx.le zero_le_one)
     exact le_add_of_nonneg_right zero_le_one
-  refine' lt_of_le_of_lt _ (div_lt_div_of_lt_left (exp_pos _) (cast_pos.2 <| ceil_pos.2 hx) h₁)
-  refine' le_trans _ (div_le_div_of_le_of_nonneg (exp_le_exp.2 hβ‚‚) <| add_nonneg hx.le zero_le_one)
+  refine' lt_of_le_of_lt _ (div_lt_div_of_pos_left (exp_pos _) (cast_pos.2 <| ceil_pos.2 hx) h₁)
+  refine' le_trans _ (div_le_div_of_nonneg_right (exp_le_exp.2 hβ‚‚) <| add_nonneg hx.le zero_le_one)
   rw [le_div_iff (add_pos hx zero_lt_one), ← le_div_iff' (exp_pos _), ← exp_sub, neg_mul,
     sub_neg_eq_add, two_mul, sub_add_add_cancel, add_comm _ x]
   refine' le_trans _ (add_one_le_exp_of_nonneg <| add_nonneg hx.le zero_le_one)
@@ -567,7 +567,7 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (1 / nValue N : ℝ) / exp 1 < dVa
   by
   apply div_lt_floor _
   rw [← log_le_log, log_rpow, mul_comm, ← div_eq_mul_one_div]
-  Β· apply le_trans _ (div_le_div_of_le_left _ _ (ceil_lt_mul _).le)
+  Β· apply le_trans _ (div_le_div_of_nonneg_left _ _ (ceil_lt_mul _).le)
     rw [mul_comm, ← div_div, div_sqrt, le_div_iff]
     Β· exact le_sqrt_log hN
     Β· norm_num1
@@ -614,7 +614,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
   have hnβ‚‚ : 2 ≀ n := two_le_n_value (hN.trans' <| by norm_num1)
   have : (2 * d_value N - 1) ^ n ≀ N := le_N (hN.trans' <| by norm_num1)
   refine' ((bound_aux hd.ne' hnβ‚‚).trans <| cast_le.2 <| roth_number_nat.mono this).trans_lt' _
-  refine' (div_lt_div_of_lt hn <| pow_lt_pow_left (bound hN) _ _).trans_le' _
+  refine' (div_lt_div_of_pos_right hn <| pow_lt_pow_left (bound hN) _ _).trans_le' _
   Β· exact div_nonneg (rpow_nonneg_of_nonneg (cast_nonneg _) _) (exp_pos _).le
   Β· exact tsub_pos_of_lt (three_le_n_value <| hN.trans' <| by norm_num1)
   rw [← rpow_nat_cast, div_rpow (rpow_nonneg_of_nonneg hNβ‚€.le _) (exp_pos _).le, ← rpow_mul hNβ‚€.le,
Diff
@@ -251,8 +251,7 @@ theorem addSalemSpencer_image_sphere :
 theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : βˆ‘ i : Fin n, x i ^ 2 ≀ n * (d - 1) ^ 2 :=
   by
   rw [mem_box] at hx 
-  have : βˆ€ i, x i ^ 2 ≀ (d - 1) ^ 2 := fun i =>
-    Nat.pow_le_pow_of_le_left (Nat.le_pred_of_lt (hx i)) _
+  have : βˆ€ i, x i ^ 2 ≀ (d - 1) ^ 2 := fun i => Nat.pow_le_pow_left (Nat.le_pred_of_lt (hx i)) _
   exact (sum_le_card_nsmul univ _ _ fun i _ => this i).trans (by rw [card_fin, smul_eq_mul])
 #align behrend.sum_sq_le_of_mem_box Behrend.sum_sq_le_of_mem_box
 -/
@@ -490,7 +489,6 @@ theorem nValue_pos (hN : 2 ≀ N) : 0 < nValue N :=
 #align behrend.n_value_pos Behrend.nValue_pos
 -/
 
-#print Behrend.two_le_nValue /-
 theorem two_le_nValue (hN : 3 ≀ N) : 2 ≀ nValue N :=
   by
   refine' succ_le_of_lt (lt_ceil.2 <| lt_sqrt_of_sq_lt _)
@@ -500,7 +498,6 @@ theorem two_le_nValue (hN : 3 ≀ N) : 2 ≀ nValue N :=
   rw [cast_pos]
   exact (zero_lt_succ _).trans_le hN
 #align behrend.two_le_n_value Behrend.two_le_nValue
--/
 
 #print Behrend.three_le_nValue /-
 theorem three_le_nValue (hN : 64 ≀ N) : 3 ≀ nValue N :=
@@ -550,7 +547,7 @@ theorem dValue_pos (hN₃ : 8 ≀ N) : 0 < dValue N :=
 theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N :=
   by
   have : (2 * d_value N - 1) ^ n_value N ≀ (2 * d_value N) ^ n_value N :=
-    Nat.pow_le_pow_of_le_left (Nat.sub_le _ _) _
+    Nat.pow_le_pow_left (Nat.sub_le _ _) _
   apply this.trans
   suffices ((2 * d_value N) ^ n_value N : ℝ) ≀ N by exact_mod_cast this
   rw [← rpow_nat_cast]
@@ -617,7 +614,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
   have hnβ‚‚ : 2 ≀ n := two_le_n_value (hN.trans' <| by norm_num1)
   have : (2 * d_value N - 1) ^ n ≀ N := le_N (hN.trans' <| by norm_num1)
   refine' ((bound_aux hd.ne' hnβ‚‚).trans <| cast_le.2 <| roth_number_nat.mono this).trans_lt' _
-  refine' (div_lt_div_of_lt hn <| pow_lt_pow_of_lt_left (bound hN) _ _).trans_le' _
+  refine' (div_lt_div_of_lt hn <| pow_lt_pow_left (bound hN) _ _).trans_le' _
   Β· exact div_nonneg (rpow_nonneg_of_nonneg (cast_nonneg _) _) (exp_pos _).le
   Β· exact tsub_pos_of_lt (three_le_n_value <| hN.trans' <| by norm_num1)
   rw [← rpow_nat_cast, div_rpow (rpow_nonneg_of_nonneg hNβ‚€.le _) (exp_pos _).le, ← rpow_mul hNβ‚€.le,
Diff
@@ -428,9 +428,9 @@ theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈x
     apply (add_le_add_left h₁.le _).trans_eq
     rw [← add_assoc, sub_add_cancel]
     rfl
-  have h₃ : exp (-(x + 1)) ≀ 1 / (x + 1) :=
+  have h₃ : NormedSpace.exp (-(x + 1)) ≀ 1 / (x + 1) :=
     by
-    rw [exp_neg, inv_eq_one_div]
+    rw [NormedSpace.exp_neg, inv_eq_one_div]
     refine' one_div_le_one_div_of_le (add_pos hx zero_lt_one) _
     apply le_trans _ (add_one_le_exp_of_nonneg <| add_nonneg hx.le zero_le_one)
     exact le_add_of_nonneg_right zero_le_one
@@ -447,7 +447,8 @@ theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈x
 theorem div_lt_floor {x : ℝ} (hx : 2 / (1 - 2 / exp 1) ≀ x) : x / exp 1 < (⌊x / 2βŒ‹β‚Š : ℝ) :=
   by
   apply lt_of_le_of_lt _ (sub_one_lt_floor _)
-  have : 0 < 1 - 2 / exp 1 := by
+  have : 0 < 1 - 2 / NormedSpace.exp 1 :=
+    by
     rw [sub_pos, div_lt_one (exp_pos _)]
     exact lt_of_le_of_lt (by norm_num) exp_one_gt_d9
   rwa [le_sub_comm, div_eq_mul_one_div x, div_eq_mul_one_div x, ← mul_sub, div_sub', ←
@@ -623,10 +624,13 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
     mul_comm (_ / _), mul_one_div, cast_sub hnβ‚‚, cast_two, same_sub_div hn.ne', exp_one_rpow,
     div_div, rpow_sub hNβ‚€, rpow_one, div_div, div_eq_mul_inv]
   refine' mul_le_mul_of_nonneg_left _ (cast_nonneg _)
-  rw [mul_inv, mul_inv, ← exp_neg, ← rpow_neg (cast_nonneg _), neg_sub, ← div_eq_mul_inv]
-  have : exp (-4 * sqrt (log N)) = exp (-2 * sqrt (log N)) * exp (-2 * sqrt (log N)) :=
+  rw [mul_inv, mul_inv, ← NormedSpace.exp_neg, ← rpow_neg (cast_nonneg _), neg_sub, ←
+    div_eq_mul_inv]
+  have :
+    NormedSpace.exp (-4 * sqrt (log N)) =
+      NormedSpace.exp (-2 * sqrt (log N)) * NormedSpace.exp (-2 * sqrt (log N)) :=
     by
-    rw [← exp_add, ← add_mul]
+    rw [← NormedSpace.exp_add, ← add_mul]
     norm_num
   rw [this]
   refine'
Diff
@@ -3,10 +3,10 @@ Copyright (c) 2022 YaΓ«l Dillies, Bhavik Mehta. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: YaΓ«l Dillies, Bhavik Mehta
 -/
-import Mathbin.Analysis.InnerProductSpace.PiL2
-import Mathbin.Combinatorics.Additive.SalemSpencer
-import Mathbin.Combinatorics.Pigeonhole
-import Mathbin.Data.Complex.ExponentialBounds
+import Analysis.InnerProductSpace.PiL2
+import Combinatorics.Additive.SalemSpencer
+import Combinatorics.Pigeonhole
+import Data.Complex.ExponentialBounds
 
 #align_import combinatorics.additive.behrend from "leanprover-community/mathlib"@"c20927220ef87bb4962ba08bf6da2ce3cf50a6dd"
 
Diff
@@ -2,17 +2,14 @@
 Copyright (c) 2022 YaΓ«l Dillies, Bhavik Mehta. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: YaΓ«l Dillies, Bhavik Mehta
-
-! This file was ported from Lean 3 source module combinatorics.additive.behrend
-! leanprover-community/mathlib commit c20927220ef87bb4962ba08bf6da2ce3cf50a6dd
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.Analysis.InnerProductSpace.PiL2
 import Mathbin.Combinatorics.Additive.SalemSpencer
 import Mathbin.Combinatorics.Pigeonhole
 import Mathbin.Data.Complex.ExponentialBounds
 
+#align_import combinatorics.additive.behrend from "leanprover-community/mathlib"@"c20927220ef87bb4962ba08bf6da2ce3cf50a6dd"
+
 /-!
 # Behrend's bound on Roth numbers
 
Diff
@@ -124,6 +124,7 @@ theorem sphere_subset_box : sphere n d k βŠ† box n d :=
 #align behrend.sphere_subset_box Behrend.sphere_subset_box
 -/
 
+#print Behrend.norm_of_mem_sphere /-
 theorem norm_of_mem_sphere {x : Fin n β†’ β„•} (hx : x ∈ sphere n d k) :
     β€–(PiLp.equiv 2 _).symm (coe ∘ x : Fin n β†’ ℝ)β€– = sqrt k :=
   by
@@ -131,6 +132,7 @@ theorem norm_of_mem_sphere {x : Fin n β†’ β„•} (hx : x ∈ sphere n d k) :
   dsimp
   simp_rw [abs_cast, ← cast_pow, ← cast_sum, (mem_filter.1 hx).2]
 #align behrend.norm_of_mem_sphere Behrend.norm_of_mem_sphere
+-/
 
 #print Behrend.sphere_subset_preimage_metric_sphere /-
 theorem sphere_subset_preimage_metric_sphere :
@@ -152,27 +154,38 @@ def map (d : β„•) : (Fin n β†’ β„•) β†’+ β„•
 #align behrend.map Behrend.map
 -/
 
+#print Behrend.map_zero /-
 @[simp]
 theorem map_zero (d : β„•) (a : Fin 0 β†’ β„•) : map d a = 0 := by simp [map]
 #align behrend.map_zero Behrend.map_zero
+-/
 
+#print Behrend.map_succ /-
 theorem map_succ (a : Fin (n + 1) β†’ β„•) :
     map d a = a 0 + (βˆ‘ x : Fin n, a x.succ * d ^ (x : β„•)) * d := by
   simp [map, Fin.sum_univ_succ, pow_succ', ← mul_assoc, ← sum_mul]
 #align behrend.map_succ Behrend.map_succ
+-/
 
+#print Behrend.map_succ' /-
 theorem map_succ' (a : Fin (n + 1) β†’ β„•) : map d a = a 0 + map d (a ∘ Fin.succ) * d :=
   map_succ _
 #align behrend.map_succ' Behrend.map_succ'
+-/
 
+#print Behrend.map_monotone /-
 theorem map_monotone (d : β„•) : Monotone (map d : (Fin n β†’ β„•) β†’ β„•) := fun x y h => by dsimp;
   exact sum_le_sum fun i _ => Nat.mul_le_mul_right _ <| h i
 #align behrend.map_monotone Behrend.map_monotone
+-/
 
+#print Behrend.map_mod /-
 theorem map_mod (a : Fin n.succ β†’ β„•) : map d a % d = a 0 % d := by
   rw [map_succ, Nat.add_mul_mod_self_right]
 #align behrend.map_mod Behrend.map_mod
+-/
 
+#print Behrend.map_eq_iff /-
 theorem map_eq_iff {x₁ xβ‚‚ : Fin n.succ β†’ β„•} (hx₁ : βˆ€ i, x₁ i < d) (hxβ‚‚ : βˆ€ i, xβ‚‚ i < d) :
     map d x₁ = map d xβ‚‚ ↔ x₁ 0 = xβ‚‚ 0 ∧ map d (x₁ ∘ Fin.succ) = map d (xβ‚‚ ∘ Fin.succ) :=
   by
@@ -182,7 +195,9 @@ theorem map_eq_iff {x₁ xβ‚‚ : Fin n.succ β†’ β„•} (hx₁ : βˆ€ i, x₁ i < d)
   rw [map_succ, map_succ, this, add_right_inj, mul_eq_mul_right_iff] at h 
   exact ⟨this, h.resolve_right (pos_of_gt (hx₁ 0)).ne'⟩
 #align behrend.map_eq_iff Behrend.map_eq_iff
+-/
 
+#print Behrend.map_injOn /-
 theorem map_injOn : {x : Fin n β†’ β„• | βˆ€ i, x i < d}.InjOn (map d) :=
   by
   intro x₁ hx₁ xβ‚‚ hxβ‚‚ h
@@ -194,11 +209,14 @@ theorem map_injOn : {x : Fin n β†’ β„• | βˆ€ i, x i < d}.InjOn (map d) :=
   Β· exact hx₁ _
   Β· exact hxβ‚‚ _
 #align behrend.map_inj_on Behrend.map_injOn
+-/
 
+#print Behrend.map_le_of_mem_box /-
 theorem map_le_of_mem_box (hx : x ∈ box n d) :
     map (2 * d - 1) x ≀ βˆ‘ i : Fin n, (d - 1) * (2 * d - 1) ^ (i : β„•) :=
   map_monotone (2 * d - 1) fun _ => Nat.le_pred_of_lt <| mem_box.1 hx _
 #align behrend.map_le_of_mem_box Behrend.map_le_of_mem_box
+-/
 
 #print Behrend.addSalemSpencer_sphere /-
 theorem addSalemSpencer_sphere : AddSalemSpencer (sphere n d k : Set (Fin n β†’ β„•)) :=
@@ -215,6 +233,7 @@ theorem addSalemSpencer_sphere : AddSalemSpencer (sphere n d k : Set (Fin n β†’
 #align behrend.add_salem_spencer_sphere Behrend.addSalemSpencer_sphere
 -/
 
+#print Behrend.addSalemSpencer_image_sphere /-
 theorem addSalemSpencer_image_sphere :
     AddSalemSpencer ((sphere n d k).image (map (2 * d - 1)) : Set β„•) :=
   by
@@ -229,6 +248,7 @@ theorem addSalemSpencer_image_sphere :
   rw [lt_tsub_iff_right, ← succ_le_iff, two_mul]
   exact (add_add_add_comm _ _ 1 1).trans_le (add_le_add hai hbi)
 #align behrend.add_salem_spencer_image_sphere Behrend.addSalemSpencer_image_sphere
+-/
 
 #print Behrend.sum_sq_le_of_mem_box /-
 theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : βˆ‘ i : Fin n, x i ^ 2 ≀ n * (d - 1) ^ 2 :=
@@ -286,6 +306,7 @@ that we then optimize by tweaking the parameters. The (almost) optimal parameter
 -/
 
 
+#print Behrend.exists_large_sphere_aux /-
 theorem exists_large_sphere_aux (n d : β„•) :
     βˆƒ k ∈ range (n * (d - 1) ^ 2 + 1),
       (↑(d ^ n) / (↑(n * (d - 1) ^ 2) + 1) : ℝ) ≀ (sphere n d k).card :=
@@ -297,7 +318,9 @@ theorem exists_large_sphere_aux (n d : β„•) :
       card_box]
     exact (cast_add_one_pos _).ne'
 #align behrend.exists_large_sphere_aux Behrend.exists_large_sphere_aux
+-/
 
+#print Behrend.exists_large_sphere /-
 theorem exists_large_sphere (n d : β„•) : βˆƒ k, (d ^ n / ↑(n * d ^ 2) : ℝ) ≀ (sphere n d k).card :=
   by
   obtain ⟨k, -, hk⟩ := exists_large_sphere_aux n d
@@ -318,12 +341,16 @@ theorem exists_large_sphere (n d : β„•) : βˆƒ k, (d ^ n / ↑(n * d ^ 2) : ℝ)
   norm_num
   exact one_le_cast.2 hd
 #align behrend.exists_large_sphere Behrend.exists_large_sphere
+-/
 
+#print Behrend.bound_aux' /-
 theorem bound_aux' (n d : β„•) : (d ^ n / ↑(n * d ^ 2) : ℝ) ≀ rothNumberNat ((2 * d - 1) ^ n) :=
   let ⟨k, h⟩ := exists_large_sphere n d
   h.trans <| cast_le.2 <| card_sphere_le_rothNumberNat _ _ _
 #align behrend.bound_aux' Behrend.bound_aux'
+-/
 
+#print Behrend.bound_aux /-
 theorem bound_aux (hd : d β‰  0) (hn : 2 ≀ n) :
     (d ^ (n - 2) / n : ℝ) ≀ rothNumberNat ((2 * d - 1) ^ n) :=
   by
@@ -331,6 +358,7 @@ theorem bound_aux (hd : d β‰  0) (hn : 2 ≀ n) :
   rw [cast_mul, cast_pow, mul_comm, ← div_div, pow_subβ‚€ _ _ hn, ← div_eq_mul_inv]
   rwa [cast_ne_zero]
 #align behrend.bound_aux Behrend.bound_aux
+-/
 
 open scoped Filter Topology
 
@@ -338,6 +366,7 @@ open Real
 
 section NumericalBounds
 
+#print Behrend.log_two_mul_two_le_sqrt_log_eight /-
 theorem log_two_mul_two_le_sqrt_log_eight : log 2 * 2 ≀ sqrt (log 8) :=
   by
   rw [show (8 : ℝ) = 2 ^ ((3 : β„•) : ℝ) by norm_num1, log_rpow zero_lt_two (3 : β„•)]
@@ -348,14 +377,18 @@ theorem log_two_mul_two_le_sqrt_log_eight : log 2 * 2 ≀ sqrt (log 8) :=
   apply log_two_lt_d9.le.trans
   all_goals norm_num1
 #align behrend.log_two_mul_two_le_sqrt_log_eight Behrend.log_two_mul_two_le_sqrt_log_eight
+-/
 
+#print Behrend.two_div_one_sub_two_div_e_le_eight /-
 theorem two_div_one_sub_two_div_e_le_eight : 2 / (1 - 2 / exp 1) ≀ 8 :=
   by
   rw [div_le_iff, mul_sub, mul_one, mul_div_assoc', le_sub_comm, div_le_iff (exp_pos _)]
   Β· linarith [exp_one_gt_d9]
   rw [sub_pos, div_lt_one] <;> exact exp_one_gt_d9.trans' (by norm_num)
 #align behrend.two_div_one_sub_two_div_e_le_eight Behrend.two_div_one_sub_two_div_e_le_eight
+-/
 
+#print Behrend.le_sqrt_log /-
 theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) ≀ sqrt (log ↑N) :=
   by
   have : ((12 : β„•) : ℝ) * log 2 ≀ log N :=
@@ -387,7 +420,9 @@ theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) 
   Β· exact log_two_lt_d9.le.trans (by norm_num1)
   exact sq_pos_of_ne_zero _ (by norm_num1)
 #align behrend.le_sqrt_log Behrend.le_sqrt_log
+-/
 
+#print Behrend.exp_neg_two_mul_le /-
 theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈xβŒ‰β‚Š) / ⌈xβŒ‰β‚Š :=
   by
   have h₁ := ceil_lt_add_one hx.le
@@ -409,7 +444,9 @@ theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈x
   refine' le_trans _ (add_one_le_exp_of_nonneg <| add_nonneg hx.le zero_le_one)
   exact le_add_of_nonneg_right zero_le_one
 #align behrend.exp_neg_two_mul_le Behrend.exp_neg_two_mul_le
+-/
 
+#print Behrend.div_lt_floor /-
 theorem div_lt_floor {x : ℝ} (hx : 2 / (1 - 2 / exp 1) ≀ x) : x / exp 1 < (⌊x / 2βŒ‹β‚Š : ℝ) :=
   by
   apply lt_of_le_of_lt _ (sub_one_lt_floor _)
@@ -421,7 +458,9 @@ theorem div_lt_floor {x : ℝ} (hx : 2 / (1 - 2 / exp 1) ≀ x) : x / exp 1 < (
   Β· exact zero_lt_two
   Β· exact two_ne_zero
 #align behrend.div_lt_floor Behrend.div_lt_floor
+-/
 
+#print Behrend.ceil_lt_mul /-
 theorem ceil_lt_mul {x : ℝ} (hx : 50 / 19 ≀ x) : (⌈xβŒ‰β‚Š : ℝ) < 1.38 * x :=
   by
   refine' (ceil_lt_add_one <| hx.trans' <| by norm_num).trans_le _
@@ -429,6 +468,7 @@ theorem ceil_lt_mul {x : ℝ} (hx : 50 / 19 ≀ x) : (⌈xβŒ‰β‚Š : ℝ) < 1.38 *
     div_eq_inv_mul, one_le_div]
   norm_num1
 #align behrend.ceil_lt_mul Behrend.ceil_lt_mul
+-/
 
 end NumericalBounds
 
@@ -527,6 +567,7 @@ theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N :=
 #align behrend.le_N Behrend.le_N
 -/
 
+#print Behrend.bound /-
 theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (1 / nValue N : ℝ) / exp 1 < dValue N :=
   by
   apply div_lt_floor _
@@ -565,7 +606,9 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (1 / nValue N : ℝ) / exp 1 < dVa
   rw [cast_pos]
   exact hN.trans_lt' (by norm_num1)
 #align behrend.bound Behrend.bound
+-/
 
+#print Behrend.roth_lower_bound_explicit /-
 theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
     (N : ℝ) * exp (-4 * sqrt (log N)) < rothNumberNat N :=
   by
@@ -601,7 +644,9 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
   Β· rw [one_lt_cast]
     exact hN.trans_lt' (by norm_num1)
 #align behrend.roth_lower_bound_explicit Behrend.roth_lower_bound_explicit
+-/
 
+#print Behrend.exp_four_lt /-
 theorem exp_four_lt : exp 4 < 64 :=
   by
   rw [show (64 : ℝ) = 2 ^ ((6 : β„•) : ℝ) by norm_num1, ←
@@ -609,14 +654,18 @@ theorem exp_four_lt : exp 4 < 64 :=
   exact log_two_gt_d9.trans_le' (by norm_num1)
   norm_num
 #align behrend.exp_four_lt Behrend.exp_four_lt
+-/
 
+#print Behrend.four_zero_nine_six_lt_exp_sixteen /-
 theorem four_zero_nine_six_lt_exp_sixteen : 4096 < exp 16 :=
   by
   rw [← log_lt_iff_lt_exp (show (0 : ℝ) < 4096 by norm_num), show (4096 : ℝ) = 2 ^ 12 by norm_num, ←
     rpow_nat_cast, log_rpow zero_lt_two, cast_bit0, cast_bit0, cast_bit1, cast_one]
   linarith [log_two_lt_d9]
 #align behrend.four_zero_nine_six_lt_exp_sixteen Behrend.four_zero_nine_six_lt_exp_sixteen
+-/
 
+#print Behrend.lower_bound_le_one' /-
 theorem lower_bound_le_one' (hN : 2 ≀ N) (hN' : N ≀ 4096) : (N : ℝ) * exp (-4 * sqrt (log N)) ≀ 1 :=
   by
   rw [← log_le_log (mul_pos (cast_pos.2 (zero_lt_two.trans_le hN)) (exp_pos _)) zero_lt_one,
@@ -629,14 +678,18 @@ theorem lower_bound_le_one' (hN : 2 ≀ N) (hN' : N ≀ 4096) : (N : ℝ) * exp
   apply le_trans _ four_zero_nine_six_lt_exp_sixteen.le
   exact_mod_cast hN'
 #align behrend.lower_bound_le_one' Behrend.lower_bound_le_one'
+-/
 
+#print Behrend.lower_bound_le_one /-
 theorem lower_bound_le_one (hN : 1 ≀ N) (hN' : N ≀ 4096) : (N : ℝ) * exp (-4 * sqrt (log N)) ≀ 1 :=
   by
   obtain rfl | hN := hN.eq_or_lt
   Β· norm_num
   Β· exact lower_bound_le_one' hN hN'
 #align behrend.lower_bound_le_one Behrend.lower_bound_le_one
+-/
 
+#print Behrend.roth_lower_bound /-
 theorem roth_lower_bound : (N : ℝ) * exp (-4 * sqrt (log N)) ≀ rothNumberNat N :=
   by
   obtain rfl | hN := Nat.eq_zero_or_pos N
@@ -646,6 +699,7 @@ theorem roth_lower_bound : (N : ℝ) * exp (-4 * sqrt (log N)) ≀ rothNumberNat
   Β· apply (lower_bound_le_one hN h₁.le).trans
     simpa using roth_number_nat.monotone hN
 #align behrend.roth_lower_bound Behrend.roth_lower_bound
+-/
 
 end Behrend
 
Diff
@@ -102,7 +102,7 @@ theorem box_zero : box (n + 1) 0 = βˆ… := by simp [box]
 /-- The intersection of the sphere of radius `sqrt k` with the integer points in the positive
 quadrant. -/
 def sphere (n d k : β„•) : Finset (Fin n β†’ β„•) :=
-  (box n d).filterβ‚“ fun x => (βˆ‘ i, x i ^ 2) = k
+  (box n d).filterβ‚“ fun x => βˆ‘ i, x i ^ 2 = k
 #align behrend.sphere Behrend.sphere
 -/
 
@@ -231,7 +231,7 @@ theorem addSalemSpencer_image_sphere :
 #align behrend.add_salem_spencer_image_sphere Behrend.addSalemSpencer_image_sphere
 
 #print Behrend.sum_sq_le_of_mem_box /-
-theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : (βˆ‘ i : Fin n, x i ^ 2) ≀ n * (d - 1) ^ 2 :=
+theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : βˆ‘ i : Fin n, x i ^ 2 ≀ n * (d - 1) ^ 2 :=
   by
   rw [mem_box] at hx 
   have : βˆ€ i, x i ^ 2 ≀ (d - 1) ^ 2 := fun i =>
@@ -241,7 +241,7 @@ theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : (βˆ‘ i : Fin n, x i ^ 2) ≀
 -/
 
 #print Behrend.sum_eq /-
-theorem sum_eq : (βˆ‘ i : Fin n, d * (2 * d + 1) ^ (i : β„•)) = ((2 * d + 1) ^ n - 1) / 2 :=
+theorem sum_eq : βˆ‘ i : Fin n, d * (2 * d + 1) ^ (i : β„•) = ((2 * d + 1) ^ n - 1) / 2 :=
   by
   refine' (Nat.div_eq_of_eq_mul_left zero_lt_two _).symm
   rw [← sum_range fun i => d * (2 * d + 1) ^ (i : β„•), ← mul_sum, mul_right_comm, mul_comm d, ←
@@ -250,7 +250,7 @@ theorem sum_eq : (βˆ‘ i : Fin n, d * (2 * d + 1) ^ (i : β„•)) = ((2 * d + 1) ^ n
 -/
 
 #print Behrend.sum_lt /-
-theorem sum_lt : (βˆ‘ i : Fin n, d * (2 * d + 1) ^ (i : β„•)) < (2 * d + 1) ^ n :=
+theorem sum_lt : βˆ‘ i : Fin n, d * (2 * d + 1) ^ (i : β„•) < (2 * d + 1) ^ n :=
   sum_eq.trans_lt <| (Nat.div_le_self _ 2).trans_lt <| pred_lt (pow_pos (succ_pos _) _).ne'
 #align behrend.sum_lt Behrend.sum_lt
 -/
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: YaΓ«l Dillies, Bhavik Mehta
 
 ! This file was ported from Lean 3 source module combinatorics.additive.behrend
-! leanprover-community/mathlib commit 4fa54b337f7d52805480306db1b1439c741848c8
+! leanprover-community/mathlib commit c20927220ef87bb4962ba08bf6da2ce3cf50a6dd
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -16,6 +16,9 @@ import Mathbin.Data.Complex.ExponentialBounds
 /-!
 # Behrend's bound on Roth numbers
 
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
 This file proves Behrend's lower bound on Roth numbers. This says that we can find a subset of
 `{1, ..., n}` of size `n / exp (O (sqrt (log n)))` which does not contain arithmetic progressions of
 length `3`.
Diff
@@ -71,39 +71,55 @@ an additive monoid homomorphism.
 -/
 
 
+#print Behrend.box /-
 /-- The box `{0, ..., d - 1}^n` as a finset. -/
 def box (n d : β„•) : Finset (Fin n β†’ β„•) :=
   Fintype.piFinset fun _ => range d
 #align behrend.box Behrend.box
+-/
 
+#print Behrend.mem_box /-
 theorem mem_box : x ∈ box n d ↔ βˆ€ i, x i < d := by simp only [box, Fintype.mem_piFinset, mem_range]
 #align behrend.mem_box Behrend.mem_box
+-/
 
+#print Behrend.card_box /-
 @[simp]
 theorem card_box : (box n d).card = d ^ n := by simp [box]
 #align behrend.card_box Behrend.card_box
+-/
 
+#print Behrend.box_zero /-
 @[simp]
 theorem box_zero : box (n + 1) 0 = βˆ… := by simp [box]
 #align behrend.box_zero Behrend.box_zero
+-/
 
+#print Behrend.sphere /-
 /-- The intersection of the sphere of radius `sqrt k` with the integer points in the positive
 quadrant. -/
 def sphere (n d k : β„•) : Finset (Fin n β†’ β„•) :=
   (box n d).filterβ‚“ fun x => (βˆ‘ i, x i ^ 2) = k
 #align behrend.sphere Behrend.sphere
+-/
 
+#print Behrend.sphere_zero_subset /-
 theorem sphere_zero_subset : sphere n d 0 βŠ† 0 := fun x => by
   simp (config := { contextual := true }) [sphere, Function.funext_iff]
 #align behrend.sphere_zero_subset Behrend.sphere_zero_subset
+-/
 
+#print Behrend.sphere_zero_right /-
 @[simp]
 theorem sphere_zero_right (n k : β„•) : sphere (n + 1) 0 k = βˆ… := by simp [sphere]
 #align behrend.sphere_zero_right Behrend.sphere_zero_right
+-/
 
+#print Behrend.sphere_subset_box /-
 theorem sphere_subset_box : sphere n d k βŠ† box n d :=
   filter_subset _ _
 #align behrend.sphere_subset_box Behrend.sphere_subset_box
+-/
 
 theorem norm_of_mem_sphere {x : Fin n β†’ β„•} (hx : x ∈ sphere n d k) :
     β€–(PiLp.equiv 2 _).symm (coe ∘ x : Fin n β†’ ℝ)β€– = sqrt k :=
@@ -113,13 +129,16 @@ theorem norm_of_mem_sphere {x : Fin n β†’ β„•} (hx : x ∈ sphere n d k) :
   simp_rw [abs_cast, ← cast_pow, ← cast_sum, (mem_filter.1 hx).2]
 #align behrend.norm_of_mem_sphere Behrend.norm_of_mem_sphere
 
+#print Behrend.sphere_subset_preimage_metric_sphere /-
 theorem sphere_subset_preimage_metric_sphere :
     (sphere n d k : Set (Fin n β†’ β„•)) βŠ†
       (fun x : Fin n β†’ β„• => (PiLp.equiv 2 _).symm (coe ∘ x : Fin n β†’ ℝ)) ⁻¹'
         Metric.sphere (0 : PiLp 2 fun _ : Fin n => ℝ) (sqrt k) :=
   fun x hx => by rw [Set.mem_preimage, mem_sphere_zero_iff_norm, norm_of_mem_sphere hx]
 #align behrend.sphere_subset_preimage_metric_sphere Behrend.sphere_subset_preimage_metric_sphere
+-/
 
+#print Behrend.map /-
 /-- The map that appears in Behrend's bound on Roth numbers. -/
 @[simps]
 def map (d : β„•) : (Fin n β†’ β„•) β†’+ β„•
@@ -128,6 +147,7 @@ def map (d : β„•) : (Fin n β†’ β„•) β†’+ β„•
   map_zero' := by simp_rw [Pi.zero_apply, MulZeroClass.zero_mul, sum_const_zero]
   map_add' a b := by simp_rw [Pi.add_apply, add_mul, sum_add_distrib]
 #align behrend.map Behrend.map
+-/
 
 @[simp]
 theorem map_zero (d : β„•) (a : Fin 0 β†’ β„•) : map d a = 0 := by simp [map]
@@ -177,6 +197,7 @@ theorem map_le_of_mem_box (hx : x ∈ box n d) :
   map_monotone (2 * d - 1) fun _ => Nat.le_pred_of_lt <| mem_box.1 hx _
 #align behrend.map_le_of_mem_box Behrend.map_le_of_mem_box
 
+#print Behrend.addSalemSpencer_sphere /-
 theorem addSalemSpencer_sphere : AddSalemSpencer (sphere n d k : Set (Fin n β†’ β„•)) :=
   by
   set f : (Fin n β†’ β„•) β†’+ EuclideanSpace ℝ (Fin n) :=
@@ -189,6 +210,7 @@ theorem addSalemSpencer_sphere : AddSalemSpencer (sphere n d k : Set (Fin n β†’
   rw [Set.mem_preimage, mem_sphere_zero_iff_norm]
   exact norm_of_mem_sphere
 #align behrend.add_salem_spencer_sphere Behrend.addSalemSpencer_sphere
+-/
 
 theorem addSalemSpencer_image_sphere :
     AddSalemSpencer ((sphere n d k).image (map (2 * d - 1)) : Set β„•) :=
@@ -205,6 +227,7 @@ theorem addSalemSpencer_image_sphere :
   exact (add_add_add_comm _ _ 1 1).trans_le (add_le_add hai hbi)
 #align behrend.add_salem_spencer_image_sphere Behrend.addSalemSpencer_image_sphere
 
+#print Behrend.sum_sq_le_of_mem_box /-
 theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : (βˆ‘ i : Fin n, x i ^ 2) ≀ n * (d - 1) ^ 2 :=
   by
   rw [mem_box] at hx 
@@ -212,18 +235,24 @@ theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : (βˆ‘ i : Fin n, x i ^ 2) ≀
     Nat.pow_le_pow_of_le_left (Nat.le_pred_of_lt (hx i)) _
   exact (sum_le_card_nsmul univ _ _ fun i _ => this i).trans (by rw [card_fin, smul_eq_mul])
 #align behrend.sum_sq_le_of_mem_box Behrend.sum_sq_le_of_mem_box
+-/
 
+#print Behrend.sum_eq /-
 theorem sum_eq : (βˆ‘ i : Fin n, d * (2 * d + 1) ^ (i : β„•)) = ((2 * d + 1) ^ n - 1) / 2 :=
   by
   refine' (Nat.div_eq_of_eq_mul_left zero_lt_two _).symm
   rw [← sum_range fun i => d * (2 * d + 1) ^ (i : β„•), ← mul_sum, mul_right_comm, mul_comm d, ←
     geom_sum_mul_add, add_tsub_cancel_right, mul_comm]
 #align behrend.sum_eq Behrend.sum_eq
+-/
 
+#print Behrend.sum_lt /-
 theorem sum_lt : (βˆ‘ i : Fin n, d * (2 * d + 1) ^ (i : β„•)) < (2 * d + 1) ^ n :=
   sum_eq.trans_lt <| (Nat.div_le_self _ 2).trans_lt <| pred_lt (pow_pos (succ_pos _) _).ne'
 #align behrend.sum_lt Behrend.sum_lt
+-/
 
+#print Behrend.card_sphere_le_rothNumberNat /-
 theorem card_sphere_le_rothNumberNat (n d k : β„•) :
     (sphere n d k).card ≀ rothNumberNat ((2 * d - 1) ^ n) :=
   by
@@ -242,6 +271,7 @@ theorem card_sphere_le_rothNumberNat (n d k : β„•) :
   simp only [mem_coe, sphere, mem_filter, mem_box, and_imp, two_mul]
   exact fun h _ i => (h i).trans_le le_self_add
 #align behrend.card_sphere_le_roth_number_nat Behrend.card_sphere_le_rothNumberNat
+-/
 
 /-!
 ### Optimization
@@ -399,20 +429,27 @@ theorem ceil_lt_mul {x : ℝ} (hx : 50 / 19 ≀ x) : (⌈xβŒ‰β‚Š : ℝ) < 1.38 *
 
 end NumericalBounds
 
+#print Behrend.nValue /-
 /-- The (almost) optimal value of `n` in `behrend.bound_aux`. -/
 noncomputable def nValue (N : β„•) : β„• :=
   ⌈sqrt (log N)βŒ‰β‚Š
 #align behrend.n_value Behrend.nValue
+-/
 
+#print Behrend.dValue /-
 /-- The (almost) optimal value of `d` in `behrend.bound_aux`. -/
 noncomputable def dValue (N : β„•) : β„• :=
   ⌊(N : ℝ) ^ (1 / nValue N : ℝ) / 2βŒ‹β‚Š
 #align behrend.d_value Behrend.dValue
+-/
 
+#print Behrend.nValue_pos /-
 theorem nValue_pos (hN : 2 ≀ N) : 0 < nValue N :=
   ceil_pos.2 <| Real.sqrt_pos.2 <| log_pos <| one_lt_cast.2 <| hN
 #align behrend.n_value_pos Behrend.nValue_pos
+-/
 
+#print Behrend.two_le_nValue /-
 theorem two_le_nValue (hN : 3 ≀ N) : 2 ≀ nValue N :=
   by
   refine' succ_le_of_lt (lt_ceil.2 <| lt_sqrt_of_sq_lt _)
@@ -422,7 +459,9 @@ theorem two_le_nValue (hN : 3 ≀ N) : 2 ≀ nValue N :=
   rw [cast_pos]
   exact (zero_lt_succ _).trans_le hN
 #align behrend.two_le_n_value Behrend.two_le_nValue
+-/
 
+#print Behrend.three_le_nValue /-
 theorem three_le_nValue (hN : 64 ≀ N) : 3 ≀ nValue N :=
   by
   rw [n_value, ← lt_iff_add_one_le, lt_ceil, cast_two]
@@ -437,7 +476,9 @@ theorem three_le_nValue (hN : 64 ≀ N) : 3 ≀ nValue N :=
   rw [cast_pos]
   exact hN.trans_lt' (by norm_num1)
 #align behrend.three_le_n_value Behrend.three_le_nValue
+-/
 
+#print Behrend.dValue_pos /-
 theorem dValue_pos (hN₃ : 8 ≀ N) : 0 < dValue N :=
   by
   have hNβ‚€ : 0 < (N : ℝ) := cast_pos.2 (succ_pos'.trans_le hN₃)
@@ -462,7 +503,9 @@ theorem dValue_pos (hN₃ : 8 ≀ N) : 0 < dValue N :=
   Β· exact (rpow_pos_of_pos hNβ‚€ _).ne'
   Β· exact div_pos (rpow_pos_of_pos hNβ‚€ _) zero_lt_two
 #align behrend.d_value_pos Behrend.dValue_pos
+-/
 
+#print Behrend.le_N /-
 theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N :=
   by
   have : (2 * d_value N - 1) ^ n_value N ≀ (2 * d_value N) ^ n_value N :=
@@ -479,6 +522,7 @@ theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N :=
   Β· exact floor_le (div_nonneg (rpow_nonneg_of_nonneg (cast_nonneg _) _) zero_le_two)
   apply zero_lt_two
 #align behrend.le_N Behrend.le_N
+-/
 
 theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (1 / nValue N : ℝ) / exp 1 < dValue N :=
   by
Diff
@@ -160,7 +160,7 @@ theorem map_eq_iff {x₁ xβ‚‚ : Fin n.succ β†’ β„•} (hx₁ : βˆ€ i, x₁ i < d)
   exact ⟨this, h.resolve_right (pos_of_gt (hx₁ 0)).ne'⟩
 #align behrend.map_eq_iff Behrend.map_eq_iff
 
-theorem map_injOn : { x : Fin n β†’ β„• | βˆ€ i, x i < d }.InjOn (map d) :=
+theorem map_injOn : {x : Fin n β†’ β„• | βˆ€ i, x i < d}.InjOn (map d) :=
   by
   intro x₁ hx₁ xβ‚‚ hxβ‚‚ h
   induction' n with n ih
Diff
@@ -156,7 +156,7 @@ theorem map_eq_iff {x₁ xβ‚‚ : Fin n.succ β†’ β„•} (hx₁ : βˆ€ i, x₁ i < d)
   refine' ⟨fun h => _, fun h => by rw [map_succ', map_succ', h.1, h.2]⟩
   have : x₁ 0 = xβ‚‚ 0 := by
     rw [← mod_eq_of_lt (hx₁ _), ← map_mod, ← mod_eq_of_lt (hxβ‚‚ _), ← map_mod, h]
-  rw [map_succ, map_succ, this, add_right_inj, mul_eq_mul_right_iff] at h
+  rw [map_succ, map_succ, this, add_right_inj, mul_eq_mul_right_iff] at h 
   exact ⟨this, h.resolve_right (pos_of_gt (hx₁ 0)).ne'⟩
 #align behrend.map_eq_iff Behrend.map_eq_iff
 
@@ -207,7 +207,7 @@ theorem addSalemSpencer_image_sphere :
 
 theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : (βˆ‘ i : Fin n, x i ^ 2) ≀ n * (d - 1) ^ 2 :=
   by
-  rw [mem_box] at hx
+  rw [mem_box] at hx 
   have : βˆ€ i, x i ^ 2 ≀ (d - 1) ^ 2 := fun i =>
     Nat.pow_le_pow_of_le_left (Nat.le_pred_of_lt (hx i)) _
   exact (sum_le_card_nsmul univ _ _ fun i _ => this i).trans (by rw [card_fin, smul_eq_mul])
Diff
@@ -54,7 +54,7 @@ open Nat hiding log
 
 open Real
 
-open BigOperators Pointwise
+open scoped BigOperators Pointwise
 
 namespace Behrend
 
@@ -299,7 +299,7 @@ theorem bound_aux (hd : d β‰  0) (hn : 2 ≀ n) :
   rwa [cast_ne_zero]
 #align behrend.bound_aux Behrend.bound_aux
 
-open Filter Topology
+open scoped Filter Topology
 
 open Real
 
Diff
@@ -142,9 +142,7 @@ theorem map_succ' (a : Fin (n + 1) β†’ β„•) : map d a = a 0 + map d (a ∘ Fin.s
   map_succ _
 #align behrend.map_succ' Behrend.map_succ'
 
-theorem map_monotone (d : β„•) : Monotone (map d : (Fin n β†’ β„•) β†’ β„•) := fun x y h =>
-  by
-  dsimp
+theorem map_monotone (d : β„•) : Monotone (map d : (Fin n β†’ β„•) β†’ β„•) := fun x y h => by dsimp;
   exact sum_le_sum fun i _ => Nat.mul_le_mul_right _ <| h i
 #align behrend.map_monotone Behrend.map_monotone
 
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: YaΓ«l Dillies, Bhavik Mehta
 
 ! This file was ported from Lean 3 source module combinatorics.additive.behrend
-! leanprover-community/mathlib commit 0b9eaaa7686280fad8cce467f5c3c57ee6ce77f8
+! leanprover-community/mathlib commit 4fa54b337f7d52805480306db1b1439c741848c8
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -12,7 +12,6 @@ import Mathbin.Analysis.InnerProductSpace.PiL2
 import Mathbin.Combinatorics.Additive.SalemSpencer
 import Mathbin.Combinatorics.Pigeonhole
 import Mathbin.Data.Complex.ExponentialBounds
-import Mathbin.Analysis.SpecialFunctions.Pow.Tactic
 
 /-!
 # Behrend's bound on Roth numbers
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: YaΓ«l Dillies, Bhavik Mehta
 
 ! This file was ported from Lean 3 source module combinatorics.additive.behrend
-! leanprover-community/mathlib commit ceb887ddf3344dab425292e497fa2af91498437c
+! leanprover-community/mathlib commit 0b9eaaa7686280fad8cce467f5c3c57ee6ce77f8
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -12,6 +12,7 @@ import Mathbin.Analysis.InnerProductSpace.PiL2
 import Mathbin.Combinatorics.Additive.SalemSpencer
 import Mathbin.Combinatorics.Pigeonhole
 import Mathbin.Data.Complex.ExponentialBounds
+import Mathbin.Analysis.SpecialFunctions.Pow.Tactic
 
 /-!
 # Behrend's bound on Roth numbers
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: YaΓ«l Dillies, Bhavik Mehta
 
 ! This file was ported from Lean 3 source module combinatorics.additive.behrend
-! leanprover-community/mathlib commit f2ce6086713c78a7f880485f7917ea547a215982
+! leanprover-community/mathlib commit ceb887ddf3344dab425292e497fa2af91498437c
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -48,7 +48,11 @@ Salem-Spencer, Behrend construction, arithmetic progression, sphere, strictly co
 -/
 
 
-open Finset Nat Real
+open Finset
+
+open Nat hiding log
+
+open Real
 
 open BigOperators Pointwise
 
@@ -490,7 +494,7 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (1 / nValue N : ℝ) / exp 1 < dVa
       rw [one_le_cast]
       exact hN.trans' (by norm_num1)
     Β· rw [cast_pos, lt_ceil, cast_zero, Real.sqrt_pos]
-      apply log_pos
+      refine' log_pos _
       rw [one_lt_cast]
       exact hN.trans_lt' (by norm_num1)
     apply le_sqrt_of_sq_le
Diff
@@ -121,7 +121,7 @@ theorem sphere_subset_preimage_metric_sphere :
 def map (d : β„•) : (Fin n β†’ β„•) β†’+ β„•
     where
   toFun a := βˆ‘ i, a i * d ^ (i : β„•)
-  map_zero' := by simp_rw [Pi.zero_apply, zero_mul, sum_const_zero]
+  map_zero' := by simp_rw [Pi.zero_apply, MulZeroClass.zero_mul, sum_const_zero]
   map_add' a b := by simp_rw [Pi.add_apply, add_mul, sum_add_distrib]
 #align behrend.map Behrend.map
 

Changes in mathlib4

mathlib3
mathlib4
chore: adapt to multiple goal linter 2 (#12361)

A PR analogous to #12338: reformatting proofs following the multiple goals linter of #12339.

Diff
@@ -293,7 +293,7 @@ theorem log_two_mul_two_le_sqrt_log_eight : log 2 * 2 ≀ √(log 8) := by
   rw [mul_pow, sq (log 2), mul_assoc, mul_comm]
   refine' mul_le_mul_of_nonneg_right _ (log_nonneg one_le_two)
   rw [← le_div_iff]
-  apply log_two_lt_d9.le.trans
+  on_goal 1 => apply log_two_lt_d9.le.trans
   all_goals norm_num1
 #align behrend.log_two_mul_two_le_sqrt_log_eight Behrend.log_two_mul_two_le_sqrt_log_eight
 
@@ -428,9 +428,9 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dV
   apply div_lt_floor _
   rw [← log_le_log_iff, log_rpow, mul_comm, ← div_eq_mul_inv]
   Β· apply le_trans _ (div_le_div_of_nonneg_left _ _ (ceil_lt_mul _).le)
-    rw [mul_comm, ← div_div, div_sqrt, le_div_iff]
-    Β· set_option tactic.skipAssignedInstances false in norm_num; exact le_sqrt_log hN
-    Β· norm_num1
+    Β· rw [mul_comm, ← div_div, div_sqrt, le_div_iff]
+      Β· set_option tactic.skipAssignedInstances false in norm_num; exact le_sqrt_log hN
+      Β· norm_num1
     Β· apply log_nonneg
       rw [one_le_cast]
       exact hN.trans' (by norm_num1)
@@ -491,8 +491,8 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
 theorem exp_four_lt : exp 4 < 64 := by
   rw [show (64 : ℝ) = 2 ^ ((6 : β„•) : ℝ) by rw [rpow_natCast]; norm_num1,
     ← lt_log_iff_exp_lt (rpow_pos_of_pos zero_lt_two _), log_rpow zero_lt_two, ← div_lt_iff']
-  exact log_two_gt_d9.trans_le' (by norm_num1)
-  norm_num
+  Β· exact log_two_gt_d9.trans_le' (by norm_num1)
+  Β· norm_num
 #align behrend.exp_four_lt Behrend.exp_four_lt
 
 theorem four_zero_nine_six_lt_exp_sixteen : 4096 < exp 16 := by
chore: make argument to sq_pos_of_ne_zero/sq_pos_iff implicit (#12288)

This matches our general policy and zpow_two_pos_of_ne_zero.

Also define sq_pos_of_ne_zero as an alias.

Diff
@@ -322,7 +322,7 @@ theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) 
   apply mul_le_mul_of_nonneg_right _ (log_nonneg one_le_two)
   rw [← le_div_iff']
   Β· exact log_two_lt_d9.le.trans (by norm_num1)
-  exact sq_pos_of_ne_zero _ (by norm_num1)
+  exact sq_pos_of_ne_zero (by norm_num1)
 #align behrend.le_sqrt_log Behrend.le_sqrt_log
 
 theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈xβŒ‰β‚Š) / ⌈xβŒ‰β‚Š := by
chore: Rename nat_cast/int_cast/rat_cast to natCast/intCast/ratCast (#11486)

Now that I am defining NNRat.cast, I want a definitive answer to this naming issue. Plenty of lemmas in mathlib already use natCast/intCast/ratCast over nat_cast/int_cast/rat_cast, and this matches with the general expectation that underscore-separated name parts correspond to a single declaration.

Diff
@@ -287,7 +287,7 @@ open Real
 section NumericalBounds
 
 theorem log_two_mul_two_le_sqrt_log_eight : log 2 * 2 ≀ √(log 8) := by
-  have : (8 : ℝ) = 2 ^ ((3 : β„•) : ℝ) := by rw [rpow_nat_cast]; norm_num
+  have : (8 : ℝ) = 2 ^ ((3 : β„•) : ℝ) := by rw [rpow_natCast]; norm_num
   rw [this, log_rpow zero_lt_two (3 : β„•)]
   apply le_sqrt_of_sq_le
   rw [mul_pow, sq (log 2), mul_assoc, mul_comm]
@@ -306,7 +306,7 @@ theorem two_div_one_sub_two_div_e_le_eight : 2 / (1 - 2 / exp 1) ≀ 8 := by
 
 theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) ≀ √(log ↑N) := by
   have : (12 : β„•) * log 2 ≀ log N := by
-    rw [← log_rpow zero_lt_two, rpow_nat_cast]
+    rw [← log_rpow zero_lt_two, rpow_natCast]
     exact log_le_log (by positivity) (mod_cast hN)
   refine (mul_le_mul_of_nonneg_right (log_le_log ?_ two_div_one_sub_two_div_e_le_eight) <| by
     norm_num1).trans ?_
@@ -314,7 +314,7 @@ theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) 
     rw [sub_pos, div_lt_one (exp_pos _)]
     exact exp_one_gt_d9.trans_le' (by norm_num1)
   have l8 : log 8 = (3 : β„•) * log 2 := by
-    rw [← log_rpow zero_lt_two, rpow_nat_cast]
+    rw [← log_rpow zero_lt_two, rpow_natCast]
     norm_num
   rw [l8]
   apply le_sqrt_of_sq_le (le_trans _ this)
@@ -378,7 +378,7 @@ theorem three_le_nValue (hN : 64 ≀ N) : 3 ≀ nValue N := by
   rw [nValue, ← lt_iff_add_one_le, lt_ceil, cast_two]
   apply lt_sqrt_of_sq_lt
   have : (2 : ℝ) ^ ((6 : β„•) : ℝ) ≀ N := by
-    rw [rpow_nat_cast]
+    rw [rpow_natCast]
     exact (cast_le.2 hN).trans' (by norm_num1)
   apply lt_of_lt_of_le _ (log_le_log (rpow_pos_of_pos zero_lt_two _) this)
   rw [log_rpow zero_lt_two, ← div_lt_iff']
@@ -413,7 +413,7 @@ theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N := by
   apply this.trans
   suffices ((2 * dValue N) ^ nValue N : ℝ) ≀ N from mod_cast this
   suffices i : (2 * dValue N : ℝ) ≀ (N : ℝ) ^ (nValue N : ℝ)⁻¹ by
-    rw [← rpow_nat_cast]
+    rw [← rpow_natCast]
     apply (rpow_le_rpow (mul_nonneg zero_le_two (cast_nonneg _)) i (cast_nonneg _)).trans
     rw [← rpow_mul (cast_nonneg _), inv_mul_cancel, rpow_one]
     rw [cast_ne_zero]
@@ -440,7 +440,7 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dV
       exact hN.trans_lt' (by norm_num1)
     apply le_sqrt_of_sq_le
     have : (12 : β„•) * log 2 ≀ log N := by
-      rw [← log_rpow zero_lt_two, rpow_nat_cast]
+      rw [← log_rpow zero_lt_two, rpow_natCast]
       exact log_le_log (by positivity) (mod_cast hN)
     refine' le_trans _ this
     rw [← div_le_iff']
@@ -467,7 +467,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
     _ < _ := by gcongr; exacts [(tsub_pos_of_lt hnβ‚‚).ne', bound hN]
     _ ≀ rothNumberNat ((2 * dValue N - 1) ^ n) := bound_aux hd.ne' hnβ‚‚.le
     _ ≀ rothNumberNat N := mod_cast rothNumberNat.mono this
-  rw [← rpow_nat_cast, div_rpow (rpow_nonneg hNβ‚€.le _) (exp_pos _).le, ← rpow_mul hNβ‚€.le,
+  rw [← rpow_natCast, div_rpow (rpow_nonneg hNβ‚€.le _) (exp_pos _).le, ← rpow_mul hNβ‚€.le,
     inv_mul_eq_div, cast_sub hnβ‚‚.le, cast_two, same_sub_div hn.ne', exp_one_rpow,
     div_div, rpow_sub hNβ‚€, rpow_one, div_div, div_eq_mul_inv]
   refine' mul_le_mul_of_nonneg_left _ (cast_nonneg _)
@@ -489,7 +489,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
 #align behrend.roth_lower_bound_explicit Behrend.roth_lower_bound_explicit
 
 theorem exp_four_lt : exp 4 < 64 := by
-  rw [show (64 : ℝ) = 2 ^ ((6 : β„•) : ℝ) by rw [rpow_nat_cast]; norm_num1,
+  rw [show (64 : ℝ) = 2 ^ ((6 : β„•) : ℝ) by rw [rpow_natCast]; norm_num1,
     ← lt_log_iff_exp_lt (rpow_pos_of_pos zero_lt_two _), log_rpow zero_lt_two, ← div_lt_iff']
   exact log_two_gt_d9.trans_le' (by norm_num1)
   norm_num
@@ -497,7 +497,7 @@ theorem exp_four_lt : exp 4 < 64 := by
 
 theorem four_zero_nine_six_lt_exp_sixteen : 4096 < exp 16 := by
   rw [← log_lt_iff_lt_exp (show (0 : ℝ) < 4096 by norm_num), show (4096 : ℝ) = 2 ^ 12 by norm_cast,
-    ← rpow_nat_cast, log_rpow zero_lt_two, cast_ofNat]
+    ← rpow_natCast, log_rpow zero_lt_two, cast_ofNat]
   have : 12 * (0.6931471808 : ℝ) < 16 := by norm_num
   linarith [log_two_lt_d9]
 #align behrend.four_zero_nine_six_lt_exp_sixteen Behrend.four_zero_nine_six_lt_exp_sixteen
feat: add notation for Real.sqrt (#12056)

This adds the notation √r for Real.sqrt r. The precedence is such that √x⁻¹ is parsed as √(x⁻¹); not because this is particularly desirable, but because it's the default and the choice doesn't really matter.

This is extracted from #7907, which adds a more general nth root typeclass. The idea is to perform all the boring substitutions downstream quickly, so that we can play around with custom elaborators with a much slower rate of code-rot. This PR also won't rot as quickly, as it does not forbid writing x.sqrt as that PR does.

While perhaps claiming √ for Real.sqrt is greedy; it:

  • Is far more common thatn NNReal.sqrt and Nat.sqrt
  • Is far more interesting to mathlib than sqrt on Float
  • Can be overloaded anyway, so this does not prevent downstream code using the notation on their own types.
  • Will be replaced by a more general typeclass in a future PR.

Zulip

Co-authored-by: Yury G. Kudryashov <urkud@urkud.name>

Diff
@@ -82,7 +82,7 @@ theorem card_box : (box n d).card = d ^ n := by simp [box]
 theorem box_zero : box (n + 1) 0 = βˆ… := by simp [box]
 #align behrend.box_zero Behrend.box_zero
 
-/-- The intersection of the sphere of radius `sqrt k` with the integer points in the positive
+/-- The intersection of the sphere of radius `√k` with the integer points in the positive
 quadrant. -/
 def sphere (n d k : β„•) : Finset (Fin n β†’ β„•) :=
   (box n d).filter fun x => βˆ‘ i, x i ^ 2 = k
@@ -100,7 +100,7 @@ theorem sphere_subset_box : sphere n d k βŠ† box n d :=
 #align behrend.sphere_subset_box Behrend.sphere_subset_box
 
 theorem norm_of_mem_sphere {x : Fin n β†’ β„•} (hx : x ∈ sphere n d k) :
-    β€–(WithLp.equiv 2 _).symm ((↑) ∘ x : Fin n β†’ ℝ)β€– = Real.sqrt k := by
+    β€–(WithLp.equiv 2 _).symm ((↑) ∘ x : Fin n β†’ ℝ)β€– = βˆšβ†‘k := by
   rw [EuclideanSpace.norm_eq]
   dsimp
   simp_rw [abs_cast, ← cast_pow, ← cast_sum, (mem_filter.1 hx).2]
@@ -108,7 +108,7 @@ theorem norm_of_mem_sphere {x : Fin n β†’ β„•} (hx : x ∈ sphere n d k) :
 
 theorem sphere_subset_preimage_metric_sphere : (sphere n d k : Set (Fin n β†’ β„•)) βŠ†
     (fun x : Fin n β†’ β„• => (WithLp.equiv 2 _).symm ((↑) ∘ x : Fin n β†’ ℝ)) ⁻¹'
-      Metric.sphere (0 : PiLp 2 fun _ : Fin n => ℝ) (Real.sqrt k) :=
+      Metric.sphere (0 : PiLp 2 fun _ : Fin n => ℝ) (βˆšβ†‘k) :=
   fun x hx => by rw [Set.mem_preimage, mem_sphere_zero_iff_norm, norm_of_mem_sphere hx]
 #align behrend.sphere_subset_preimage_metric_sphere Behrend.sphere_subset_preimage_metric_sphere
 
@@ -174,7 +174,7 @@ nonrec theorem addSalemSpencer_sphere : AddSalemSpencer (sphere n d k : Set (Fin
       map_add' := fun _ _ => funext fun _ => cast_add _ _ }
   refine' AddSalemSpencer.of_image (f.toAddFreimanHom (sphere n d k : Set (Fin n β†’ β„•)) 2) _ _
   Β· exact cast_injective.comp_left.injOn _
-  refine' (addSalemSpencer_sphere 0 <| Real.sqrt k).mono (Set.image_subset_iff.2 fun x => _)
+  refine' (addSalemSpencer_sphere 0 (βˆšβ†‘k)).mono (Set.image_subset_iff.2 fun x => _)
   rw [Set.mem_preimage, mem_sphere_zero_iff_norm]
   exact norm_of_mem_sphere
 #align behrend.add_salem_spencer_sphere Behrend.addSalemSpencer_sphere
@@ -286,7 +286,7 @@ open Real
 
 section NumericalBounds
 
-theorem log_two_mul_two_le_sqrt_log_eight : log 2 * 2 ≀ sqrt (log 8) := by
+theorem log_two_mul_two_le_sqrt_log_eight : log 2 * 2 ≀ √(log 8) := by
   have : (8 : ℝ) = 2 ^ ((3 : β„•) : ℝ) := by rw [rpow_nat_cast]; norm_num
   rw [this, log_rpow zero_lt_two (3 : β„•)]
   apply le_sqrt_of_sq_le
@@ -304,7 +304,7 @@ theorem two_div_one_sub_two_div_e_le_eight : 2 / (1 - 2 / exp 1) ≀ 8 := by
   rw [sub_pos, div_lt_one] <;> exact exp_one_gt_d9.trans' (by norm_num)
 #align behrend.two_div_one_sub_two_div_e_le_eight Behrend.two_div_one_sub_two_div_e_le_eight
 
-theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) ≀ sqrt (log ↑N) := by
+theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) ≀ √(log ↑N) := by
   have : (12 : β„•) * log 2 ≀ log N := by
     rw [← log_rpow zero_lt_two, rpow_nat_cast]
     exact log_le_log (by positivity) (mod_cast hN)
@@ -361,7 +361,7 @@ end NumericalBounds
 
 /-- The (almost) optimal value of `n` in `Behrend.bound_aux`. -/
 noncomputable def nValue (N : β„•) : β„• :=
-  ⌈sqrt (log N)βŒ‰β‚Š
+  ⌈√(log N)βŒ‰β‚Š
 #align behrend.n_value Behrend.nValue
 
 /-- The (almost) optimal value of `d` in `Behrend.bound_aux`. -/
@@ -390,7 +390,7 @@ theorem dValue_pos (hN₃ : 8 ≀ N) : 0 < dValue N := by
   have hNβ‚€ : 0 < (N : ℝ) := cast_pos.2 (succ_pos'.trans_le hN₃)
   rw [dValue, floor_pos, ← log_le_log_iff zero_lt_one, log_one, log_div _ two_ne_zero, log_rpow hNβ‚€,
     inv_mul_eq_div, sub_nonneg, le_div_iff]
-  Β· have : (nValue N : ℝ) ≀ 2 * sqrt (log N) := by
+  Β· have : (nValue N : ℝ) ≀ 2 * √(log N) := by
       apply (ceil_lt_add_one <| sqrt_nonneg _).le.trans
       rw [two_mul, add_le_add_iff_left]
       apply le_sqrt_of_sq_le
@@ -455,7 +455,7 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dV
 #align behrend.bound Behrend.bound
 
 theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
-    (N : ℝ) * exp (-4 * sqrt (log N)) < rothNumberNat N := by
+    (N : ℝ) * exp (-4 * √(log N)) < rothNumberNat N := by
   let n := nValue N
   have hn : 0 < (n : ℝ) := cast_pos.2 (nValue_pos <| hN.trans' <| by norm_num1)
   have hd : 0 < dValue N := dValue_pos (hN.trans' <| by norm_num1)
@@ -472,7 +472,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
     div_div, rpow_sub hNβ‚€, rpow_one, div_div, div_eq_mul_inv]
   refine' mul_le_mul_of_nonneg_left _ (cast_nonneg _)
   rw [mul_inv, mul_inv, ← exp_neg, ← rpow_neg (cast_nonneg _), neg_sub, ← div_eq_mul_inv]
-  have : exp (-4 * sqrt (log N)) = exp (-2 * sqrt (log N)) * exp (-2 * sqrt (log N)) := by
+  have : exp (-4 * √(log N)) = exp (-2 * √(log N)) * exp (-2 * √(log N)) := by
     rw [← exp_add, ← add_mul]
     norm_num
   rw [this]
@@ -503,7 +503,7 @@ theorem four_zero_nine_six_lt_exp_sixteen : 4096 < exp 16 := by
 #align behrend.four_zero_nine_six_lt_exp_sixteen Behrend.four_zero_nine_six_lt_exp_sixteen
 
 theorem lower_bound_le_one' (hN : 2 ≀ N) (hN' : N ≀ 4096) :
-    (N : ℝ) * exp (-4 * sqrt (log N)) ≀ 1 := by
+    (N : ℝ) * exp (-4 * √(log N)) ≀ 1 := by
   rw [← log_le_log_iff (mul_pos (cast_pos.2 (zero_lt_two.trans_le hN)) (exp_pos _)) zero_lt_one,
     log_one, log_mul (cast_pos.2 (zero_lt_two.trans_le hN)).ne' (exp_pos _).ne', log_exp, neg_mul, ←
     sub_eq_add_neg, sub_nonpos, ←
@@ -515,13 +515,13 @@ theorem lower_bound_le_one' (hN : 2 ≀ N) (hN' : N ≀ 4096) :
 #align behrend.lower_bound_le_one' Behrend.lower_bound_le_one'
 
 theorem lower_bound_le_one (hN : 1 ≀ N) (hN' : N ≀ 4096) :
-    (N : ℝ) * exp (-4 * sqrt (log N)) ≀ 1 := by
+    (N : ℝ) * exp (-4 * √(log N)) ≀ 1 := by
   obtain rfl | hN := hN.eq_or_lt
   Β· norm_num
   Β· exact lower_bound_le_one' hN hN'
 #align behrend.lower_bound_le_one Behrend.lower_bound_le_one
 
-theorem roth_lower_bound : (N : ℝ) * exp (-4 * sqrt (log N)) ≀ rothNumberNat N := by
+theorem roth_lower_bound : (N : ℝ) * exp (-4 * √(log N)) ≀ rothNumberNat N := by
   obtain rfl | hN := Nat.eq_zero_or_pos N
   Β· norm_num
   obtain h₁ | h₁ := le_or_lt 4096 N
change the order of operation in zsmulRec and nsmulRec (#11451)

We change the following field in the definition of an additive commutative monoid:

 nsmul_succ : βˆ€ (n : β„•) (x : G),
-  AddMonoid.nsmul (n + 1) x = x + AddMonoid.nsmul n x
+  AddMonoid.nsmul (n + 1) x = AddMonoid.nsmul n x + x

where the latter is more natural

We adjust the definitions of ^ in monoids, groups, etc. Originally there was a warning comment about why this natural order was preferred

use x * npowRec n x and not npowRec n x * x in the definition to make sure that definitional unfolding of npowRec is blocked, to avoid deep recursion issues.

but it seems to no longer apply.

Remarks on the PR :

  • pow_succ and pow_succ' have switched their meanings.
  • Most of the time, the proofs were adjusted by priming/unpriming one lemma, or exchanging left and right; a few proofs were more complicated to adjust.
  • In particular, [Mathlib/NumberTheory/RamificationInertia.lean] used Ideal.IsPrime.mul_mem_pow which is defined in [Mathlib/RingTheory/DedekindDomain/Ideal.lean]. Changing the order of operation forced me to add the symmetric lemma Ideal.IsPrime.mem_pow_mul.
  • the docstring for Cauchy condensation test in [Mathlib/Analysis/PSeries.lean] was mathematically incorrect, I added the mention that the function is antitone.
Diff
@@ -126,7 +126,7 @@ theorem map_zero (d : β„•) (a : Fin 0 β†’ β„•) : map d a = 0 := by simp [map]
 
 theorem map_succ (a : Fin (n + 1) β†’ β„•) :
     map d a = a 0 + (βˆ‘ x : Fin n, a x.succ * d ^ (x : β„•)) * d := by
-  simp [map, Fin.sum_univ_succ, _root_.pow_succ', ← mul_assoc, ← sum_mul]
+  simp [map, Fin.sum_univ_succ, _root_.pow_succ, ← mul_assoc, ← sum_mul]
 #align behrend.map_succ Behrend.map_succ
 
 theorem map_succ' (a : Fin (n + 1) β†’ β„•) : map d a = a 0 + map d (a ∘ Fin.succ) * d :=
chore: Rename mul-div cancellation lemmas (#11530)

Lemma names around cancellation of multiplication and division are a mess.

This PR renames a handful of them according to the following table (each big row contains the multiplicative statement, then the three rows contain the GroupWithZero lemma name, the Group lemma, the AddGroup lemma name).

| Statement | New name | Old name | |

Diff
@@ -243,7 +243,7 @@ theorem exists_large_sphere_aux (n d : β„•) : βˆƒ k ∈ range (n * (d - 1) ^ 2 +
   refine' exists_le_card_fiber_of_nsmul_le_card_of_maps_to (fun x hx => _) nonempty_range_succ _
   Β· rw [mem_range, Nat.lt_succ_iff]
     exact sum_sq_le_of_mem_box hx
-  Β· rw [card_range, _root_.nsmul_eq_mul, mul_div_assoc', cast_add_one, mul_div_cancel_left,
+  Β· rw [card_range, _root_.nsmul_eq_mul, mul_div_assoc', cast_add_one, mul_div_cancel_leftβ‚€,
       card_box]
     exact (cast_add_one_pos _).ne'
 #align behrend.exists_large_sphere_aux Behrend.exists_large_sphere_aux
chore: Rename monotonicity of / lemmas (#10634)

The new names and argument orders match the corresponding * lemmas, which I already took care of in a previous PR.

From LeanAPAP

Diff
@@ -256,7 +256,7 @@ theorem exists_large_sphere (n d : β„•) :
   Β· simp
   obtain rfl | hd := d.eq_zero_or_pos
   Β· simp
-  refine' (div_le_div_of_le_left _ _ _).trans hk
+  refine' (div_le_div_of_nonneg_left _ _ _).trans hk
   Β· exact cast_nonneg _
   Β· exact cast_add_one_pos _
   simp only [← le_sub_iff_add_le', cast_mul, ← mul_sub, cast_pow, cast_sub hd, sub_sq, one_pow,
@@ -327,13 +327,11 @@ theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) 
 
 theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈xβŒ‰β‚Š) / ⌈xβŒ‰β‚Š := by
   have h₁ := ceil_lt_add_one hx.le
-  have hβ‚‚ : 1 - x ≀ 2 - ⌈xβŒ‰β‚Š := by
-    rw [_root_.le_sub_iff_add_le]
-    apply (add_le_add_left h₁.le _).trans_eq
-    rw [← add_assoc, sub_add_cancel]
-    linarith
-  refine' lt_of_le_of_lt _ (div_lt_div_of_lt_left (exp_pos _) (cast_pos.2 <| ceil_pos.2 hx) h₁)
-  refine' le_trans _ (div_le_div_of_le (add_nonneg hx.le zero_le_one) (exp_le_exp.2 hβ‚‚))
+  have hβ‚‚ : 1 - x ≀ 2 - ⌈xβŒ‰β‚Š := by linarith
+  calc
+    _ ≀ exp (1 - x) / (x + 1) := ?_
+    _ ≀ exp (2 - ⌈xβŒ‰β‚Š) / (x + 1) := by gcongr
+    _ < _ := by gcongr
   rw [le_div_iff (add_pos hx zero_lt_one), ← le_div_iff' (exp_pos _), ← exp_sub, neg_mul,
     sub_neg_eq_add, two_mul, sub_add_add_cancel, add_comm _ x]
   exact le_trans (le_add_of_nonneg_right zero_le_one) (add_one_le_exp _)
@@ -429,7 +427,7 @@ set_option linter.uppercaseLean3 false in
 theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dValue N := by
   apply div_lt_floor _
   rw [← log_le_log_iff, log_rpow, mul_comm, ← div_eq_mul_inv]
-  Β· apply le_trans _ (div_le_div_of_le_left _ _ (ceil_lt_mul _).le)
+  Β· apply le_trans _ (div_le_div_of_nonneg_left _ _ (ceil_lt_mul _).le)
     rw [mul_comm, ← div_div, div_sqrt, le_div_iff]
     Β· set_option tactic.skipAssignedInstances false in norm_num; exact le_sqrt_log hN
     Β· norm_num1
chore: move Mathlib to v4.7.0-rc1 (#11162)

This is a very large PR, but it has been reviewed piecemeal already in PRs to the bump/v4.7.0 branch as we update to intermediate nightlies.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Kyle Miller <kmill31415@gmail.com> Co-authored-by: damiano <adomani@gmail.com>

Diff
@@ -264,7 +264,7 @@ theorem exists_large_sphere (n d : β„•) :
   apply one_le_mul_of_one_le_of_one_le
   Β· rwa [one_le_cast]
   rw [_root_.le_sub_iff_add_le]
-  norm_num
+  set_option tactic.skipAssignedInstances false in norm_num
   exact one_le_cast.2 hd
 #align behrend.exists_large_sphere Behrend.exists_large_sphere
 
@@ -431,7 +431,7 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dV
   rw [← log_le_log_iff, log_rpow, mul_comm, ← div_eq_mul_inv]
   Β· apply le_trans _ (div_le_div_of_le_left _ _ (ceil_lt_mul _).le)
     rw [mul_comm, ← div_div, div_sqrt, le_div_iff]
-    Β· norm_num; exact le_sqrt_log hN
+    Β· set_option tactic.skipAssignedInstances false in norm_num; exact le_sqrt_log hN
     Β· norm_num1
     Β· apply log_nonneg
       rw [one_le_cast]
chore: classify simp can do this porting notes (#10619)

Classify by adding issue number (#10618) to porting notes claiming anything semantically equivalent to simp can prove this or simp can simplify this.

Diff
@@ -120,7 +120,7 @@ def map (d : β„•) : (Fin n β†’ β„•) β†’+ β„• where
   map_add' a b := by simp_rw [Pi.add_apply, add_mul, sum_add_distrib]
 #align behrend.map Behrend.map
 
--- @[simp] -- Porting note: simp can prove this
+-- @[simp] -- Porting note (#10618): simp can prove this
 theorem map_zero (d : β„•) (a : Fin 0 β†’ β„•) : map d a = 0 := by simp [map]
 #align behrend.map_zero Behrend.map_zero
 
chore: remove stream-of-consciousness uses of have, replace and suffices (#10640)

No changes to tactic file, it's just boring fixes throughout the library.

This follows on from #6964.

Co-authored-by: sgouezel <sebastien.gouezel@univ-rennes1.fr> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -414,8 +414,8 @@ theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N := by
     Nat.pow_le_pow_left (Nat.sub_le _ _) _
   apply this.trans
   suffices ((2 * dValue N) ^ nValue N : ℝ) ≀ N from mod_cast this
-  suffices i : (2 * dValue N : ℝ) ≀ (N : ℝ) ^ (nValue N : ℝ)⁻¹
-  Β· rw [← rpow_nat_cast]
+  suffices i : (2 * dValue N : ℝ) ≀ (N : ℝ) ^ (nValue N : ℝ)⁻¹ by
+    rw [← rpow_nat_cast]
     apply (rpow_le_rpow (mul_nonneg zero_le_two (cast_nonneg _)) i (cast_nonneg _)).trans
     rw [← rpow_mul (cast_nonneg _), inv_mul_cancel, rpow_one]
     rw [cast_ne_zero]
chore: bump dependencies (#10315)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -241,7 +241,7 @@ that we then optimize by tweaking the parameters. The (almost) optimal parameter
 theorem exists_large_sphere_aux (n d : β„•) : βˆƒ k ∈ range (n * (d - 1) ^ 2 + 1),
     (↑(d ^ n) / ((n * (d - 1) ^ 2 :) + 1) : ℝ) ≀ (sphere n d k).card := by
   refine' exists_le_card_fiber_of_nsmul_le_card_of_maps_to (fun x hx => _) nonempty_range_succ _
-  Β· rw [mem_range, lt_succ_iff]
+  Β· rw [mem_range, Nat.lt_succ_iff]
     exact sum_sq_le_of_mem_box hx
   Β· rw [card_range, _root_.nsmul_eq_mul, mul_div_assoc', cast_add_one, mul_div_cancel_left,
       card_box]
refactor(Data/FunLike): use unbundled inheritance from FunLike (#8386)

The FunLike hierarchy is very big and gets scanned through each time we need a coercion (via the CoeFun instance). It looks like unbundled inheritance suits Lean 4 better here. The only class that still extends FunLike is EquivLike, since that has a custom coe_injective' field that is easier to implement. All other classes should take FunLike or EquivLike as a parameter.

Zulip thread

Important changes

Previously, morphism classes would be Type-valued and extend FunLike:

/-- `MyHomClass F A B` states that `F` is a type of `MyClass.op`-preserving morphisms.
You should extend this class when you extend `MyHom`. -/
class MyHomClass (F : Type*) (A B : outParam <| Type*) [MyClass A] [MyClass B]
  extends FunLike F A B :=
(map_op : βˆ€ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y))

After this PR, they should be Prop-valued and take FunLike as a parameter:

/-- `MyHomClass F A B` states that `F` is a type of `MyClass.op`-preserving morphisms.
You should extend this class when you extend `MyHom`. -/
class MyHomClass (F : Type*) (A B : outParam <| Type*) [MyClass A] [MyClass B]
  [FunLike F A B] : Prop :=
(map_op : βˆ€ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y))

(Note that A B stay marked as outParam even though they are not purely required to be so due to the FunLike parameter already filling them in. This is required to see through type synonyms, which is important in the category theory library. Also, I think keeping them as outParam is slightly faster.)

Similarly, MyEquivClass should take EquivLike as a parameter.

As a result, every mention of [MyHomClass F A B] should become [FunLike F A B] [MyHomClass F A B].

Remaining issues

Slower (failing) search

While overall this gives some great speedups, there are some cases that are noticeably slower. In particular, a failing application of a lemma such as map_mul is more expensive. This is due to suboptimal processing of arguments. For example:

variable [FunLike F M N] [Mul M] [Mul N] (f : F) (x : M) (y : M)

theorem map_mul [MulHomClass F M N] : f (x * y) = f x * f y

example [AddHomClass F A B] : f (x * y) = f x * f y := map_mul f _ _

Before this PR, applying map_mul f gives the goals [Mul ?M] [Mul ?N] [MulHomClass F ?M ?N]. Since M and N are out_params, [MulHomClass F ?M ?N] is synthesized first, supplies values for ?M and ?N and then the Mul M and Mul N instances can be found.

After this PR, the goals become [FunLike F ?M ?N] [Mul ?M] [Mul ?N] [MulHomClass F ?M ?N]. Now [FunLike F ?M ?N] is synthesized first, supplies values for ?M and ?N and then the Mul M and Mul N instances can be found, before trying MulHomClass F M N which fails. Since the Mul hierarchy is very big, this can be slow to fail, especially when there is no such Mul instance.

A long-term but harder to achieve solution would be to specify the order in which instance goals get solved. For example, we'd like to change the arguments to map_mul to look like [FunLike F M N] [Mul M] [Mul N] [highPriority <| MulHomClass F M N] because MulHomClass fails or succeeds much faster than the others.

As a consequence, the simpNF linter is much slower since by design it tries and fails to apply many map_ lemmas. The same issue occurs a few times in existing calls to simp [map_mul], where map_mul is tried "too soon" and fails. Thanks to the speedup of leanprover/lean4#2478 the impact is very limited, only in files that already were close to the timeout.

simp not firing sometimes

This affects map_smulβ‚›β‚— and related definitions. For simp lemmas Lean apparently uses a slightly different mechanism to find instances, so that rw can find every argument to map_smulβ‚›β‚— successfully but simp can't: leanprover/lean4#3701.

Missing instances due to unification failing

Especially in the category theory library, we might sometimes have a type A which is also accessible as a synonym (Bundled A hA).1. Instance synthesis doesn't always work if we have f : A β†’* B but x * y : (Bundled A hA).1 or vice versa. This seems to be mostly fixed by keeping A B as outParams in MulHomClass F A B. (Presumably because Lean will do a definitional check A =?= (Bundled A hA).1 instead of using the syntax in the discrimination tree.)

Workaround for issues

The timeouts can be worked around for now by specifying which map_mul we mean, either as map_mul f for some explicit f, or as e.g. MonoidHomClass.map_mul.

map_smulβ‚›β‚— not firing as simp lemma can be worked around by going back to the pre-FunLike situation and making LinearMap.map_smulβ‚›β‚— a simp lemma instead of the generic map_smulβ‚›β‚—. Writing simp [map_smulβ‚›β‚— _] also works.

Co-authored-by: Matthew Ballard <matt@mrb.email> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Scott Morrison <scott@tqft.net> Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>

Diff
@@ -182,7 +182,7 @@ nonrec theorem addSalemSpencer_sphere : AddSalemSpencer (sphere n d k : Set (Fin
 theorem addSalemSpencer_image_sphere :
     AddSalemSpencer ((sphere n d k).image (map (2 * d - 1)) : Set β„•) := by
   rw [coe_image]
-  refine' @AddSalemSpencer.image _ (Fin n β†’ β„•) β„• _ _ (sphere n d k) _ (map (2 * d - 1))
+  refine' AddSalemSpencer.image (Ξ± := Fin n β†’ β„•) (Ξ² := β„•) (s := sphere n d k) (map (2 * d - 1))
     (map_injOn.mono _) addSalemSpencer_sphere
   Β· exact x
   rw [Set.add_subset_iff]
chore: Rename rpow_nonneg_of_nonneg to rpow_nonneg (#9518)

This better matches other lemma names.

From LeanAPAP

Diff
@@ -421,7 +421,7 @@ theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N := by
     rw [cast_ne_zero]
     apply (nValue_pos hN).ne'
   rw [← le_div_iff']
-  Β· exact floor_le (div_nonneg (rpow_nonneg_of_nonneg (cast_nonneg _) _) zero_le_two)
+  Β· exact floor_le (div_nonneg (rpow_nonneg (cast_nonneg _) _) zero_le_two)
   apply zero_lt_two
 set_option linter.uppercaseLean3 false in
 #align behrend.le_N Behrend.le_N
@@ -469,7 +469,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
     _ < _ := by gcongr; exacts [(tsub_pos_of_lt hnβ‚‚).ne', bound hN]
     _ ≀ rothNumberNat ((2 * dValue N - 1) ^ n) := bound_aux hd.ne' hnβ‚‚.le
     _ ≀ rothNumberNat N := mod_cast rothNumberNat.mono this
-  rw [← rpow_nat_cast, div_rpow (rpow_nonneg_of_nonneg hNβ‚€.le _) (exp_pos _).le, ← rpow_mul hNβ‚€.le,
+  rw [← rpow_nat_cast, div_rpow (rpow_nonneg hNβ‚€.le _) (exp_pos _).le, ← rpow_mul hNβ‚€.le,
     inv_mul_eq_div, cast_sub hnβ‚‚.le, cast_two, same_sub_div hn.ne', exp_one_rpow,
     div_div, rpow_sub hNβ‚€, rpow_one, div_div, div_eq_mul_inv]
   refine' mul_le_mul_of_nonneg_left _ (cast_nonneg _)
@@ -479,7 +479,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
     norm_num
   rw [this]
   refine' mul_le_mul _ (exp_neg_two_mul_le <| Real.sqrt_pos.2 <| log_pos _).le (exp_pos _).le <|
-      rpow_nonneg_of_nonneg (cast_nonneg _) _
+      rpow_nonneg (cast_nonneg _) _
   Β· rw [← le_log_iff_exp_le (rpow_pos_of_pos hNβ‚€ _), log_rpow hNβ‚€, ← le_div_iff, mul_div_assoc,
       div_sqrt, neg_mul, neg_le_neg_iff, div_mul_eq_mul_div, div_le_iff hn]
     Β· exact mul_le_mul_of_nonneg_left (le_ceil _) zero_le_two
chore(*): replace $ with <| (#9319)

See Zulip thread for the discussion.

Diff
@@ -462,7 +462,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
   have hn : 0 < (n : ℝ) := cast_pos.2 (nValue_pos <| hN.trans' <| by norm_num1)
   have hd : 0 < dValue N := dValue_pos (hN.trans' <| by norm_num1)
   have hNβ‚€ : 0 < (N : ℝ) := cast_pos.2 (hN.trans' <| by norm_num1)
-  have hnβ‚‚ : 2 < n := three_le_nValue $ hN.trans' $ by norm_num1
+  have hnβ‚‚ : 2 < n := three_le_nValue <| hN.trans' <| by norm_num1
   have : (2 * dValue N - 1) ^ n ≀ N := le_N (hN.trans' <| by norm_num1)
   calc
     _ ≀ (N ^ (nValue N : ℝ)⁻¹ / rexp 1 : ℝ) ^ (n - 2) / n := ?_
feat: deprecate div_le_div_of_le_of_nonneg (#9399)

This was noticed in the discussion around #9393.

Diff
@@ -333,7 +333,7 @@ theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈x
     rw [← add_assoc, sub_add_cancel]
     linarith
   refine' lt_of_le_of_lt _ (div_lt_div_of_lt_left (exp_pos _) (cast_pos.2 <| ceil_pos.2 hx) h₁)
-  refine' le_trans _ (div_le_div_of_le_of_nonneg (exp_le_exp.2 hβ‚‚) <| add_nonneg hx.le zero_le_one)
+  refine' le_trans _ (div_le_div_of_le (add_nonneg hx.le zero_le_one) (exp_le_exp.2 hβ‚‚))
   rw [le_div_iff (add_pos hx zero_lt_one), ← le_div_iff' (exp_pos _), ← exp_sub, neg_mul,
     sub_neg_eq_add, two_mul, sub_add_add_cancel, add_comm _ x]
   exact le_trans (le_add_of_nonneg_right zero_le_one) (add_one_le_exp _)
feat: More rpow lemmas (#9108)

A bunch of easy lemmas about Real.pow and the golf of existing lemmas with them.

Also rename log_le_log to log_le_log_iff and log_le_log' to log_le_log. Those misnames caused several proofs to bother with side conditions they didn't need.

From LeanAPAP

Diff
@@ -305,15 +305,11 @@ theorem two_div_one_sub_two_div_e_le_eight : 2 / (1 - 2 / exp 1) ≀ 8 := by
 #align behrend.two_div_one_sub_two_div_e_le_eight Behrend.two_div_one_sub_two_div_e_le_eight
 
 theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) ≀ sqrt (log ↑N) := by
-  have : ((12 : β„•) : ℝ) * log 2 ≀ log N := by
-    rw [← log_rpow zero_lt_two, log_le_log, rpow_nat_cast]
-    Β· norm_num1
-      exact mod_cast hN
-    Β· exact rpow_pos_of_pos zero_lt_two _
-    rw [cast_pos]
-    exact hN.trans_lt' (by norm_num1)
-  refine' (mul_le_mul_of_nonneg_right ((log_le_log _ <| by norm_num1).2
-      two_div_one_sub_two_div_e_le_eight) <| by norm_num1).trans _
+  have : (12 : β„•) * log 2 ≀ log N := by
+    rw [← log_rpow zero_lt_two, rpow_nat_cast]
+    exact log_le_log (by positivity) (mod_cast hN)
+  refine (mul_le_mul_of_nonneg_right (log_le_log ?_ two_div_one_sub_two_div_e_le_eight) <| by
+    norm_num1).trans ?_
   Β· refine' div_pos zero_lt_two _
     rw [sub_pos, div_lt_one (exp_pos _)]
     exact exp_one_gt_d9.trans_le' (by norm_num1)
@@ -386,17 +382,15 @@ theorem three_le_nValue (hN : 64 ≀ N) : 3 ≀ nValue N := by
   have : (2 : ℝ) ^ ((6 : β„•) : ℝ) ≀ N := by
     rw [rpow_nat_cast]
     exact (cast_le.2 hN).trans' (by norm_num1)
-  apply lt_of_lt_of_le _ ((log_le_log (rpow_pos_of_pos zero_lt_two _) _).2 this)
+  apply lt_of_lt_of_le _ (log_le_log (rpow_pos_of_pos zero_lt_two _) this)
   rw [log_rpow zero_lt_two, ← div_lt_iff']
   Β· exact log_two_gt_d9.trans_le' (by norm_num1)
   Β· norm_num1
-  rw [cast_pos]
-  exact hN.trans_lt' (by norm_num1)
 #align behrend.three_le_n_value Behrend.three_le_nValue
 
 theorem dValue_pos (hN₃ : 8 ≀ N) : 0 < dValue N := by
   have hNβ‚€ : 0 < (N : ℝ) := cast_pos.2 (succ_pos'.trans_le hN₃)
-  rw [dValue, floor_pos, ← log_le_log zero_lt_one, log_one, log_div _ two_ne_zero, log_rpow hNβ‚€,
+  rw [dValue, floor_pos, ← log_le_log_iff zero_lt_one, log_one, log_div _ two_ne_zero, log_rpow hNβ‚€,
     inv_mul_eq_div, sub_nonneg, le_div_iff]
   Β· have : (nValue N : ℝ) ≀ 2 * sqrt (log N) := by
       apply (ceil_lt_add_one <| sqrt_nonneg _).le.trans
@@ -408,9 +402,7 @@ theorem dValue_pos (hN₃ : 8 ≀ N) : 0 < dValue N := by
     rw [← mul_assoc, ← le_div_iff (Real.sqrt_pos.2 <| log_pos <| one_lt_cast.2 _), div_sqrt]
     Β· apply log_two_mul_two_le_sqrt_log_eight.trans
       apply Real.sqrt_le_sqrt
-      rw [log_le_log _ hNβ‚€]
-      Β· exact mod_cast hN₃
-      Β· norm_num
+      exact log_le_log (by norm_num) (mod_cast hN₃)
     exact hN₃.trans_lt' (by norm_num)
   Β· exact cast_pos.2 (nValue_pos <| hN₃.trans' <| by norm_num)
   Β· exact (rpow_pos_of_pos hNβ‚€ _).ne'
@@ -436,7 +428,7 @@ set_option linter.uppercaseLean3 false in
 
 theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dValue N := by
   apply div_lt_floor _
-  rw [← log_le_log, log_rpow, mul_comm, ← div_eq_mul_inv]
+  rw [← log_le_log_iff, log_rpow, mul_comm, ← div_eq_mul_inv]
   Β· apply le_trans _ (div_le_div_of_le_left _ _ (ceil_lt_mul _).le)
     rw [mul_comm, ← div_div, div_sqrt, le_div_iff]
     Β· norm_num; exact le_sqrt_log hN
@@ -449,13 +441,9 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dV
       rw [one_lt_cast]
       exact hN.trans_lt' (by norm_num1)
     apply le_sqrt_of_sq_le
-    have : ((12 : β„•) : ℝ) * log 2 ≀ log N := by
-      rw [← log_rpow zero_lt_two, log_le_log, rpow_nat_cast]
-      Β· norm_num1
-        exact mod_cast hN
-      Β· exact rpow_pos_of_pos zero_lt_two _
-      rw [cast_pos]
-      exact hN.trans_lt' (by norm_num1)
+    have : (12 : β„•) * log 2 ≀ log N := by
+      rw [← log_rpow zero_lt_two, rpow_nat_cast]
+      exact log_le_log (by positivity) (mod_cast hN)
     refine' le_trans _ this
     rw [← div_le_iff']
     Β· exact log_two_gt_d9.le.trans' (by norm_num1)
@@ -465,9 +453,7 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dV
   Β· refine' div_pos zero_lt_two _
     rw [sub_pos, div_lt_one (exp_pos _)]
     exact lt_of_le_of_lt (by norm_num1) exp_one_gt_d9
-  apply rpow_pos_of_pos
-  rw [cast_pos]
-  exact hN.trans_lt' (by norm_num1)
+  positivity
 #align behrend.bound Behrend.bound
 
 theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
@@ -520,7 +506,7 @@ theorem four_zero_nine_six_lt_exp_sixteen : 4096 < exp 16 := by
 
 theorem lower_bound_le_one' (hN : 2 ≀ N) (hN' : N ≀ 4096) :
     (N : ℝ) * exp (-4 * sqrt (log N)) ≀ 1 := by
-  rw [← log_le_log (mul_pos (cast_pos.2 (zero_lt_two.trans_le hN)) (exp_pos _)) zero_lt_one,
+  rw [← log_le_log_iff (mul_pos (cast_pos.2 (zero_lt_two.trans_le hN)) (exp_pos _)) zero_lt_one,
     log_one, log_mul (cast_pos.2 (zero_lt_two.trans_le hN)).ne' (exp_pos _).ne', log_exp, neg_mul, ←
     sub_eq_add_neg, sub_nonpos, ←
     div_le_iff (Real.sqrt_pos.2 <| log_pos <| one_lt_cast.2 <| one_lt_two.trans_le hN), div_sqrt,
chore: Rename pow monotonicity lemmas (#9095)

The names for lemmas about monotonicity of (a ^ Β·) and (Β· ^ n) were a mess. This PR tidies up everything related by following the naming convention for (a * Β·) and (Β· * b). Namely, (a ^ Β·) is pow_right and (Β· ^ n) is pow_left in lemma names. All lemma renames follow the corresponding multiplication lemma names closely.

Renames

Algebra.GroupPower.Order

  • pow_mono β†’ pow_right_mono
  • pow_le_pow β†’ pow_le_pow_right
  • pow_le_pow_of_le_left β†’ pow_le_pow_left
  • pow_lt_pow_of_lt_left β†’ pow_lt_pow_left
  • strictMonoOn_pow β†’ pow_left_strictMonoOn
  • pow_strictMono_right β†’ pow_right_strictMono
  • pow_lt_pow β†’ pow_lt_pow_right
  • pow_lt_pow_iff β†’ pow_lt_pow_iff_right
  • pow_le_pow_iff β†’ pow_le_pow_iff_right
  • self_lt_pow β†’ lt_self_pow
  • strictAnti_pow β†’ pow_right_strictAnti
  • pow_lt_pow_iff_of_lt_one β†’ pow_lt_pow_iff_right_of_lt_one
  • pow_lt_pow_of_lt_one β†’ pow_lt_pow_right_of_lt_one
  • lt_of_pow_lt_pow β†’ lt_of_pow_lt_pow_left
  • le_of_pow_le_pow β†’ le_of_pow_le_pow_left
  • pow_lt_powβ‚€ β†’ pow_lt_pow_rightβ‚€

Algebra.GroupPower.CovariantClass

  • pow_le_pow_of_le_left' β†’ pow_le_pow_left'
  • nsmul_le_nsmul_of_le_right β†’ nsmul_le_nsmul_right
  • pow_lt_pow' β†’ pow_lt_pow_right'
  • nsmul_lt_nsmul β†’ nsmul_lt_nsmul_left
  • pow_strictMono_left β†’ pow_right_strictMono'
  • nsmul_strictMono_right β†’ nsmul_left_strictMono
  • StrictMono.pow_right' β†’ StrictMono.pow_const
  • StrictMono.nsmul_left β†’ StrictMono.const_nsmul
  • pow_strictMono_right' β†’ pow_left_strictMono
  • nsmul_strictMono_left β†’ nsmul_right_strictMono
  • Monotone.pow_right β†’ Monotone.pow_const
  • Monotone.nsmul_left β†’ Monotone.const_nsmul
  • lt_of_pow_lt_pow' β†’ lt_of_pow_lt_pow_left'
  • lt_of_nsmul_lt_nsmul β†’ lt_of_nsmul_lt_nsmul_right
  • pow_le_pow' β†’ pow_le_pow_right'
  • nsmul_le_nsmul β†’ nsmul_le_nsmul_left
  • pow_le_pow_of_le_one' β†’ pow_le_pow_right_of_le_one'
  • nsmul_le_nsmul_of_nonpos β†’ nsmul_le_nsmul_left_of_nonpos
  • le_of_pow_le_pow' β†’ le_of_pow_le_pow_left'
  • le_of_nsmul_le_nsmul' β†’ le_of_nsmul_le_nsmul_right'
  • pow_le_pow_iff' β†’ pow_le_pow_iff_right'
  • nsmul_le_nsmul_iff β†’ nsmul_le_nsmul_iff_left
  • pow_lt_pow_iff' β†’ pow_lt_pow_iff_right'
  • nsmul_lt_nsmul_iff β†’ nsmul_lt_nsmul_iff_left

Data.Nat.Pow

  • Nat.pow_lt_pow_of_lt_left β†’ Nat.pow_lt_pow_left
  • Nat.pow_le_iff_le_left β†’ Nat.pow_le_pow_iff_left
  • Nat.pow_lt_iff_lt_left β†’ Nat.pow_lt_pow_iff_left

Lemmas added

  • pow_le_pow_iff_left
  • pow_lt_pow_iff_left
  • pow_right_injective
  • pow_right_inj
  • Nat.pow_le_pow_left to have the correct name since Nat.pow_le_pow_of_le_left is in Std.
  • Nat.pow_le_pow_right to have the correct name since Nat.pow_le_pow_of_le_right is in Std.

Lemmas removed

  • self_le_pow was a duplicate of le_self_pow.
  • Nat.pow_lt_pow_of_lt_right is defeq to pow_lt_pow_right.
  • Nat.pow_right_strictMono is defeq to pow_right_strictMono.
  • Nat.pow_le_iff_le_right is defeq to pow_le_pow_iff_right.
  • Nat.pow_lt_iff_lt_right is defeq to pow_lt_pow_iff_right.

Other changes

  • A bunch of proofs have been golfed.
  • Some lemma assumptions have been turned from 0 < n or 1 ≀ n to n β‰  0.
  • A few Nat lemmas have been protected.
  • One docstring has been fixed.
Diff
@@ -196,7 +196,7 @@ theorem addSalemSpencer_image_sphere :
 theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : βˆ‘ i : Fin n, x i ^ 2 ≀ n * (d - 1) ^ 2 := by
   rw [mem_box] at hx
   have : βˆ€ i, x i ^ 2 ≀ (d - 1) ^ 2 := fun i =>
-    Nat.pow_le_pow_of_le_left (Nat.le_sub_one_of_lt (hx i)) _
+    Nat.pow_le_pow_left (Nat.le_sub_one_of_lt (hx i)) _
   exact (sum_le_card_nsmul univ _ _ fun i _ => this i).trans (by rw [card_fin, smul_eq_mul])
 #align behrend.sum_sq_le_of_mem_box Behrend.sum_sq_le_of_mem_box
 
@@ -371,22 +371,14 @@ noncomputable def nValue (N : β„•) : β„• :=
 #align behrend.n_value Behrend.nValue
 
 /-- The (almost) optimal value of `d` in `Behrend.bound_aux`. -/
-noncomputable def dValue (N : β„•) : β„• :=
-  ⌊(N : ℝ) ^ (1 / nValue N : ℝ) / 2βŒ‹β‚Š
+noncomputable def dValue (N : β„•) : β„• := ⌊(N : ℝ) ^ (nValue N : ℝ)⁻¹ / 2βŒ‹β‚Š
 #align behrend.d_value Behrend.dValue
 
 theorem nValue_pos (hN : 2 ≀ N) : 0 < nValue N :=
   ceil_pos.2 <| Real.sqrt_pos.2 <| log_pos <| one_lt_cast.2 <| hN
 #align behrend.n_value_pos Behrend.nValue_pos
 
-theorem two_le_nValue (hN : 3 ≀ N) : 2 ≀ nValue N := by
-  refine' succ_le_of_lt (lt_ceil.2 <| lt_sqrt_of_sq_lt _)
-  rw [cast_one, one_pow, lt_log_iff_exp_lt]
-  refine' lt_of_lt_of_le _ (cast_le.2 hN)
-  Β· exact exp_one_lt_d9.trans_le (by norm_num)
-  rw [cast_pos]
-  exact (zero_lt_succ _).trans_le hN
-#align behrend.two_le_n_value Behrend.two_le_nValue
+#noalign behrend.two_le_n_value
 
 theorem three_le_nValue (hN : 64 ≀ N) : 3 ≀ nValue N := by
   rw [nValue, ← lt_iff_add_one_le, lt_ceil, cast_two]
@@ -405,7 +397,7 @@ theorem three_le_nValue (hN : 64 ≀ N) : 3 ≀ nValue N := by
 theorem dValue_pos (hN₃ : 8 ≀ N) : 0 < dValue N := by
   have hNβ‚€ : 0 < (N : ℝ) := cast_pos.2 (succ_pos'.trans_le hN₃)
   rw [dValue, floor_pos, ← log_le_log zero_lt_one, log_one, log_div _ two_ne_zero, log_rpow hNβ‚€,
-    div_mul_eq_mul_div, one_mul, sub_nonneg, le_div_iff]
+    inv_mul_eq_div, sub_nonneg, le_div_iff]
   Β· have : (nValue N : ℝ) ≀ 2 * sqrt (log N) := by
       apply (ceil_lt_add_one <| sqrt_nonneg _).le.trans
       rw [two_mul, add_le_add_iff_left]
@@ -427,13 +419,13 @@ theorem dValue_pos (hN₃ : 8 ≀ N) : 0 < dValue N := by
 
 theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N := by
   have : (2 * dValue N - 1) ^ nValue N ≀ (2 * dValue N) ^ nValue N :=
-    Nat.pow_le_pow_of_le_left (Nat.sub_le _ _) _
+    Nat.pow_le_pow_left (Nat.sub_le _ _) _
   apply this.trans
   suffices ((2 * dValue N) ^ nValue N : ℝ) ≀ N from mod_cast this
-  suffices i : (2 * dValue N : ℝ) ≀ (N : ℝ) ^ (1 / nValue N : ℝ)
+  suffices i : (2 * dValue N : ℝ) ≀ (N : ℝ) ^ (nValue N : ℝ)⁻¹
   Β· rw [← rpow_nat_cast]
     apply (rpow_le_rpow (mul_nonneg zero_le_two (cast_nonneg _)) i (cast_nonneg _)).trans
-    rw [← rpow_mul (cast_nonneg _), one_div_mul_cancel, rpow_one]
+    rw [← rpow_mul (cast_nonneg _), inv_mul_cancel, rpow_one]
     rw [cast_ne_zero]
     apply (nValue_pos hN).ne'
   rw [← le_div_iff']
@@ -442,9 +434,9 @@ theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N := by
 set_option linter.uppercaseLean3 false in
 #align behrend.le_N Behrend.le_N
 
-theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (1 / nValue N : ℝ) / exp 1 < dValue N := by
+theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (nValue N : ℝ)⁻¹ / exp 1 < dValue N := by
   apply div_lt_floor _
-  rw [← log_le_log, log_rpow, mul_comm, ← div_eq_mul_one_div]
+  rw [← log_le_log, log_rpow, mul_comm, ← div_eq_mul_inv]
   Β· apply le_trans _ (div_le_div_of_le_left _ _ (ceil_lt_mul _).le)
     rw [mul_comm, ← div_div, div_sqrt, le_div_iff]
     Β· norm_num; exact le_sqrt_log hN
@@ -484,14 +476,15 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
   have hn : 0 < (n : ℝ) := cast_pos.2 (nValue_pos <| hN.trans' <| by norm_num1)
   have hd : 0 < dValue N := dValue_pos (hN.trans' <| by norm_num1)
   have hNβ‚€ : 0 < (N : ℝ) := cast_pos.2 (hN.trans' <| by norm_num1)
-  have hnβ‚‚ : 2 ≀ n := two_le_nValue (hN.trans' <| by norm_num1)
+  have hnβ‚‚ : 2 < n := three_le_nValue $ hN.trans' $ by norm_num1
   have : (2 * dValue N - 1) ^ n ≀ N := le_N (hN.trans' <| by norm_num1)
-  refine' ((bound_aux hd.ne' hnβ‚‚).trans <| cast_le.2 <| rothNumberNat.mono this).trans_lt' _
-  refine' (div_lt_div_of_lt hn <| pow_lt_pow_of_lt_left (bound hN) _ _).trans_le' _
-  Β· exact div_nonneg (rpow_nonneg_of_nonneg (cast_nonneg _) _) (exp_pos _).le
-  Β· exact tsub_pos_of_lt (three_le_nValue <| hN.trans' <| by norm_num1)
+  calc
+    _ ≀ (N ^ (nValue N : ℝ)⁻¹ / rexp 1 : ℝ) ^ (n - 2) / n := ?_
+    _ < _ := by gcongr; exacts [(tsub_pos_of_lt hnβ‚‚).ne', bound hN]
+    _ ≀ rothNumberNat ((2 * dValue N - 1) ^ n) := bound_aux hd.ne' hnβ‚‚.le
+    _ ≀ rothNumberNat N := mod_cast rothNumberNat.mono this
   rw [← rpow_nat_cast, div_rpow (rpow_nonneg_of_nonneg hNβ‚€.le _) (exp_pos _).le, ← rpow_mul hNβ‚€.le,
-    mul_comm (_ / _), mul_one_div, cast_sub hnβ‚‚, cast_two, same_sub_div hn.ne', exp_one_rpow,
+    inv_mul_eq_div, cast_sub hnβ‚‚.le, cast_two, same_sub_div hn.ne', exp_one_rpow,
     div_div, rpow_sub hNβ‚€, rpow_one, div_div, div_eq_mul_inv]
   refine' mul_le_mul_of_nonneg_left _ (cast_nonneg _)
   rw [mul_inv, mul_inv, ← exp_neg, ← rpow_neg (cast_nonneg _), neg_sub, ← div_eq_mul_inv]
feat: x ^ n / n ! ≀ exp x (#9099)

Also make private/delete the intermediate lemmas of the form x + 1 ≀ Real.exp x so that people use the more general final results instead.

Diff
@@ -340,8 +340,7 @@ theorem exp_neg_two_mul_le {x : ℝ} (hx : 0 < x) : exp (-2 * x) < exp (2 - ⌈x
   refine' le_trans _ (div_le_div_of_le_of_nonneg (exp_le_exp.2 hβ‚‚) <| add_nonneg hx.le zero_le_one)
   rw [le_div_iff (add_pos hx zero_lt_one), ← le_div_iff' (exp_pos _), ← exp_sub, neg_mul,
     sub_neg_eq_add, two_mul, sub_add_add_cancel, add_comm _ x]
-  refine' le_trans _ (add_one_le_exp_of_nonneg <| add_nonneg hx.le zero_le_one)
-  exact le_add_of_nonneg_right zero_le_one
+  exact le_trans (le_add_of_nonneg_right zero_le_one) (add_one_le_exp _)
 #align behrend.exp_neg_two_mul_le Behrend.exp_neg_two_mul_le
 
 theorem div_lt_floor {x : ℝ} (hx : 2 / (1 - 2 / exp 1) ≀ x) : x / exp 1 < (⌊x / 2βŒ‹β‚Š : ℝ) := by
chore: replace exact_mod_cast tactic with mod_cast elaborator where possible (#8404)

We still have the exact_mod_cast tactic, used in a few places, which somehow (?) works a little bit harder to prevent the expected type influencing the elaboration of the term. I would like to get to the bottom of this, and it will be easier once the only usages of exact_mod_cast are the ones that don't work using the term elaborator by itself.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -308,7 +308,7 @@ theorem le_sqrt_log (hN : 4096 ≀ N) : log (2 / (1 - 2 / exp 1)) * (69 / 50) 
   have : ((12 : β„•) : ℝ) * log 2 ≀ log N := by
     rw [← log_rpow zero_lt_two, log_le_log, rpow_nat_cast]
     Β· norm_num1
-      exact_mod_cast hN
+      exact mod_cast hN
     Β· exact rpow_pos_of_pos zero_lt_two _
     rw [cast_pos]
     exact hN.trans_lt' (by norm_num1)
@@ -418,7 +418,7 @@ theorem dValue_pos (hN₃ : 8 ≀ N) : 0 < dValue N := by
     Β· apply log_two_mul_two_le_sqrt_log_eight.trans
       apply Real.sqrt_le_sqrt
       rw [log_le_log _ hNβ‚€]
-      Β· exact_mod_cast hN₃
+      Β· exact mod_cast hN₃
       Β· norm_num
     exact hN₃.trans_lt' (by norm_num)
   Β· exact cast_pos.2 (nValue_pos <| hN₃.trans' <| by norm_num)
@@ -430,7 +430,7 @@ theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N := by
   have : (2 * dValue N - 1) ^ nValue N ≀ (2 * dValue N) ^ nValue N :=
     Nat.pow_le_pow_of_le_left (Nat.sub_le _ _) _
   apply this.trans
-  suffices ((2 * dValue N) ^ nValue N : ℝ) ≀ N by exact_mod_cast this
+  suffices ((2 * dValue N) ^ nValue N : ℝ) ≀ N from mod_cast this
   suffices i : (2 * dValue N : ℝ) ≀ (N : ℝ) ^ (1 / nValue N : ℝ)
   Β· rw [← rpow_nat_cast]
     apply (rpow_le_rpow (mul_nonneg zero_le_two (cast_nonneg _)) i (cast_nonneg _)).trans
@@ -461,7 +461,7 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (1 / nValue N : ℝ) / exp 1 < dVa
     have : ((12 : β„•) : ℝ) * log 2 ≀ log N := by
       rw [← log_rpow zero_lt_two, log_le_log, rpow_nat_cast]
       Β· norm_num1
-        exact_mod_cast hN
+        exact mod_cast hN
       Β· exact rpow_pos_of_pos zero_lt_two _
       rw [cast_pos]
       exact hN.trans_lt' (by norm_num1)
@@ -535,7 +535,7 @@ theorem lower_bound_le_one' (hN : 2 ≀ N) (hN' : N ≀ 4096) :
     sqrt_le_left zero_le_four, log_le_iff_le_exp (cast_pos.2 (zero_lt_two.trans_le hN))]
   norm_num1
   apply le_trans _ four_zero_nine_six_lt_exp_sixteen.le
-  exact_mod_cast hN'
+  exact mod_cast hN'
 #align behrend.lower_bound_le_one' Behrend.lower_bound_le_one'
 
 theorem lower_bound_le_one (hN : 1 ≀ N) (hN' : N ≀ 4096) :
chore: bump to v4.3.0-rc2 (#8366)

PR contents

This is the supremum of

along with some minor fixes from failures on nightly-testing as Mathlib master is merged into it.

Note that some PRs for changes that are already compatible with the current toolchain and will be necessary have already been split out: #8380.

I am hopeful that in future we will be able to progressively merge adaptation PRs into a bump/v4.X.0 branch, so we never end up with a "big merge" like this. However one of these adaptation PRs (#8056) predates my new scheme for combined CI, and it wasn't possible to keep that PR viable in the meantime.

Lean PRs involved in this bump

In particular this includes adjustments for the Lean PRs

leanprover/lean4#2778

We can get rid of all the

local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue [lean4#2220](https://github.com/leanprover/lean4/pull/2220)

macros across Mathlib (and in any projects that want to write natural number powers of reals).

leanprover/lean4#2722

Changes the default behaviour of simp to (config := {decide := false}). This makes simp (and consequentially norm_num) less powerful, but also more consistent, and less likely to blow up in long failures. This requires a variety of changes: changing some previously by simp or norm_num to decide or rfl, or adding (config := {decide := true}).

leanprover/lean4#2783

This changed the behaviour of simp so that simp [f] will only unfold "fully applied" occurrences of f. The old behaviour can be recovered with simp (config := { unfoldPartialApp := true }). We may in future add a syntax for this, e.g. simp [!f]; please provide feedback! In the meantime, we have made the following changes:

  • switching to using explicit lemmas that have the intended level of application
  • (config := { unfoldPartialApp := true }) in some places, to recover the old behaviour
  • Using @[eqns] to manually adjust the equation lemmas for a particular definition, recovering the old behaviour just for that definition. See #8371, where we do this for Function.comp and Function.flip.

This change in Lean may require further changes down the line (e.g. adding the !f syntax, and/or upstreaming the special treatment for Function.comp and Function.flip, and/or removing this special treatment). Please keep an open and skeptical mind about these changes!

Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Mauricio Collares <mauricio@collares.org>

Diff
@@ -213,7 +213,7 @@ theorem sum_lt : (βˆ‘ i : Fin n, d * (2 * d + 1) ^ (i : β„•)) < (2 * d + 1) ^ n
 theorem card_sphere_le_rothNumberNat (n d k : β„•) :
     (sphere n d k).card ≀ rothNumberNat ((2 * d - 1) ^ n) := by
   cases n
-  Β· dsimp; refine' (card_le_univ _).trans_eq _; simp
+  Β· dsimp; refine' (card_le_univ _).trans_eq _; rfl
   cases d
   Β· simp
   refine' addSalemSpencer_image_sphere.le_rothNumberNat _ _ (card_image_of_injOn _)
@@ -239,7 +239,7 @@ that we then optimize by tweaking the parameters. The (almost) optimal parameter
 
 
 theorem exists_large_sphere_aux (n d : β„•) : βˆƒ k ∈ range (n * (d - 1) ^ 2 + 1),
-    (↑(d ^ n) / (↑(n * (d - 1) ^ 2) + 1) : ℝ) ≀ (sphere n d k).card := by
+    (↑(d ^ n) / ((n * (d - 1) ^ 2 :) + 1) : ℝ) ≀ (sphere n d k).card := by
   refine' exists_le_card_fiber_of_nsmul_le_card_of_maps_to (fun x hx => _) nonempty_range_succ _
   Β· rw [mem_range, lt_succ_iff]
     exact sum_sq_le_of_mem_box hx
@@ -248,14 +248,14 @@ theorem exists_large_sphere_aux (n d : β„•) : βˆƒ k ∈ range (n * (d - 1) ^ 2 +
     exact (cast_add_one_pos _).ne'
 #align behrend.exists_large_sphere_aux Behrend.exists_large_sphere_aux
 
-theorem exists_large_sphere (n d : β„•) : βˆƒ k, (d ^ n / ↑(n * d ^ 2) : ℝ) ≀ (sphere n d k).card := by
+theorem exists_large_sphere (n d : β„•) :
+    βˆƒ k, ((d ^ n :) / (n * d ^ 2 :) : ℝ) ≀ (sphere n d k).card := by
   obtain ⟨k, -, hk⟩ := exists_large_sphere_aux n d
   refine' ⟨k, _⟩
   obtain rfl | hn := n.eq_zero_or_pos
   Β· simp
   obtain rfl | hd := d.eq_zero_or_pos
   Β· simp
-  rw [rpow_nat_cast, ← cast_pow]
   refine' (div_le_div_of_le_left _ _ _).trans hk
   Β· exact cast_nonneg _
   Β· exact cast_add_one_pos _
@@ -268,16 +268,16 @@ theorem exists_large_sphere (n d : β„•) : βˆƒ k, (d ^ n / ↑(n * d ^ 2) : ℝ)
   exact one_le_cast.2 hd
 #align behrend.exists_large_sphere Behrend.exists_large_sphere
 
-theorem bound_aux' (n d : β„•) : (d ^ n / ↑(n * d ^ 2) : ℝ) ≀ rothNumberNat ((2 * d - 1) ^ n) :=
+theorem bound_aux' (n d : β„•) : ((d ^ n :) / (n * d ^ 2 :) : ℝ) ≀ rothNumberNat ((2 * d - 1) ^ n) :=
   let ⟨_, h⟩ := exists_large_sphere n d
   h.trans <| cast_le.2 <| card_sphere_le_rothNumberNat _ _ _
 #align behrend.bound_aux' Behrend.bound_aux'
 
 theorem bound_aux (hd : d β‰  0) (hn : 2 ≀ n) :
-    (d ^ (n - 2) / n : ℝ) ≀ rothNumberNat ((2 * d - 1) ^ n) := by
+    (d ^ (n - 2 :) / n : ℝ) ≀ rothNumberNat ((2 * d - 1) ^ n) := by
   convert bound_aux' n d using 1
-  rw [cast_mul, cast_pow, mul_comm, ← div_div, ← cast_two, ← cast_sub hn, rpow_nat_cast,
-    rpow_nat_cast, pow_subβ‚€ _ (cast_ne_zero.2 hd) hn, ← div_eq_mul_inv]
+  rw [cast_mul, cast_pow, mul_comm, ← div_div, pow_subβ‚€ _ _ hn, ← div_eq_mul_inv, cast_pow]
+  rwa [cast_ne_zero]
 #align behrend.bound_aux Behrend.bound_aux
 
 open scoped Filter Topology
@@ -432,7 +432,8 @@ theorem le_N (hN : 2 ≀ N) : (2 * dValue N - 1) ^ nValue N ≀ N := by
   apply this.trans
   suffices ((2 * dValue N) ^ nValue N : ℝ) ≀ N by exact_mod_cast this
   suffices i : (2 * dValue N : ℝ) ≀ (N : ℝ) ^ (1 / nValue N : ℝ)
-  Β· apply (rpow_le_rpow (mul_nonneg zero_le_two (cast_nonneg _)) i (cast_nonneg _)).trans
+  Β· rw [← rpow_nat_cast]
+    apply (rpow_le_rpow (mul_nonneg zero_le_two (cast_nonneg _)) i (cast_nonneg _)).trans
     rw [← rpow_mul (cast_nonneg _), one_div_mul_cancel, rpow_one]
     rw [cast_ne_zero]
     apply (nValue_pos hN).ne'
@@ -487,7 +488,6 @@ theorem roth_lower_bound_explicit (hN : 4096 ≀ N) :
   have hnβ‚‚ : 2 ≀ n := two_le_nValue (hN.trans' <| by norm_num1)
   have : (2 * dValue N - 1) ^ n ≀ N := le_N (hN.trans' <| by norm_num1)
   refine' ((bound_aux hd.ne' hnβ‚‚).trans <| cast_le.2 <| rothNumberNat.mono this).trans_lt' _
-  conv_rhs => rw [← cast_two, ← cast_sub hnβ‚‚, rpow_nat_cast]
   refine' (div_lt_div_of_lt hn <| pow_lt_pow_of_lt_left (bound hN) _ _).trans_le' _
   Β· exact div_nonneg (rpow_nonneg_of_nonneg (cast_nonneg _) _) (exp_pos _).le
   Β· exact tsub_pos_of_lt (three_le_nValue <| hN.trans' <| by norm_num1)
@@ -521,7 +521,7 @@ theorem exp_four_lt : exp 4 < 64 := by
 
 theorem four_zero_nine_six_lt_exp_sixteen : 4096 < exp 16 := by
   rw [← log_lt_iff_lt_exp (show (0 : ℝ) < 4096 by norm_num), show (4096 : ℝ) = 2 ^ 12 by norm_cast,
-    log_rpow zero_lt_two]
+    ← rpow_nat_cast, log_rpow zero_lt_two, cast_ofNat]
   have : 12 * (0.6931471808 : ℝ) < 16 := by norm_num
   linarith [log_two_lt_d9]
 #align behrend.four_zero_nine_six_lt_exp_sixteen Behrend.four_zero_nine_six_lt_exp_sixteen
fix: attribute [simp] ... in -> attribute [local simp] ... in (#7678)

Mathlib.Logic.Unique contains the line attribute [simp] eq_iff_true_of_subsingleton in ...:

https://github.com/leanprover-community/mathlib4/blob/96a11c7aac574c00370c2b3dab483cb676405c5d/Mathlib/Logic/Unique.lean#L255-L256

Despite what the in part may imply, this adds the lemma to the simp set "globally", including for downstream files; it is likely that attribute [local simp] eq_iff_true_of_subsingleton in ... was meant instead (or maybe scoped simp, but I think "scoped" refers to the current namespace). Indeed, the relevant lemma is not marked with @[simp] for possible slowness: https://github.com/leanprover/std4/blob/846e9e1d6bb534774d1acd2dc430e70987da3c18/Std/Logic.lean#L749. Adding it to the simp set causes the example at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Regression.20in.20simp to slow down.

This PR changes this and fixes the relevant downstream simps. There was also one ocurrence of attribute [simp] FullSubcategory.comp_def FullSubcategory.id_def in in Mathlib.CategoryTheory.Monoidal.Subcategory but that was much easier to fix.

https://github.com/leanprover-community/mathlib4/blob/bc49eb9ba756a233370b4b68bcdedd60402f71ed/Mathlib/CategoryTheory/Monoidal/Subcategory.lean#L118-L119

Diff
@@ -153,7 +153,7 @@ theorem map_eq_iff {x₁ xβ‚‚ : Fin n.succ β†’ β„•} (hx₁ : βˆ€ i, x₁ i < d)
 theorem map_injOn : {x : Fin n β†’ β„• | βˆ€ i, x i < d}.InjOn (map d) := by
   intro x₁ hx₁ xβ‚‚ hxβ‚‚ h
   induction' n with n ih
-  Β· simp
+  Β· simp [eq_iff_true_of_subsingleton]
   rw [forall_const] at ih
   ext i
   have x := (map_eq_iff hx₁ hxβ‚‚).1 h
fix: patch for std4#195 (more succ/pred lemmas for Nat) (#6203)
Diff
@@ -164,7 +164,7 @@ theorem map_injOn : {x : Fin n β†’ β„• | βˆ€ i, x i < d}.InjOn (map d) := by
 
 theorem map_le_of_mem_box (hx : x ∈ box n d) :
     map (2 * d - 1) x ≀ βˆ‘ i : Fin n, (d - 1) * (2 * d - 1) ^ (i : β„•) :=
-  map_monotone (2 * d - 1) fun _ => Nat.le_pred_of_lt <| mem_box.1 hx _
+  map_monotone (2 * d - 1) fun _ => Nat.le_sub_one_of_lt <| mem_box.1 hx _
 #align behrend.map_le_of_mem_box Behrend.map_le_of_mem_box
 
 nonrec theorem addSalemSpencer_sphere : AddSalemSpencer (sphere n d k : Set (Fin n β†’ β„•)) := by
@@ -196,7 +196,7 @@ theorem addSalemSpencer_image_sphere :
 theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : βˆ‘ i : Fin n, x i ^ 2 ≀ n * (d - 1) ^ 2 := by
   rw [mem_box] at hx
   have : βˆ€ i, x i ^ 2 ≀ (d - 1) ^ 2 := fun i =>
-    Nat.pow_le_pow_of_le_left (Nat.le_pred_of_lt (hx i)) _
+    Nat.pow_le_pow_of_le_left (Nat.le_sub_one_of_lt (hx i)) _
   exact (sum_le_card_nsmul univ _ _ fun i _ => this i).trans (by rw [card_fin, smul_eq_mul])
 #align behrend.sum_sq_le_of_mem_box Behrend.sum_sq_le_of_mem_box
 
refactor: remove PiLp.equiv (#6501)

This removes the (PiLp.equiv 2 fun i => Ξ± i) abbreviation, replacing it with its implementation (WithLp.equiv 2 (βˆ€ i, Ξ± i)). The same thing is done for PiLp.linearEquiv.

Diff
@@ -100,14 +100,14 @@ theorem sphere_subset_box : sphere n d k βŠ† box n d :=
 #align behrend.sphere_subset_box Behrend.sphere_subset_box
 
 theorem norm_of_mem_sphere {x : Fin n β†’ β„•} (hx : x ∈ sphere n d k) :
-    β€–(PiLp.equiv 2 _).symm ((↑) ∘ x : Fin n β†’ ℝ)β€– = Real.sqrt k := by
+    β€–(WithLp.equiv 2 _).symm ((↑) ∘ x : Fin n β†’ ℝ)β€– = Real.sqrt k := by
   rw [EuclideanSpace.norm_eq]
   dsimp
   simp_rw [abs_cast, ← cast_pow, ← cast_sum, (mem_filter.1 hx).2]
 #align behrend.norm_of_mem_sphere Behrend.norm_of_mem_sphere
 
 theorem sphere_subset_preimage_metric_sphere : (sphere n d k : Set (Fin n β†’ β„•)) βŠ†
-    (fun x : Fin n β†’ β„• => (PiLp.equiv 2 _).symm ((↑) ∘ x : Fin n β†’ ℝ)) ⁻¹'
+    (fun x : Fin n β†’ β„• => (WithLp.equiv 2 _).symm ((↑) ∘ x : Fin n β†’ ℝ)) ⁻¹'
       Metric.sphere (0 : PiLp 2 fun _ : Fin n => ℝ) (Real.sqrt k) :=
   fun x hx => by rw [Set.mem_preimage, mem_sphere_zero_iff_norm, norm_of_mem_sphere hx]
 #align behrend.sphere_subset_preimage_metric_sphere Behrend.sphere_subset_preimage_metric_sphere
chore: drop MulZeroClass. in mul_zero/zero_mul (#6682)

Search&replace MulZeroClass.mul_zero -> mul_zero, MulZeroClass.zero_mul -> zero_mul.

These were introduced by Mathport, as the full name of mul_zero is actually MulZeroClass.mul_zero (it's exported with the short name).

Diff
@@ -116,7 +116,7 @@ theorem sphere_subset_preimage_metric_sphere : (sphere n d k : Set (Fin n β†’ 
 @[simps]
 def map (d : β„•) : (Fin n β†’ β„•) β†’+ β„• where
   toFun a := βˆ‘ i, a i * d ^ (i : β„•)
-  map_zero' := by simp_rw [Pi.zero_apply, MulZeroClass.zero_mul, sum_const_zero]
+  map_zero' := by simp_rw [Pi.zero_apply, zero_mul, sum_const_zero]
   map_add' a b := by simp_rw [Pi.add_apply, add_mul, sum_add_distrib]
 #align behrend.map Behrend.map
 
chore: remove unused simps (#6632)

Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -465,7 +465,6 @@ theorem bound (hN : 4096 ≀ N) : (N : ℝ) ^ (1 / nValue N : ℝ) / exp 1 < dVa
       rw [cast_pos]
       exact hN.trans_lt' (by norm_num1)
     refine' le_trans _ this
-    simp only [cast_one]
     rw [← div_le_iff']
     Β· exact log_two_gt_d9.le.trans' (by norm_num1)
     Β· norm_num1
chore: banish Type _ and Sort _ (#6499)

We remove all possible occurences of Type _ and Sort _ in favor of Type* and Sort*.

This has nice performance benefits.

Diff
@@ -53,7 +53,7 @@ open scoped BigOperators Pointwise
 
 namespace Behrend
 
-variable {Ξ± Ξ² : Type _} {n d k N : β„•} {x : Fin n β†’ β„•}
+variable {Ξ± Ξ² : Type*} {n d k N : β„•} {x : Fin n β†’ β„•}
 
 /-!
 ### Turning the sphere into a Salem-Spencer set
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -2,17 +2,14 @@
 Copyright (c) 2022 YaΓ«l Dillies, Bhavik Mehta. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: YaΓ«l Dillies, Bhavik Mehta
-
-! This file was ported from Lean 3 source module combinatorics.additive.behrend
-! leanprover-community/mathlib commit 4fa54b337f7d52805480306db1b1439c741848c8
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.Analysis.InnerProductSpace.PiL2
 import Mathlib.Combinatorics.Additive.SalemSpencer
 import Mathlib.Combinatorics.Pigeonhole
 import Mathlib.Data.Complex.ExponentialBounds
 
+#align_import combinatorics.additive.behrend from "leanprover-community/mathlib"@"4fa54b337f7d52805480306db1b1439c741848c8"
+
 /-!
 # Behrend's bound on Roth numbers
 
chore: bump to nightly-2023-07-01 (#5409)

Open in Gitpod

Co-authored-by: Komyyy <pol_tta@outlook.jp> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@anu.edu.au> Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Co-authored-by: Mario Carneiro <di.gama@gmail.com>

Diff
@@ -266,7 +266,7 @@ theorem exists_large_sphere (n d : β„•) : βˆƒ k, (d ^ n / ↑(n * d ^ 2) : ℝ)
     cast_one, mul_one, sub_add, sub_sub_self]
   apply one_le_mul_of_one_le_of_one_le
   Β· rwa [one_le_cast]
-  rw [← one_eq_succ_zero, _root_.le_sub_iff_add_le]
+  rw [_root_.le_sub_iff_add_le]
   norm_num
   exact one_le_cast.2 hd
 #align behrend.exists_large_sphere Behrend.exists_large_sphere
fix: βˆ‘' precedence (#5615)
  • Also remove most superfluous parentheses around big operators (βˆ‘, ∏ and variants).
  • roughly the used regex: ([^a-zA-ZΞ±-ωΑ-Ξ©'𝓝ℳ₀𝕂ₛ)]) \(([βˆ‘βˆ][^()βˆ‘βˆ]*,[^()βˆ‘βˆ:]*)\) ([βŠ‚βŠ†=<≀]) replaced by $1 $2 $3
Diff
@@ -88,7 +88,7 @@ theorem box_zero : box (n + 1) 0 = βˆ… := by simp [box]
 /-- The intersection of the sphere of radius `sqrt k` with the integer points in the positive
 quadrant. -/
 def sphere (n d k : β„•) : Finset (Fin n β†’ β„•) :=
-  (box n d).filter fun x => (βˆ‘ i, x i ^ 2) = k
+  (box n d).filter fun x => βˆ‘ i, x i ^ 2 = k
 #align behrend.sphere Behrend.sphere
 
 theorem sphere_zero_subset : sphere n d 0 βŠ† 0 := fun x => by simp [sphere, Function.funext_iff]
@@ -196,7 +196,7 @@ theorem addSalemSpencer_image_sphere :
   exact (add_add_add_comm _ _ 1 1).trans_le (_root_.add_le_add hai hbi)
 #align behrend.add_salem_spencer_image_sphere Behrend.addSalemSpencer_image_sphere
 
-theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : (βˆ‘ i : Fin n, x i ^ 2) ≀ n * (d - 1) ^ 2 := by
+theorem sum_sq_le_of_mem_box (hx : x ∈ box n d) : βˆ‘ i : Fin n, x i ^ 2 ≀ n * (d - 1) ^ 2 := by
   rw [mem_box] at hx
   have : βˆ€ i, x i ^ 2 ≀ (d - 1) ^ 2 := fun i =>
     Nat.pow_le_pow_of_le_left (Nat.le_pred_of_lt (hx i)) _
feat: port Combinatorics.Additive.Behrend (#4730)

Dependencies 12 + 961

962 files ported (98.8%)
422728 lines ported (98.7%)
Show graph

The unported dependencies are

The following 1 dependencies have changed in mathlib3 since they were ported, which may complicate porting this file