diff --git a/Gromov/BoundedDoubling.lean b/Gromov/BoundedDoubling.lean index 61fd0b4..ac55b91 100644 --- a/Gromov/BoundedDoubling.lean +++ b/Gromov/BoundedDoubling.lean @@ -11,11 +11,6 @@ public import Gromov.Lemma326 public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false open scoped Finset open scoped Pointwise @@ -39,29 +34,62 @@ variable {ι : Type*} [Fintype ι] [DecidableEq ι] [Nonempty ι] variable {b : Module.Basis ι ℝ V} -set_option maxHeartbeats 2500000 in -lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodule ℝ LipschitzH, U ≤ V ∧ dim V ≤ 2 * dim U ∧ ∀ f ∈ U, Q_R (16 * (R_2 data)) f f ≤ Real.exp (2 * (a data.d)) * Q_R ((R_2 data)) f f := by +omit hGS v_wrapper_inst in +private lemma diagonal_form_eval {E I : Type*} [AddCommGroup E] [Module ℝ E] + [Fintype I] [DecidableEq I] (b : Module.Basis I ℝ E) + (B : LinearMap.BilinForm ℝ E) (hB : B.IsOrthoᵢ b) (x : E) : + B x x = ∑ i, (b.repr x i)^2 * B (b i) (b i) := by + calc + B x x = B (∑ i, b.repr x i • b i) (∑ j, b.repr x j • b j) := by + rw [b.sum_repr] + _ = ∑ i, ∑ j, b.repr x i * b.repr x j * B (b j) (b i) := by + simp only [map_sum, LinearMap.sum_apply, map_smul, LinearMap.smul_apply, smul_eq_mul] + apply Finset.sum_congr rfl + intro i hi + rw [Finset.mul_sum] + apply Finset.sum_congr rfl + intro j hj + ring + _ = ∑ i, (b.repr x i)^2 * B (b i) (b i) := by + apply Finset.sum_congr rfl + intro i hi + rw [Finset.sum_eq_single i] + · ring + · intro j hj hji + rw [hB hji] + simp + · simp + +omit hGS v_wrapper_inst in +private lemma diagonal_forms_le {E I : Type*} [AddCommGroup E] [Module ℝ E] + [Fintype I] [DecidableEq I] (b : Module.Basis I ℝ E) + (B D : LinearMap.BilinForm ℝ E) (hB : B.IsOrthoᵢ b) (hD : D.IsOrthoᵢ b) + (x : E) (k : ℝ) + (hk : ∀ i ∈ (b.repr x).support, D (b i) (b i) ≤ k * B (b i) (b i)) : + D x x ≤ k * B x x := by + rw [diagonal_form_eval b B hB, diagonal_form_eval b D hD, Finset.mul_sum] + apply Finset.sum_le_sum + intro i hi + by_cases hx : i ∈ (b.repr x).support + · nlinarith [mul_le_mul_of_nonneg_left (hk i hx) (sq_nonneg (b.repr x i))] + · have hz : b.repr x i = 0 := Finsupp.notMem_support_iff.mp hx + simp [hz] + +private lemma doubleScale_basis (R : ℕ) (h_R : R'_ V ≤ (R : ℝ)) : + ∃ v_orthonormal : Module.Basis (Fin (Module.finrank ℝ V)) ℝ V, + let _q_r_16_m := (Q_R_lin V (16 * R)).toMatrix₂ v_orthonormal v_orthonormal + let q_r_16_m_hermitian := Q_R_lin_hermetian v_orthonormal (16 * R) + let q_r_16_eigen := q_r_16_m_hermitian.eigenvectorBasis.toBasis + let eigen_basis_V := (WithLp.linearEquiv 2 ℝ (Fin (Module.finrank ℝ V) → ℝ)).trans v_orthonormal.equivFun.symm + let remapped_ortho := Module.Basis.map q_r_16_eigen eigen_basis_V + (Q_R_lin V R).IsOrthoᵢ remapped_ortho ∧ + (∀ i, Q_R_lin V R (remapped_ortho i) (remapped_ortho i) = 1) ∧ + (Q_R_lin V R).toMatrix₂ v_orthonormal v_orthonormal = 1 ∧ + (Q_R_lin_plain V (16 * R)).IsOrthoᵢ remapped_ortho := by classical - - let R := 16 ^ ((GoodScales data).i_2) - have h_R: R'_ V ≤ ↑R := R'_le_R_2 data - - have q_r_base_pos_def := (Q_R_matrix_pos_def_i₀ b (16 ^ ((GoodScales data).i_2)) (by - simp [i₀] - rw [pow_le_pow_iff_right₀] - . have foo := (GoodScales data).i_2_ge - simp [i₀] at foo - exact foo - . simp - )) - - have det_succ_pos : 0 < (Q_R_matrix b (16 ^ ((GoodScales data).i_2 + 1))).det := - (Q_R_matrix_pos_def b (16 ^ ((GoodScales data).i_2 + 1)) - (le_trans h_R (by simp only [R]; push_cast; exact pow_le_pow_right₀ (by norm_num) (Nat.le_succ _)))).det_pos - -- Full (definite) inner product core, registered as a local instance so that -- `toNormedAddCommGroup` / `ofCore` pick it up by inference. - letI Q_R_inner_core: InnerProductSpace.Core ℝ V := { + let Q_R_inner_core: InnerProductSpace.Core ℝ V := { inner := fun u v => Q_R R u.val v.val conj_inner_symm := by simp [Q_R] @@ -93,11 +121,11 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul -- Install the definite Q_R-derived NORM (not just a seminorm) *before* `ofCore`, so the -- ambient LipschitzH norm on `↥V` is shadowed and `Q_R_inner` is over this `NormedAddCommGroup`. - letI Q_R_norm : NormedAddCommGroup ↥V := InnerProductSpace.Core.toNormedAddCommGroup (𝕜 := ℝ) + let Q_R_norm : NormedAddCommGroup ↥V := InnerProductSpace.Core.toNormedAddCommGroup (𝕜 := ℝ) -- Also expose the seminorm projection as a *direct* local instance, so it shadows the -- ambient `V.seminormedAddCommGroup` (a bare `NormedAddCommGroup` letI does not). - letI Q_R_seminorm : SeminormedAddCommGroup ↥V := Q_R_norm.toSeminormedAddCommGroup - letI Q_R_inner : InnerProductSpace ℝ ↥V := + let Q_R_seminorm : SeminormedAddCommGroup ↥V := Q_R_norm.toSeminormedAddCommGroup + let Q_R_inner : InnerProductSpace ℝ ↥V := InnerProductSpace.ofCore (inferInstance : PreInnerProductSpace.Core ℝ ↥V) have norm_eq_q_r : ∀ x : ↥V, ‖x‖ = Real.sqrt (Q_R R x x) := fun _ => rfl @@ -163,7 +191,7 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul apply v_orthogonal_orig_eval _ _ hij )] - ring + ring_nf simp [norm_eq_q_r] conv => lhs @@ -190,9 +218,9 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul intro i simp [remapped_ortho] simp [eigen_basis_V,] - ring + ring_nf field_simp - simp only [eigen_basis_V, q_r_16_eigen] + simp only [q_r_16_eigen] simp simp_rw [Finset.mul_sum] simp [v_orthonormal] @@ -218,7 +246,7 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul apply v_orthogonal_orig_eval _ _ hij )] - ring + ring_nf simp [norm_eq_q_r] conv => lhs @@ -288,36 +316,6 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul let Q_R_16_new_ortho := (Q_R_lin V (16 *R)).toMatrix₂ remapped_ortho remapped_ortho have Q_R_16_new_ortho_hermitian: Q_R_16_new_ortho.IsHermitian := Q_R_lin_hermetian remapped_ortho (16 *R) - have det_Q_R_one: Q_R_ortho.det = 1 := by - simp [Q_R_ortho_eq_1] - - have det_Q_R_16_ge: 1 ≤ Q_R_16_new_ortho.det := by - rw [← det_Q_R_one] - apply matrix_det_montone - . - simp [Q_R_ortho] - apply Matrix.PosDef.of_dotProduct_mulVec_pos (?_) - . - intro x hx - simp [Q_R_matrix] - conv => - rhs - lhs - equals (star x) => simp - rw [star_dotProduct_toMatrix₂_mulVec] - apply Q_R_pos_on_R' - . rw [LinearEquiv.map_ne_zero_iff] - exact hx - . exact h_R - . apply Q_R_ortho_m_hermitian - . - simp [Q_R_16_new_ortho, Q_R_ortho] - rw [← map_sub] - rw [← LinearMap.isPosSemidef_iff_posSemidef_toMatrix] - apply Q_R_lin_sub_pos_semi_def - norm_cast - grind - have q_r_16_remapped_orthogonal : (Q_R_lin_plain V (16 * R)).IsOrthoᵢ remapped_ortho := by simp [remapped_ortho] rw [LinearMap.isOrthoᵢ_def] @@ -357,7 +355,7 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul have tobasis_lp: ∀ x, (q_r_16_m_hermitian.eigenvectorBasis.toBasis x).ofLp = (q_r_16_m_hermitian.eigenvectorBasis x).ofLp := by simp - simp [tobasis_lp] + simp rw [Matrix.IsHermitian.mulVec_eigenvectorBasis q_r_16_m_hermitian] simp right @@ -371,6 +369,51 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul apply OrthonormalBasis.inner_eq_zero exact hxy.symm + exact ⟨v_orthonormal, v_orthonormal_isortho, q_r_lin_remapped_one, + Q_R_v_orthonormal_eq_1, q_r_16_remapped_orthogonal⟩ + +lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodule ℝ LipschitzH, U ≤ V ∧ dim V ≤ 2 * dim U ∧ ∀ f ∈ U, Q_R (16 * (R_2 data)) f f ≤ Real.exp (2 * (a data.d)) * Q_R ((R_2 data)) f f := by + classical + + let R := 16 ^ ((GoodScales data).i_2) + have h_R: R'_ V ≤ ↑R := R'_le_R_2 data + + have q_r_base_pos_def := (Q_R_matrix_pos_def_i₀ b (16 ^ ((GoodScales data).i_2)) (by + simp [i₀] + rw [pow_le_pow_iff_right₀] + . have foo := (GoodScales data).i_2_ge + simp [i₀] at foo + exact foo + . simp + )) + + have det_succ_pos : 0 < (Q_R_matrix b (16 ^ ((GoodScales data).i_2 + 1))).det := + (Q_R_matrix_pos_def b (16 ^ ((GoodScales data).i_2 + 1)) + (le_trans h_R (by simp only [R]; push_cast; exact pow_le_pow_right₀ (by norm_num) (Nat.le_succ _)))).det_pos + + obtain ⟨v_orthonormal, hb⟩ := doubleScale_basis R h_R + let q_r_16_m := (Q_R_lin V (16 * R)).toMatrix₂ v_orthonormal v_orthonormal + have q_r_16_m_hermitian : q_r_16_m.IsHermitian := Q_R_lin_hermetian v_orthonormal (16 * R) + let q_r_16_eigen := q_r_16_m_hermitian.eigenvectorBasis.toBasis + let eigen_basis_V := (WithLp.linearEquiv 2 ℝ (Fin (Module.finrank ℝ V) → ℝ)).trans v_orthonormal.equivFun.symm + let remapped_ortho := Module.Basis.map q_r_16_eigen eigen_basis_V + change (Q_R_lin V R).IsOrthoᵢ remapped_ortho ∧ + (∀ i, Q_R_lin V R (remapped_ortho i) (remapped_ortho i) = 1) ∧ + (Q_R_lin V R).toMatrix₂ v_orthonormal v_orthonormal = 1 ∧ + (Q_R_lin_plain V (16 * R)).IsOrthoᵢ remapped_ortho at hb + obtain ⟨v_orthonormal_isortho, q_r_lin_remapped_one, + Q_R_v_orthonormal_eq_1, q_r_16_remapped_orthogonal⟩ := hb + let q_r_v_orthonormal := (Q_R_lin V R).toMatrix₂ v_orthonormal v_orthonormal + let Q_R_ortho := (Q_R_lin V R).toMatrix₂ remapped_ortho remapped_ortho + have det_Q_R_one : Q_R_ortho.det = 1 := by + have hmat : Q_R_ortho = 1 := by + ext i j + by_cases hij : i = j + · subst j + simpa [Q_R_ortho] using q_r_lin_remapped_one i + · simpa [Q_R_ortho, Matrix.one_apply, hij] using v_orthonormal_isortho hij + simp [hmat] + have new_growth := data.h_growth have nonempty_fin: Nonempty (Fin (Module.finrank ℝ ↥V)) := by use 0 @@ -394,124 +437,18 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul . simp apply Finset.card_le_card apply Finset.pow_subset_pow_right - . simp [one_mem] + . simp [Generates.one_mem] . grind -- - have inner_x_self (x: V) (k: ℝ) (hk: ∀ i ∈ (remapped_ortho.repr x).support, (Q_R_lin_plain V (16 * R) (remapped_ortho i) (remapped_ortho i)) ≤ k * (Q_R_lin_plain V (R) (remapped_ortho i) (remapped_ortho i))) : Q_R_lin_plain V (16 * R) x x ≤ k * Q_R_lin_plain V (R) x x := by - rw [← Module.Basis.sum_repr remapped_ortho (u := x)] - have inner_sum_eq: ∀ i, ∑ i_1, inner ℝ ((remapped_ortho.repr x) i_1 • remapped_ortho i_1) ((remapped_ortho.repr x) i • remapped_ortho i) = inner ℝ ((remapped_ortho.repr x) i • remapped_ortho i) ((remapped_ortho.repr x) i • remapped_ortho i) := by - intro i - rw [Finset.sum_eq_single i] - . intro k hk k_neq - rw [inner_eq_q_r] - simp [map_smul] - rw [LinearMap.isOrthoᵢ_def] at v_orthonormal_isortho - specialize v_orthonormal_isortho k i k_neq - simp [Q_R_lin] at v_orthonormal_isortho - simp [Q_R] - simp [Q_R] at v_orthonormal_isortho - simp_rw [mul_assoc] - rw [← Finset.mul_sum] - simp_rw [mul_comm ((remapped_ortho.repr x) i)] - simp_rw [← mul_assoc] - rw [← Finset.sum_mul] - simp [v_orthonormal_isortho] - . - intro hi - simp at hi - - have q_r_16_sum_eq: ∀ i, ∑ i_1, Q_R_lin_plain V (16 * R) ((remapped_ortho.repr x) i_1 • remapped_ortho i_1) ((remapped_ortho.repr x) i • remapped_ortho i) = Q_R_lin_plain V (16 * R) ((remapped_ortho.repr x) i • remapped_ortho i) ((remapped_ortho.repr x) i • remapped_ortho i) := by - intro i - rw [Finset.sum_eq_single i] - . intro k hk k_neq - simp [map_smul] - rw [LinearMap.isOrthoᵢ_def] at q_r_16_remapped_orthogonal - specialize q_r_16_remapped_orthogonal k i k_neq - simp [Q_R_lin_plain] at q_r_16_remapped_orthogonal - simp [Q_R_lin_plain, Q_R] - simp [Q_R] at q_r_16_remapped_orthogonal - right - right - simp [q_r_16_remapped_orthogonal] - . - intro hi - simp at hi - - rw [map_sum] - simp_rw [map_sum] - simp [Finset.sum_apply] - conv => - rhs - rhs - arg 2 - intro i - rw [Finset.sum_eq_single i (by - intro k hk k_neq - simp [map_smul] - rw [LinearMap.isOrthoᵢ_def] at v_orthonormal_isortho - right - specialize v_orthonormal_isortho k i k_neq - simp [Q_R_lin] at v_orthonormal_isortho - simp [Q_R_lin_plain, Q_R] - simp [Q_R] at v_orthonormal_isortho - simp [v_orthonormal_isortho] - ) (by - intro hi - simp at hi - )] - conv => - rhs - rw [← Module.Basis.sum_repr remapped_ortho (u := x)] - - simp_rw [map_sum] - simp - simp_rw [Finset.mul_sum] - conv => - lhs - arg 2 - intro i - rw [Finset.sum_eq_single i (by - intro k hk k_neq - simp [map_smul] - rw [LinearMap.isOrthoᵢ_def] at q_r_16_remapped_orthogonal - specialize q_r_16_remapped_orthogonal k i k_neq - simp [Q_R_lin_plain] at q_r_16_remapped_orthogonal - simp [Q_R_lin_plain, Q_R] - simp [Q_R] at q_r_16_remapped_orthogonal - right - right - simp [q_r_16_remapped_orthogonal] - ) (by - intro hi - simp at hi - )] - - apply Finset.sum_le_sum - intro i hi - by_cases i_mem_inter: i ∈ (remapped_ortho.repr x).support - . - conv => - lhs - equals ((Q_R_lin_plain V (16 * ↑R)) (remapped_ortho i)) (remapped_ortho i) * (remapped_ortho.repr x) i * (remapped_ortho.repr x) i => - ring - - conv => - rhs - equals k * ((Q_R_lin_plain V ↑R) (remapped_ortho i)) (remapped_ortho i) * (remapped_ortho.repr x) i * (remapped_ortho.repr x) i => - ring - - rw [mul_assoc] - nth_rw 2 [mul_assoc] - specialize hk i i_mem_inter - grw [hk] - . ring - simp - . rw [← pow_two] - positivity - . - simp at i_mem_inter - simp [i_mem_inter] + have inner_x_self (x : V) (k : ℝ) + (hk : ∀ i ∈ (remapped_ortho.repr x).support, + Q_R_lin_plain V (16 * R) (remapped_ortho i) (remapped_ortho i) ≤ + k * Q_R_lin_plain V R (remapped_ortho i) (remapped_ortho i)) : + Q_R_lin_plain V (16 * R) x x ≤ k * Q_R_lin_plain V R x x := by + exact diagonal_forms_le remapped_ortho + (Q_R_lin_plain V R) (Q_R_lin_plain V (16 * R)) + v_orthonormal_isortho q_r_16_remapped_orthogonal x k hk grw [← log_second] at a_gt rw [Real.log_mul] at a_gt . @@ -564,7 +501,7 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul simp rw [le_sub_iff_add_le'] grw [dim_small] - ring + ring_nf simp . have all_le: ∀ f ∈ small_submodule, Q_R_lin V (16 * ↑(R_2 data)) f f ≤ Real.exp (2 * a data.d) * Q_R_lin V ↑(R_2 data) f f := by @@ -590,11 +527,11 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul . intro k hk i_neq simp right - simp [Finsupp.single_apply, i_neq] + simp [i_neq] . intro k hk i_neq simp right - simp [Finsupp.single_apply, i_neq] + simp [i_neq] simp [large_basis] at i_not_mem simp [Q_R_lin_plain] @@ -617,7 +554,6 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul field_simp at a_gt unfold Q_R_ortho at det_Q_R_one have foo := Q_R_v_orthonormal_eq_1 - unfold q_r_v_orthonormal at Q_R_v_orthonormal_eq_1 simp [R] at Q_R_v_orthonormal_eq_1 simp [Q_R_v_orthonormal_eq_1] at a_gt @@ -628,7 +564,7 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul . have foo := q_r_lin_remapped_one simp [Q_R_lin, Q_R] at foo - simp [finite_closed_ball] + simp rw [foo] . simp @@ -745,7 +681,7 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul apply Matrix.PosDef.of_dotProduct_mulVec_pos (?_) . intro x hx - simp [Q_R_matrix] + simp conv => rhs lhs @@ -767,7 +703,7 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul apply Matrix.PosDef.eigenvalues_pos apply Matrix.PosDef.of_dotProduct_mulVec_pos (?_) . intro x hx - simp [Q_R_matrix] + simp conv => rhs lhs @@ -793,7 +729,6 @@ lemma exists_bounded_doubling_subspace (data: GoodScalesData b): ∃ U: Submodul grind . exact (Real.rpow_pos_of_pos det_succ_pos _).ne' -#print axioms exists_bounded_doubling_subspace end V_Wrapper_Section diff --git a/Gromov/Complexification.lean b/Gromov/Complexification.lean index 71602f6..6ccd3ae 100644 --- a/Gromov/Complexification.lean +++ b/Gromov/Complexification.lean @@ -41,11 +41,11 @@ def fst (p : Cx V) : V := (p : V × V).1 @[expose] def snd (p : Cx V) : V := (p : V × V).2 -omit [InnerProductSpace ℝ V] in +omit [NormedAddCommGroup V] [InnerProductSpace ℝ V] in @[simp] lemma fst_mk (a b : V) : fst ((a, b) : Cx V) = a := rfl -omit [InnerProductSpace ℝ V] in +omit [NormedAddCommGroup V] [InnerProductSpace ℝ V] in @[simp] lemma snd_mk (a b : V) : snd ((a, b) : Cx V) = b := rfl -omit [InnerProductSpace ℝ V] in +omit [NormedAddCommGroup V] [InnerProductSpace ℝ V] in @[ext] lemma ext {p q : Cx V} (h1 : p.fst = q.fst) (h2 : p.snd = q.snd) : p = q := Prod.ext h1 h2 omit [InnerProductSpace ℝ V] in @@ -92,7 +92,7 @@ lemma innerC_self_re (u : Cx V) : Complex.I_im, Complex.ofReal_im, zero_mul, mul_zero, sub_zero, add_zero] /-- The inner product space core on the complexification. -/ -@[expose] +@[expose, instance_reducible] noncomputable def coreC : InnerProductSpace.Core ℂ (Cx V) where inner := innerC conj_inner_symm u v := by unfold innerC; simp [Complex.ext_iff, real_inner_comm] diff --git a/Gromov/Convolution.lean b/Gromov/Convolution.lean index 42fc819..4754eca 100644 --- a/Gromov/Convolution.lean +++ b/Gromov/Convolution.lean @@ -14,8 +14,6 @@ public import Gromov.TendstoNhdsMul public section -set_option linter.style.cdot false -set_option linter.style.whitespace false attribute [local implicit_reducible] Additive namespace GeneratesNS @@ -36,7 +34,7 @@ lemma conv_assoc_of_lp2 {f g h: G → ℝ} (hf: MemLp f 2 Measure.count) (hg: Me funext x - have h_lp_n (n: ℕ): MemLp h n myHaarAddOpp := by + have h_lp_n (n: ℕ): MemLp (fun x : Additive G => h x) n myHaarAddOpp := by apply Continuous.memLp_of_hasCompactSupport (X := Additive G) (μ := myHaarAddOpp) . apply continuous_of_discreteTopology . @@ -48,7 +46,6 @@ lemma conv_assoc_of_lp2 {f g h: G → ℝ} (hf: MemLp f 2 Measure.count) (hg: Me conv => lhs arg 1 - simp eta_reduce rw [MeasureTheory.convolution_assoc (L := ContinuousLinearMap.mul ℝ ℝ) (L₂ := ContinuousLinearMap.mul ℝ ℝ) (L₃ := ContinuousLinearMap.mul ℝ ℝ) (L₄ := ContinuousLinearMap.mul ℝ ℝ)] . rfl @@ -96,7 +93,6 @@ lemma conv_assoc_of_lp2 {f g h: G → ℝ} (hf: MemLp f 2 Measure.count) (hg: Me exact hf . unfold MeasureTheory.MemLp - refine ⟨by apply AEStronglyMeasurable.of_discrete, ?_⟩ rw [← my_add_haar_eq_count] grw [ENNReal.eLpNorm_convolution_le_enorm_mul' (p := 2) (q := 1)] . @@ -104,17 +100,13 @@ lemma conv_assoc_of_lp2 {f g h: G → ℝ} (hf: MemLp f 2 Measure.count) (hg: Me apply ENNReal.mul_lt_top . simp_rw [← Real.norm_eq_abs] - rw [MeasureTheory.eLpNorm_norm] - rw [my_add_haar_eq_count] - exact MemLp.eLpNorm_lt_top hg + have hg' : MemLp (fun x : Additive G => g x) 2 myHaarAddOpp := by + rw [my_add_haar_eq_count] + exact hg + exact hg'.norm.eLpNorm_lt_top . simp_rw [← Real.norm_eq_abs] - rw [MeasureTheory.eLpNorm_norm] - rw [my_add_haar_eq_count] - rw [← my_add_haar_eq_count] - have foo := h_lp_n 1 - simp at foo - exact MemLp.eLpNorm_lt_top foo + simpa only [Nat.cast_one] using (h_lp_n 1).norm.eLpNorm_lt_top . simp . simp . simp @@ -132,7 +124,6 @@ lemma conv_assoc {f g h: G → ℝ} (h_fg: ConvExists f g) (h_gh: ConvExists g h conv => lhs arg 1 - simp eta_reduce rw [MeasureTheory.convolution_assoc (L := ContinuousLinearMap.mul ℝ ℝ) (L₂ := ContinuousLinearMap.mul ℝ ℝ) (L₃ := ContinuousLinearMap.mul ℝ ℝ) (L₄ := ContinuousLinearMap.mul ℝ ℝ)] . rfl @@ -283,7 +274,6 @@ lemma conv_sum {T: Type*} (H: Finset T) (f: T → G → ℝ) (h: G → ℝ) (h_f @[expose] noncomputable def conv_finsupp_lp2 (f: (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G)))) (g : G → ℝ) (hg : g.support.Finite): (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G))) := MeasureTheory.MemLp.toLp (Conv f g) (by simp [MemLp] - refine ⟨by apply AEStronglyMeasurable.of_discrete, ?_⟩ have norm_bound := ENNReal.eLpNorm_convolution_le_enorm_mul (G := Additive G) (f := f) (g := g) (E' := ℝ) (E := ℝ) (F := ℝ) (𝕜 := ℝ) (p := 2) (q := 1) (r := 2) (μ := myHaarAddOpp) (ContinuousLinearMap.mul ℝ ℝ) (by simp) (by simp) (by simp) (by simp) (by apply AEMeasurable.of_discrete) (by apply AEMeasurable.of_discrete) @@ -298,7 +288,7 @@ noncomputable def conv_finsupp_lp2 (f: (MeasureTheory.Lp ℝ 2 (MeasureTheory.vo . apply WithTop.mul_lt_top . exact enorm_lt_top . rw [← my_add_haar_eq_count] - apply (MeasureTheory.Lp.memLp f).2 + apply (MeasureTheory.Lp.memLp f).eLpNorm_lt_top . simp [eLpNorm, eLpNorm'] rw [MeasureTheory.lintegral_count] diff --git a/Gromov/CutoffInequality.lean b/Gromov/CutoffInequality.lean index cb8c23e..6f8d0a7 100644 --- a/Gromov/CutoffInequality.lean +++ b/Gromov/CutoffInequality.lean @@ -17,11 +17,6 @@ public import Gromov.ToMathlib.LinearAlgebra.Matrix.Det public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false open scoped Finset open scoped Pointwise @@ -43,7 +38,6 @@ include hGS -- `deriv_sq (f ∘ (· * j)) x = deriv_sq f (x * j)`, which is what Lemma 3.25 (c) needs. @[expose] noncomputable def deriv_sq (f: G → ℝ) (x: G) := ∑ s ∈ S, (f (s * x) - f x)^2 -set_option maxHeartbeats 9000000 in lemma cutoff_inequality (f φ : G → ℝ) (hf: Laplace_b f = 0) (hφ: φ.support.Finite): ∑' (x: G), ∑ s ∈ S, ((f x * φ x) - (f (s * x) * φ (s * x)))^2 ≤ ∑' (x: G), ∑ s ∈ S, (f x)^2 * (φ (s * x) - φ x)^2 := by @@ -97,7 +91,7 @@ lemma cutoff_inequality (f φ : G → ℝ) (hf: Laplace_b f = 0) (hφ: φ.suppor simp rw [← Finset.sum_neg_distrib] simp_rw [← tsum_neg] - ring + ring_nf have double {a b: ℝ} (hab: a = b): a = (a + b) / 2 := by rw [hab] @@ -187,7 +181,7 @@ lemma cutoff_inequality (f φ : G → ℝ) (hf: Laplace_b f = 0) (hφ: φ.suppor field_simp . simp . - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp apply Set.Finite.inter_of_right @@ -201,7 +195,7 @@ lemma cutoff_inequality (f φ : G → ℝ) (hf: Laplace_b f = 0) (hφ: φ.suppor . intro x hx simp . - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp apply Set.Finite.inter_of_right @@ -221,7 +215,7 @@ lemma cutoff_inequality (f φ : G → ℝ) (hf: Laplace_b f = 0) (hφ: φ.suppor arg 2 intro s rw [Summable.tsum_add (by - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp apply Set.Finite.inter_of_right @@ -235,7 +229,7 @@ lemma cutoff_inequality (f φ : G → ℝ) (hf: Laplace_b f = 0) (hφ: φ.suppor . intro x hx simp ) (by - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp apply Set.Finite.inter_of_right @@ -269,7 +263,7 @@ lemma cutoff_inequality (f φ : G → ℝ) (hf: Laplace_b f = 0) (hφ: φ.suppor field_simp rw [← Summable.tsum_finsetSum] intro s hs - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp apply Set.Finite.inter_of_right @@ -285,7 +279,7 @@ lemma cutoff_inequality (f φ : G → ℝ) (hf: Laplace_b f = 0) (hφ: φ.suppor . simp [S_nonempty] . intro s hs - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp apply Set.Finite.inter_of_left @@ -296,7 +290,6 @@ lemma cutoff_inequality (f φ : G → ℝ) (hf: Laplace_b f = 0) (hφ: φ.suppor apply Set.Finite.inter_of_right apply hφ -#print axioms cutoff_inequality -- TODO - can we make WordNorm.instSemiNormedGroup and use norm notation diff --git a/Gromov/Defs.lean b/Gromov/Defs.lean index 87a78bf..ddaa959 100644 --- a/Gromov/Defs.lean +++ b/Gromov/Defs.lean @@ -15,10 +15,6 @@ structure, `LipschitzH` and the convolution API. public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false -set_option linter.style.whitespace false open Subgroup open scoped Finset @@ -121,19 +117,15 @@ lemma gAct_mul (g h : G) (f: LipschitzH ): gAct (g * h) f = gAct g (gAct h f) := rw [← mul_assoc] -@[expose] -def gAct_const (g: G) (z: ℝ): gAct g (ConstLipschitzH z) = ConstLipschitzH z := by +theorem gAct_const (g: G) (z: ℝ): gAct g (ConstLipschitzH z) = ConstLipschitzH z := by unfold gAct unfold ConstLipschitzH ext x simp [DFunLike.coe] -#synth Module ℝ (LipschitzH) -#synth AddCommGroup (LipschitzH) abbrev W := (LipschitzH) ⧸ ConstF -#synth Module ℝ (W) @[expose] noncomputable def f_n (n: ℕ) (g: G): ℝ := ((1: ℝ) / ((n + 1): ℝ)) * ∑ m: Fin (n + 1), muConv (m.val) g @@ -276,7 +268,7 @@ lemma laplace_sum_swap_helper {f g: G → ℝ} (hgf: f.support.Finite ∨ g.supp . intro s hs apply Summable.mul_left - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp clear foo @@ -301,7 +293,7 @@ lemma laplace_sum_swap_helper {f g: G → ℝ} (hgf: f.support.Finite ∨ g.supp -- TODO - deduplicate this intro s hs apply Summable.mul_left - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp wlog hg: g.support.Finite @@ -328,7 +320,7 @@ lemma laplace_sum_swap_helper {f g: G → ℝ} (hgf: f.support.Finite ∨ g.supp simp . apply Summable.sub - apply summable_of_finite_support + apply summable_of_hasFiniteSupport . unfold Function.HasFiniteSupport simp @@ -343,7 +335,7 @@ lemma laplace_sum_swap_helper {f g: G → ℝ} (hgf: f.support.Finite ∨ g.supp simp_rw [Finset.mul_sum] apply summable_sum intro s hs - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp cases hgf @@ -366,7 +358,7 @@ lemma laplace_sum_swap_helper {f g: G → ℝ} (hgf: f.support.Finite ∨ g.supp simp_rw [mul_sub] apply Summable.sub . - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp cases hgf @@ -382,7 +374,7 @@ lemma laplace_sum_swap_helper {f g: G → ℝ} (hgf: f.support.Finite ∨ g.supp apply Set.Finite.inter_of_right apply hg . - apply summable_of_finite_support + apply summable_of_hasFiniteSupport unfold Function.HasFiniteSupport simp cases hgf diff --git a/Gromov/Defs/Convolution.lean b/Gromov/Defs/Convolution.lean index 46685e4..15d5656 100644 --- a/Gromov/Defs/Convolution.lean +++ b/Gromov/Defs/Convolution.lean @@ -12,10 +12,6 @@ The convolution `Conv`, the measure `mu` and its iterates `muConv`, and the `Lp` public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false -set_option linter.style.whitespace false open Subgroup open scoped Finset @@ -62,12 +58,12 @@ abbrev opAdd (g : G) := Additive.ofMul g lemma conv_eq_sum {f h: G → ℝ} (hconv: ConvExists f h) (g: G): Conv f h g = ∑' (a : Additive G), f (a) * h (g * (Additive.toMul a)⁻¹) := by unfold Conv unfold MeasureTheory.convolution - rw [MeasureTheory.integral_countable'] + rw [MeasureTheory.integral_countable] . simp_rw [MeasureTheory.measureReal_def] unfold myHaarAddOpp simp_rw [MeasureTheory.Measure.addHaar_singleton] - simp [MeasureTheory.Measure.addHaarMeasure_self] + simp simp_rw [← singleton_carrier] simp_rw [TopologicalSpace.PositiveCompacts.carrier_eq_coe] simp [MeasureTheory.Measure.addHaarMeasure_self] @@ -205,7 +201,6 @@ lemma mu_finsupp: (mu ).support.Finite := by simp at foo exact Finset.nonempty_iff_ne_empty.mp foo -#print axioms mu_finsupp -- Proposition 3.12, item 2, in Vikman lemma f_conv_mu (f: G → ℝ): (Conv f (mu )) = fun g => ((1 : ℝ) / (#(S) : ℝ)) * ∑ s ∈ S, f (s * g) := by @@ -257,7 +252,7 @@ lemma f_conv_mu (f: G → ℝ): (Conv f (mu )) = fun g => ((1 : ℝ) / (#(S) : intro x rw [Summable.tsum_mul_left (hf := by ( simp [Pi.single_apply] - apply summable_of_finite_support + apply summable_of_hasFiniteSupport apply Set.Finite.subset (s := {(opAdd ( x⁻¹ * g ))}) . simp . intro z hz @@ -294,7 +289,7 @@ lemma f_conv_mu (f: G → ℝ): (Conv f (mu )) = fun g => ((1 : ℝ) / (#(S) : . -- TODO - deduplicate this simp [Pi.single_apply] - apply summable_of_finite_support + apply summable_of_hasFiniteSupport apply Set.Finite.subset (s := {(opAdd (s⁻¹ * g ))}) . simp . intro z hz @@ -312,11 +307,10 @@ lemma f_conv_mu (f: G → ℝ): (Conv f (mu )) = fun g => ((1 : ℝ) / (#(S) : @[expose] noncomputable def conv_mu_lp2 (f: (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G)))): (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G))) := MeasureTheory.MemLp.toLp (Conv f (mu )) (by rw [MeasureTheory.MemLp] - refine ⟨MeasureTheory.AEStronglyMeasurable.of_discrete, ?_⟩ simp [MeasureTheory.eLpNorm, MeasureTheory.eLpNorm'] rw [f_conv_mu] simp_rw [Finset.mul_sum] - have other := MeasureTheory.memLp_finset_sum (μ := MeasureTheory.volume (α := G)) (s := S) (p := 2) (f := fun s a => ((1 : ℝ) / (#(S) : ℝ)) * f (s * a)) (by + have other := MeasureTheory.memLp_finsetSum (μ := MeasureTheory.volume (α := G)) (s := S) (p := 2) (f := fun s a => ((1 : ℝ) / (#(S) : ℝ)) * f (s * a)) (by intro s hs simp apply MeasureTheory.MemLp.const_mul @@ -331,10 +325,11 @@ noncomputable def conv_mu_lp2 (f: (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume exact mem_f . apply AEMeasurable.of_discrete ) - have sum_norm := other.2 + have sum_norm := other.eLpNorm_lt_top simp [eLpNorm, eLpNorm'] at sum_norm field_simp at sum_norm field_simp + simp only [AEStronglyMeasurable.of_discrete, ite_true] at sum_norm ⊢ exact sum_norm ) diff --git a/Gromov/Defs/LipschitzH.lean b/Gromov/Defs/LipschitzH.lean index c83c23f..89933da 100644 --- a/Gromov/Defs/LipschitzH.lean +++ b/Gromov/Defs/LipschitzH.lean @@ -12,10 +12,6 @@ structure, and finiteness of balls. public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false -set_option linter.style.whitespace false open Subgroup open scoped Finset @@ -149,7 +145,6 @@ instance lipschitzSMul: SMul ℝ (LipschitzH) := { rw [mul_eq_mul_left_iff] left have hf := f.harmonic x - unfold Harmonic at hf simp at hf field_simp at hf exact hf @@ -216,7 +211,6 @@ instance LipschitzH.addMonoid [Generates ] : AddMonoid (LipschitzH) := { ext g show (((n + 1 : ℕ) : ℝ) • f).toFun g = (((n : ℕ) : ℝ) • f).toFun g + f.toFun g simp [lipschitz_smul_tofun] - push_cast ring } @@ -231,32 +225,30 @@ instance LipschitzH.instAddCommGroup: AddCommGroup (LipschitzH) := { sub_eq_add_neg := by intro f h ext g - simp [lipschitz_sub_tofun, lipschitz_add_tofun, lipschitz_neg_tofun] + simp [lipschitz_sub_tofun, lipschitz_neg_tofun] rfl zsmul := fun n f => (n : ℝ) • f zsmul_zero' := by intro f ext g - simp only [HSMul.hSMul, SMul.smul, DFunLike.coe, Int.cast_zero, zero_mul] + simp only [HSMul.hSMul, SMul.smul, Int.cast_zero, zero_mul] rfl neg_add_cancel := by intro f ext g - simp [negLipschitzH] + simp rfl zsmul_succ' := by intro n f ext g show (((n + 1 : ℕ) : ℝ) • f).toFun g = (((n : ℕ) : ℝ) • f).toFun g + f.toFun g simp [lipschitz_smul_tofun] - push_cast ring zsmul_neg' := by intro n hn ext g show ((Int.negSucc n : ℝ) • hn).toFun g = -((((n + 1 : ℕ) : ℝ)) • hn).toFun g simp [lipschitz_smul_tofun] - push_cast ring } @@ -309,12 +301,12 @@ instance lipschitzHVectorSpace : Module ℝ (LipschitzH) := { zero_smul := by intro a ext g - simp [HSMul.hSMul, SMul.smul, DFunLike.coe] + simp [HSMul.hSMul, SMul.smul] } lemma finite_ball (x: G) (r: ℝ): Set.Finite (Metric.ball x r) := Set.Finite.of_finite_image (f := fun a => (word_norm_prod_self a).choose) (by have foo := List.finite_length_le S (WordNorm x + ⌈r⌉₊) - rw [← Set.finite_coe_iff, Set.coe_setOf] at foo + rw [← Set.finite_coe_iff, Set.coe_ofPred] at foo apply Finite.of_injective (β := {l : List S // l.length ≤ WordNorm x + ⌈r⌉₊}) (fun a => ⟨a.val, by ( have ha := a.prop simp [-Subtype.coe_prop] at ha @@ -349,7 +341,7 @@ lemma finite_ball (x: G) (r: ℝ): Set.Finite (Metric.ball x r) := Set.Finite.of -- TODO - deduplicate 99% of this with finite_ball lemma finite_closed_ball (x: G) (r: ℝ): Set.Finite (Metric.closedBall x r) := Set.Finite.of_finite_image (f := fun a => (word_norm_prod_self a).choose) (by have foo := List.finite_length_le S (WordNorm x + ⌈r⌉₊) - rw [← Set.finite_coe_iff, Set.coe_setOf] at foo + rw [← Set.finite_coe_iff, Set.coe_ofPred] at foo apply Finite.of_injective (β := {l : List S // l.length ≤ WordNorm x + ⌈r⌉₊}) (fun a => ⟨a.val, by ( have ha := a.prop simp [-Subtype.coe_prop] at ha diff --git a/Gromov/Defs/Measure.lean b/Gromov/Defs/Measure.lean index 02450ef..2cf42d0 100644 --- a/Gromov/Defs/Measure.lean +++ b/Gromov/Defs/Measure.lean @@ -12,10 +12,6 @@ measure-space instances and the resulting a.e.-triviality lemmas. public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false -set_option linter.style.whitespace false open Subgroup open scoped Finset @@ -146,7 +142,6 @@ lemma singleton_pairwise_disjoint {T: Type*} (s: Set (T)) : s.PairwiseDisjoint S -- Use the fact that we have the discrete topology -set_option maxHeartbeats 500000 in lemma my_add_haar_eq_count: (myHaarAddOpp) = MeasureTheory.Measure.count := by ext s hs by_cases s_finite: Set.Finite s @@ -256,8 +251,7 @@ lemma count_ae_everywhere (p: G → Prop): (∀ᵐ g ∂(MeasureTheory.Measure.c simp [MeasureTheory.Measure.count_eq_zero_iff] -- TODO - there has to be a much simpler way of proving this refine ⟨?_, ?_⟩ - . intro h - intro a + . intro h a by_contra this have a_in: a ∈ {a | ¬ p a} := by simp [this] diff --git a/Gromov/Defs/WordMetric.lean b/Gromov/Defs/WordMetric.lean index 4746cfe..e9393b4 100644 --- a/Gromov/Defs/WordMetric.lean +++ b/Gromov/Defs/WordMetric.lean @@ -13,10 +13,6 @@ instance. public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false -set_option linter.style.whitespace false open Subgroup open scoped Finset @@ -99,7 +95,7 @@ lemma mem_S_prod_list (x: G): ∃ l: List S, ProdS x l := by -- https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Group.20.28.2FMonoid.2Fetc.29.20closures.20are.20a.20finite.20product.2Fsum/near/477951441 have foo := Submonoid.exists_list_of_mem_closure (s := S ∪ S⁻¹) (x := x) rw [← Subgroup.closure_toSubmonoid _] at foo - simp only [mem_toSubmonoid, Finset.mem_coe] at foo + simp only [mem_toSubmonoid] at foo specialize foo (mem_closure x) norm_cast at foo rw [s_union_sinv] at foo @@ -123,7 +119,7 @@ lemma word_norm_prod (g: G) (n: ℕ) (hgn: WordNorm g = n): ∃ l: List S, ProdS unfold ProdS at hl rw [Set.nonempty_def] at foo specialize foo ⟨l.length, ⟨l, ⟨by simp, hl⟩⟩⟩ - simp only [Set.mem_setOf_eq] at foo + simp only [Set.mem_ofPred_eq] at foo obtain ⟨l, ⟨hl, hl_prod⟩⟩ := foo rw [← hgn] exact ⟨l, ⟨hl_prod, hl⟩⟩ @@ -147,7 +143,7 @@ lemma WordDist_self (x: G): WordDist x x = 0 := by unfold WordDist rw [mul_inv_cancel] unfold WordNorm - simp only [Nat.sInf_eq_zero, Set.mem_setOf_eq, List.length_eq_zero_iff, exists_eq_left] + simp only [Nat.sInf_eq_zero, Set.mem_ofPred_eq, List.length_eq_zero_iff, exists_eq_left] left rfl @@ -228,7 +224,7 @@ lemma word_norm_eq_zero {x y: G} (hdist: WordDist x y = 0): x = y := by unfold ProdS at hl have len_in_set: l.unattach.length ∈ (∅ : Set ℕ) := by rw [← empty_set] - simp only [List.length_unattach, Set.mem_setOf_eq] + simp only [List.length_unattach, Set.mem_ofPred_eq] use l refine ⟨rfl, hl⟩ simp only [Set.mem_empty_iff_false] at len_in_set @@ -356,7 +352,7 @@ lemma dist_word_le_mul {x y z : G} (hy: y ∈ S): WordDist x z ≤ (WordDist x ( rw [mul_inv_eq_one] at l_prod grind | h::tail => - use [ ⟨y⁻¹, by simp [hGS.has_inv, hy]⟩, ⟨h.val, by simp [hGS.has_inv]⟩,] ++ tail + use [ ⟨y⁻¹, by simp [hGS.has_inv, hy]⟩, ⟨h.val, by simp⟩,] ++ tail simp [ProdS] simp [← l_len] simp [ProdS] at l_prod diff --git a/Gromov/FormalConjecturesCheck.lean b/Gromov/FormalConjecturesCheck.lean index 6c8c31e..52e4b65 100644 --- a/Gromov/FormalConjecturesCheck.lean +++ b/Gromov/FormalConjecturesCheck.lean @@ -1,6 +1,7 @@ module public import Gromov.Gromov +public import Gromov.PolynomialGrowth /-! # Cross-check of `main_gromov_theorem` against the `formal-conjectures` statement @@ -34,34 +35,32 @@ public section set_option linter.style.longLine false +@[instance_reducible] +private noncomputable def generatorsData {G : Type*} (gg : Group G) (de : DecidableEq G) + (T : Finset G) (hT : Nonempty T) + (hgen : (@Subgroup.closure G gg (T : Set G) : Set G) = Set.univ) + (h1 : @OfNat.ofNat G 1 (@One.toOfNat1 G gg.toOne) ∈ T) + (hinv : ∀ g ∈ T, @Inv.inv G gg.toInv g ∈ T) + (hi : Infinite G) (hp : @HasPolynomialGrowth G gg de T) : Generates := + @Generates.mk G gg de T hT hgen h1 hinv hi hp + +private theorem gromovOfGeneratorData {G : Type*} (gg : Group G) (de : DecidableEq G) + (T : Finset G) (hT : Nonempty T) + (hgen : (@Subgroup.closure G gg (T : Set G) : Set G) = Set.univ) + (h1 : @OfNat.ofNat G 1 (@One.toOfNat1 G gg.toOne) ∈ T) + (hinv : ∀ g ∈ T, @Inv.inv G gg.toInv g ∈ T) + (hi : Infinite G) (hp : @HasPolynomialGrowth G gg de T) : + @Group.IsVirtuallyNilpotent G gg := by + let inst := generatorsData gg de T hT hgen h1 hinv hi hp + obtain ⟨n, hn⟩ := hp + exact GeneratesNS.main_gromov_theorem (hGS := inst) n hn + namespace FormalConjecturesCheck open scoped Pointwise variable {G : Type*} [Group G] -/-! ### Definitions copied from `formal-conjectures` -/ - -/-- The `CayleyBall` is the ball of radius `n` in the Cayley graph of a group `G` with generating -set `S`. -/ -@[expose] -def CayleyBall (S : Set G) (n : ℕ) : Set G := - {g : G | ∃ (l : List G), l.length ≤ n ∧ (∀ s ∈ l, s ∈ S ∨ s⁻¹ ∈ S) ∧ l.prod = g} - -/-- The `GrowthFunction` of a group `G` with respect to a set `S` counts the number of group -elements that can be reached by words of length at most `n` in `S`. -/ -@[expose] -noncomputable def GrowthFunction (S : Set G) (n : ℕ) : ℕ := - (CayleyBall S n).ncard - -/-- A group has polynomial growth if there exists a finite generating set whose growth function is -bounded above by a polynomial. -/ -@[expose] -def HasPolynomialGrowth (G : Type*) [Group G] : Prop := - ∃ (S : Set G), Set.Finite S ∧ Subgroup.closure S = ⊤ ∧ - ∃ (C : ℝ) (d : ℕ), C > 0 ∧ - ∀ n > 0, (GrowthFunction S n : ℝ) ≤ C * (n : ℝ) ^ d - /-! ### Normalizing the generating set -/ variable [DecidableEq G] @@ -145,41 +144,59 @@ lemma card_normGen_pow (S : Set G) (hS : S.Finite) (n : ℕ) : /-! ### The forward direction of the reference statement -/ -set_option maxHeartbeats 1000000 in +private lemma normGen_polynomial (S : Set G) (hSfin : S.Finite) (C : ℝ) (d : ℕ) + (hbound : ∀ n : ℕ, 0 < n → (GrowthFunction S n : ℝ) ≤ C * (n : ℝ) ^ d) : + HasPolynomialGrowthD (normGen S hSfin) d := by + refine ⟨⌈C⌉₊, fun n hn => ?_⟩ + have hcard : ((normGen S hSfin) ^ n).card = GrowthFunction S n := card_normGen_pow S hSfin n + have hb := hbound n (by omega) + rw [← hcard] at hb + have h : (((normGen S hSfin) ^ n).card : ℝ) ≤ (⌈C⌉₊ : ℝ) * (n : ℝ) ^ d := + hb.trans (by gcongr; exact Nat.le_ceil C) + exact_mod_cast h + +private lemma normGen_generates (S : Set G) (hSfin : S.Finite) + (hSgen : Subgroup.closure S = ⊤) : + (Subgroup.closure (normGen S hSfin : Set G) : Set G) = ⊤ := by + have hclosure : Subgroup.closure ((normGen S hSfin : Finset G) : Set G) = ⊤ := by + rw [eq_top_iff, ← hSgen] + exact Subgroup.closure_mono (subset_normGen S hSfin) + rw [hclosure] + rfl + +private theorem normalized_data (S : Set G) (hSfin : S.Finite) + (hSgen : Subgroup.closure S = ⊤) (C : ℝ) (d : ℕ) + (hbound : ∀ n : ℕ, 0 < n → (GrowthFunction S n : ℝ) ≤ C * (n : ℝ) ^ d) : + ∃ T : Finset G, Nonempty T ∧ + (Subgroup.closure (T : Set G) : Set G) = Set.univ ∧ + (1 : G) ∈ T ∧ (∀ g ∈ T, g⁻¹ ∈ T) ∧ _root_.HasPolynomialGrowth T := by + refine ⟨normGen S hSfin, ⟨⟨1, one_mem_normGen S hSfin⟩⟩, + normGen_generates S hSfin hSgen, one_mem_normGen S hSfin, + fun _ hg => inv_mem_normGen S hSfin hg, d, ?_⟩ + exact normGen_polynomial S hSfin C d hbound + +omit [Group G] [DecidableEq G] in +private theorem infinite_forward (gg : Group G) (de : DecidableEq G) (S : Set G) + (hSfin : S.Finite) (hSgen : @Subgroup.closure G gg S = ⊤) (hinf : Infinite G) + (C : ℝ) (d : ℕ) + (hbound : ∀ n : ℕ, 0 < n → (@GrowthFunction G gg S n : ℝ) ≤ C * (n : ℝ) ^ d) : + @Group.IsVirtuallyNilpotent G gg := by + obtain ⟨T, hT, hgen, h1, hinv, hp⟩ := @normalized_data G gg de S hSfin hSgen C d hbound + exact @gromovOfGeneratorData G gg de T hT hgen h1 hinv hinf hp + +omit [Group G] [DecidableEq G] in /-- **The forward direction of `GromovPolynomialGrowth.GromovPolynomialGrowthTheorem`**, derived from `GeneratesNS.main_gromov_theorem`: a finitely generated group of polynomial growth (in the `formal-conjectures` formulation) is virtually nilpotent. -/ -theorem gromov_forward (G : Type*) [Group G] (h : HasPolynomialGrowth G) : +theorem gromov_forward (G : Type*) [gg : Group G] (h : @HasPolynomialGrowth G gg) : Group.IsVirtuallyNilpotent G := by classical - letI dec : DecidableEq G := Classical.decEq G obtain ⟨S, hSfin, hSgen, C, d, hC, hbound⟩ := h rcases finite_or_infinite G with hfin | hinf · exact GeneratesNS.finite_virtually_nilpotent - · have hclosure : Subgroup.closure ((normGen S hSfin : Finset G) : Set G) = ⊤ := by - rw [eq_top_iff, ← hSgen] - exact Subgroup.closure_mono (subset_normGen S hSfin) - have hgrowth : HasPolynomialGrowthD (normGen S hSfin) d := by - refine ⟨⌈C⌉₊, fun n hn => ?_⟩ - have hcard : ((normGen S hSfin) ^ n).card = GrowthFunction S n := card_normGen_pow S hSfin n - have hb := hbound n (by omega) - rw [← hcard] at hb - have : (((normGen S hSfin) ^ n).card : ℝ) ≤ (⌈C⌉₊ : ℝ) * (n : ℝ) ^ d := - hb.trans (by gcongr; exact Nat.le_ceil C) - exact_mod_cast this - letI inst : Generates := - { G := G - g_group := ‹Group G› - g_eq := dec - S := normGen S hSfin - hS := ⟨⟨1, one_mem_normGen S hSfin⟩⟩ - generates := by rw [hclosure]; simp - one_mem := one_mem_normGen S hSfin - has_inv := fun _ hg => inv_mem_normGen S hSfin hg - g_infinite := hinf - g_growth := ⟨d, hgrowth⟩ } - exact GeneratesNS.main_gromov_theorem (hGS := inst) d hgrowth + · exact infinite_forward gg (inferInstance : DecidableEq G) S hSfin hSgen hinf C d hbound +omit [Group G] [DecidableEq G] in /-- The forward direction with the reference statement's exact signature, including the `[Group.FG G]` hypothesis. That hypothesis is redundant here: `HasPolynomialGrowth G` already supplies a finite generating set, so `gromov_forward` proves the same conclusion without it. -/ diff --git a/Gromov/Gromov.lean b/Gromov/Gromov.lean index 985ce00..bfc3ce3 100644 --- a/Gromov/Gromov.lean +++ b/Gromov/Gromov.lean @@ -14,7 +14,6 @@ public section set_option linter.style.longLine false set_option linter.style.cdot false -set_option linter.style.commandStart false open Subgroup open scoped Finset @@ -29,9 +28,7 @@ include hGS open scoped RealInnerProductSpace -set_option synthInstance.maxHeartbeats 500000 -set_option maxHeartbeats 1000000 open MeasureTheory @@ -39,12 +36,445 @@ open Additive attribute [local implicit_reducible] Additive Multiplicative -set_option maxHeartbeats 2500000 in +private def kernelInclusion (data : Theorem3_1_Input G) : + Multiplicative data.φ.ker →* data.G' := + AddMonoidHom.toMultiplicativeLeft data.φ.ker.subtype + +private def kernelValue (data : Theorem3_1_Input G) + (N : Subgroup (Multiplicative data.φ.ker)) : N →* data.G' := + (AddMonoidHom.toMultiplicativeLeft data.φ.ker.subtype).comp N.subtype + +private lemma conjugate_product_wordNorm (x y : G) (Lx Ly a b k : ℕ) + (hx : WordNorm x ≤ Lx) (hy : WordNorm y ≤ Ly) + (hk : 0 < k) (hb : 0 < b) (s : Finset (Finset.Ico a b)) : + WordNorm ((s.toList.map (fun i => y ^ (k * i.val) * x * + (y ^ (k * i.val))⁻¹)).prod) ≤ (b-a) * (max Lx Ly * (4*k*b)) := by + have hterm (i : Finset.Ico a b) : + WordNorm (y ^ (k*i.val) * x * (y ^ (k*i.val))⁻¹) ≤ + max Lx Ly * (4*k*b) := by + have hp : WordNorm (y ^ (k*i.val)) ≤ k*b*max Lx Ly := by + calc + _ ≤ (k*i.val) * WordNorm y := word_norm_pow _ _ + _ ≤ (k*b) * max Lx Ly := by gcongr; exact le_of_lt (Finset.mem_Ico.mp i.property).2; exact hy.trans (le_max_right _ _) + have h1 := word_norm_mul_le (hGS := hGS) (y ^ (k*i.val) * x) ((y ^ (k*i.val))⁻¹) + have h2 := word_norm_mul_le (hGS := hGS) (y ^ (k*i.val)) x + rw [← word_norm_inv (hGS := hGS)] at h1 + have hx' := hx.trans (le_max_left Lx Ly) + have hkb : 1 ≤ k*b := one_le_mul (by omega) (by omega) + have hM := Nat.mul_le_mul_left (max Lx Ly) hkb + nlinarith + calc + _ ≤ ((s.toList.map (fun i => y ^ (k*i.val) * x * + (y ^ (k*i.val))⁻¹)).map WordNorm).sum := word_norm_list_prod_le _ + _ ≤ (s.toList.map (fun _ => max Lx Ly * (4*k*b))).sum := by + rw [List.map_map] + exact List.sum_le_sum (fun i _ => hterm i) + _ = s.card * (max Lx Ly * (4*k*b)) := by simp + _ ≤ (b-a) * (max Lx Ly * (4*k*b)) := by + apply Nat.mul_le_mul_right + simpa using Finset.card_le_univ s + +private lemma conjugate_subproducts_growth (data : Theorem3_1_Input G) + (N' : Subgroup (Multiplicative data.φ.ker)) (γ : Additive data.G') + (hγ : data.φ γ = 1) (gamma_conj_N' : MulAut N') + (conj_mem_ker : ∀ (n : ℕ) (g : N'), + Additive.ofMul (Additive.toMul γ ^ n * kernelValue data N' g * + (Additive.toMul γ ^ n)⁻¹) ∈ data.φ.ker) + (conj_mem_N' : ∀ (n : ℕ) (g : N'), + (Multiplicative.ofAdd (⟨Additive.ofMul (Additive.toMul γ ^ n * kernelValue data N' g * + (Additive.toMul γ ^ n)⁻¹), conj_mem_ker n g⟩ : data.φ.ker)) ∈ N') + (gamma_conj_iter : ∀ (n : ℕ) (g : N'), gamma_conj_N'^[n] g = + ⟨Multiplicative.ofAdd (⟨Additive.ofMul (Additive.toMul γ ^ n * kernelValue data N' g * + (Additive.toMul γ ^ n)⁻¹), conj_mem_ker n g⟩ : data.φ.ker), conj_mem_N' n g⟩) : +∀ k: ℕ, (0 < k) → ∀ g, ∃ p q: ℕ, 0 < p ∧ ∀ b: ℕ, 0 < b → ∀ a: ℕ, (0 < a) → (a < b) → ((Finset.image (fun x ↦ (List.map (fun (i: Finset.Ico a b) ↦ (gamma_conj_N')^[k * ↑i] g) x.toList).prod)) + (Finset.Ico a b).attach.powerset).card ≤ p * (b^q) * (b - a)^q := by + let N'_val := kernelValue data N' + + + have s_poly := hGS.g_growth + unfold HasPolynomialGrowth at s_poly + obtain ⟨q, hq⟩ := s_poly + unfold HasPolynomialGrowthD at hq + obtain ⟨p, hp⟩ := hq + intro k k_pos x + + + obtain ⟨x_list, x_prod, x_list_prod⟩ := + word_norm_prod_self (hGS := hGS) x.val.toAdd.val.toMul.val + obtain ⟨gamma_list, gamma_prod, gamma_list_prod⟩ := + word_norm_prod_self (hGS := hGS) (Additive.toMul γ).val + + + -- `(hGS := hGS)` is required: `new_generates` shadows the ambient instance here, + -- so a bare `S` would resolve to `new_generates.S`. + have p_pos: 0 < p := growth_const_pos (hGS := hGS) hp + + have q_pos: 0 < q := growth_exponent_pos (hGS := hGS) ⟨p, hp⟩ + use p * (((max x_list.length gamma_list.length) * (4 * k)) ^ q) + use q + + + have gamma_len_pos: 1 ≤ gamma_list.length := by + by_contra! + simp at this + simp [ProdS, this] at gamma_prod + have gamma_eq: γ = 0 := by + have gamma_coe := Subtype.coe_eq_of_eq_mk gamma_prod.symm + apply_fun (fun a => Additive.ofMul a) at gamma_coe + rw [ofMul_toMul] at gamma_coe + exact gamma_coe + simp [gamma_eq] at hγ + + refine ⟨?_, ?_⟩ + . + apply mul_pos + . exact p_pos + . + rw [pow_pos_iff] + . + positivity + . grind + + + intro b hb a ha hab + + have mul_nozero: 1 ≤ 2 * k * b := by + rw [mul_assoc] + apply one_le_mul + . simp + . apply one_le_mul + . grind + . grind + + + grw [← Finset.card_image_of_injOn (f := fun a => a.val.toAdd.val.toMul.val) (by simp)] + grw [Finset.card_le_card (t := hGS.S^((b - a) * ((max x_list.length gamma_list.length) * (4 * k * b)) ))] + · + + grw [hp] + . + rw [mul_pow] + ring_nf + simp + . + simp + apply one_le_mul + . grind + . + rw [Nat.one_le_iff_ne_zero, ← Nat.pos_iff_ne_zero] + + + positivity + -- side goal from `card_le_card`: the image is contained in `hGS.S` + · + let f : N' →* G := data.G'.subtype.comp (kernelValue data N') + have hf (n : ℕ) (g : N') : f (gamma_conj_N'^[n] g) = + (Additive.toMul γ).val ^ n * f g * ((Additive.toMul γ).val ^ n)⁻¹ := by + rw [gamma_conj_iter] + rfl + intro g hg + obtain ⟨z, hz, rfl⟩ := Finset.mem_image.mp hg + obtain ⟨s, hs, rfl⟩ := Finset.mem_image.mp hz + change f ((s.toList.map (fun i : Finset.Ico a b => gamma_conj_N'^[k*i.val] x)).prod) ∈ _ + rw [map_list_prod, List.map_map] + simp only [Function.comp_def] + simp_rw [hf] + rw [← closed_ball_eq_S_pow (hGS := hGS)] + simp only [Set.Finite.mem_toFinset, Metric.mem_closedBall, dist, WordDist_one] + norm_cast + exact conjugate_product_wordNorm (hGS := hGS) (f x) (Additive.toMul γ).val + x_list.length gamma_list.length a b k + (by change WordNorm x.val.toAdd.val.toMul.val ≤ _; rw [← x_list_prod]) + (by rw [← gamma_list_prod]) k_pos hb s + + + +omit hGS in +private lemma cyclic_kernel_sup {D : Type*} [Group D] + (φ : Additive D →+ ℤ) (γ : Additive D) (hγ : φ γ = 1) : + Subgroup.closure {γ.toMul} ⊔ φ.ker.toSubgroup' = ⊤ := by + apply top_unique + intro g _ + let z := φ (Additive.ofMul g) + have hk : Additive.toMul (-(z • γ) + Additive.ofMul g) ∈ φ.ker.toSubgroup' := by + change φ (-(z • γ) + Additive.ofMul g) = 0 + simp [z, hγ] + have ht : Additive.toMul (z • γ) ∈ Subgroup.closure {γ.toMul} := by + rw [Subgroup.mem_closure_singleton] + exact ⟨z, by simp⟩ + have he : g = Additive.toMul (z • γ) * + Additive.toMul (-(z • γ) + Additive.ofMul g) := by + rw [← toMul_add, add_neg_cancel_left] + rfl + rw [he] + exact Subgroup.mul_mem _ (Subgroup.mem_sup_left ht) (Subgroup.mem_sup_right hk) + +private lemma cyclic_kernel_finiteIndex (data : Theorem3_1_Input G) + (γ : Additive data.G') (hγ : data.φ γ = 1) + (N' : Subgroup (Multiplicative data.φ.ker)) [N'.FiniteIndex] + (N'_fg : ∃ T : Finset (Multiplicative data.φ.ker), Subgroup.closure (↑T) = N') (α : ℕ) (alpha_nonzero : α ≠ 0) + (hinv : ∀ {n : ℕ}, ∀ b ∈ Subgroup.closure {γ.toMul ^ n}, + ∀ a ∈ Subgroup.map (kernelInclusion data) (Subgroup.closure (↑N'_fg.choose)), + b * a * b⁻¹ ∈ Subgroup.map (kernelInclusion data) (Subgroup.closure (↑N'_fg.choose))) : + (Subgroup.map data.G'.subtype + (Subgroup.closure (↑(Finset.image (kernelInclusion data) N'_fg.choose) ∪ + {γ.toMul ^ α}))).FiniteIndex := by + let new_N'_map := kernelInclusion data + have map_N'_invariant_gamma {n : ℕ} := hinv (n := n) + have map_N'_invariant_gamma_one := map_N'_invariant_gamma (n := 1) + simp only [pow_one] at map_N'_invariant_gamma_one + rw [Subgroup.finiteIndex_iff] + rw [Subgroup.index_map] + simp + refine ⟨?_, ?_⟩ + . + + simp_rw [Set.insert_eq] + + have gamma_alpha_le_gamma: (Subgroup.closure ({toMul γ ^ α} ∪ (new_N'_map '' (N'_fg.choose)) )) ≤ (Subgroup.closure ({toMul γ} ∪ (new_N'_map '' (N'_fg.choose)))) := by + simp + intro g hg + rw [Set.insert_eq] + cases hg + . rename_i g_eq_gamma + rw [Subgroup.closure_union] + apply Subgroup.mem_sup_left + rw [Subgroup.mem_closure_singleton] + use α + rw [g_eq_gamma] + simp + . rename_i g_mem_map + rw [Subgroup.closure_union] + apply Subgroup.mem_sup_right + apply Subgroup.mem_closure_of_mem + exact g_mem_map + + conv => + arg 1 + arg 1 + arg 1 + arg 1 + arg 2 + equals (new_N'_map '' (N'_fg.choose)) => rfl + rw [← Subgroup.relIndex_mul_index gamma_alpha_le_gamma] + simp + refine ⟨?_, ?_⟩ + . + unfold Subgroup.relIndex + rw [← ne_eq] + rw [← Subgroup.finiteIndex_iff] + apply Subgroup.finiteIndex_of_rightCoset_cover_const (s := Finset.Ioo (-α : ℤ) (α)) (g := fun a => ⟨a • γ, (by + rw [Set.insert_eq, Subgroup.closure_union] + apply Subgroup.mem_sup_left + rw [Subgroup.mem_closure_singleton] + use a + rfl + )⟩) + ext g + simp + have g_prop := g.property + simp_rw [Set.insert_eq, Subgroup.closure_union] at g_prop + rw [← MonoidHom.map_closure] at g_prop + simp at g_prop + rw [← SetLike.mem_coe] at g_prop + rw [sup_comm] at g_prop + + + rw [Subgroup.coe_mul_of_right_le_normalizer_left _ _ + (Subgroup.le_normalizer_of_conj_mem map_N'_invariant_gamma_one)] at g_prop + rw [Set.mem_mul] at g_prop + obtain ⟨b, hb, a, ha, g_eq⟩ := g_prop + simp at ha + rw [Subgroup.mem_closure_singleton] at ha + obtain ⟨z, hz⟩ := ha + use z % α + refine ⟨?_, ?_⟩ + . + have foo := Int.emod_lt_abs z (b := α) (by grind) + rw [lt_abs] at foo + refine ⟨?_, ?_⟩ + . + have bar := Int.emod_nonneg z (b := α) (by simpa using alpha_nonzero) + grind + . grind + . + rw [Set.mem_smul_set] + use ⟨(Additive.ofMul b) + (((α : ℤ) * (z / (α : ℤ))) • γ), ?_⟩ + . + refine ⟨?_, ?_⟩ + . + simp + rw [Subgroup.mem_subgroupOf] + simp_rw [Set.insert_eq, Subgroup.closure_union] + rw [← SetLike.mem_coe] + rw [sup_comm] + rw [Subgroup.coe_mul_of_right_le_normalizer_left _ _ (Subgroup.le_normalizer_of_conj_mem (by + simp_rw [← MonoidHom.map_closure] + apply map_N'_invariant_gamma + ))] + apply Set.mul_mem_mul + . + simp + rw [← MonoidHom.map_closure] + exact hb + . + simp + rw [Subgroup.mem_closure_singleton] + use (z / (α : ℤ)) + conv => + lhs + arg 1 + equals toMul γ ^ (α : ℤ) => + simp + + rw [← zpow_mul] + . + simp + rw [Subtype.ext_iff] + simp + rw [← g_eq, ←hz] + nth_rw 3 [← Int.mul_ediv_add_emod (a := z) (b := α)] + rw [← toMul_zsmul] + conv => + lhs + equals (ofMul b) + ((↑α * (z / ↑α)) • γ) + ((z % ↑α) • γ) => + rfl + + + rw [add_zsmul] + rw [add_assoc] + rfl + . + simp_rw [Set.insert_eq, Subgroup.closure_union] + rw [sup_comm] + rw [← SetLike.mem_coe] + + rw [Subgroup.coe_mul_of_right_le_normalizer_left _ _ (Subgroup.le_normalizer_of_conj_mem (by + simp_rw [← MonoidHom.map_closure] + apply map_N'_invariant_gamma_one + ))] + apply Set.mul_mem_mul + . + simp + rw [← MonoidHom.map_closure] + exact hb + . + simp [Subgroup.mem_closure_singleton] + . + obtain ⟨s, s_compl, s_cosets⟩ := Subgroup.exists_leftTransversal_of_FiniteIndex (D := N') (H := ⊤) (by simp) + simp at s_cosets + + rw [← ne_eq] + rw [← Subgroup.finiteIndex_iff] + apply Subgroup.finiteIndex_of_leftCoset_cover_const (s := s) (g := fun g => g.val.val.toMul) + simp_rw [Set.insert_eq, Subgroup.closure_union] + rename_bvar i → g + + + conv => + arg 1 + arg 1 + intro i + arg 1 + intro hi + rw [sup_comm] + rw [Subgroup.coe_mul_of_right_le_normalizer_left _ _ (Subgroup.le_normalizer_of_conj_mem (by + intro gamma_pow h_gamma_pow n hn + simp_rw [← MonoidHom.map_closure] at hn + simp_rw [← MonoidHom.map_closure] + apply map_N'_invariant_gamma_one _ h_gamma_pow _ hn + ))] + rw [set_smul_eq_mul] + rw [← mul_assoc] + rw [← set_smul_eq_mul] + + + simp_rw [← Set.iUnion_mul] + conv => + arg 1 + arg 1 + equals Additive.toMul '' data.φ.ker => + apply_fun (fun s => Additive.toMul '' (Subtype.val '' s)) at s_cosets + conv at s_cosets => + rhs + equals Additive.toMul '' data.φ.ker => + ext a + simp + rw [← s_cosets] + conv => + arg 1 + arg 1 + intro i + arg 1 + intro hi + arg 2 + + simp_rw [← MonoidHom.map_closure] + + simp only [Set.image_image] + erw [Set.image_iUnion₂] + apply Set.iUnion_congr + intro i + apply Set.iUnion_congr + intro hi + ext z + simp only [coe_map] + rw [Set.mem_smul_set] + rw [Set.mem_image] + refine ⟨?_, ?_⟩ + . + intro hy + obtain ⟨a, ha⟩ := hy + have foo := ha.1 + rw [Set.mem_image] at foo + obtain ⟨b, b_mem, a_eq_b⟩ := foo + have N'_gen := N'_fg.choose_spec + rw [N'_gen] at b_mem + refine ⟨(↑i : Multiplicative ↥data.φ.ker) • b, Set.smul_mem_smul_set b_mem, ?_⟩ + rw [← ha.2, ← a_eq_b] + rfl + . + intro hx + obtain ⟨x, hx, x_eq⟩ := hx + erw [Set.mem_smul_set] at hx + obtain ⟨n, hn, x_eq_n⟩ := hx + refine ⟨new_N'_map n, ?_, ?_⟩ + . + rw [Set.mem_image] + have N'_gen := N'_fg.choose_spec + rw [← N'_gen] at hn + exact ⟨n, hn, rfl⟩ + . rw [← x_eq, ← x_eq_n] + rfl + + + conv => + arg 1 + lhs + equals ↑data.φ.ker.toSubgroup' => + ext a + simp + + rw [← Subgroup.coe_mul_of_right_le_normalizer_left _ _] + . + simpa [sup_comm] using cyclic_kernel_sup data.φ γ hγ + . + apply Subgroup.le_normalizer_of_conj_mem + intro b hb a ha + rw [Subgroup.mem_closure_singleton] at hb + obtain ⟨n, b_eq⟩ := hb + simp [← b_eq] + simp at ha + exact ha + . have foo := data.finite_index + rw [Subgroup.finiteIndex_iff] at foo + exact foo + omit hGS in lemma theorem_3_1.{u} [hGS: Generates.{u}] (data: Theorem3_1_Input G) (d: ℕ) (hd: 1 ≤ d) (h_growth: HasPolynomialGrowthD S d) (inductive_gromov: ∀ (Q_generates: Generates.{u}),(Q_growth : (HasPolynomialGrowthD (Q_generates.S)) (d - 1)) → Group.IsVirtuallyNilpotent Q_generates.G) : Group.IsVirtuallyNilpotent G := by - letI inst_dec_G : DecidableEq G := G_dec_eq + let inst_dec_G : DecidableEq G := G_dec_eq have G'_finite_index := data.finite_index have G'_fg: Group.FG data.G' := by @@ -224,14 +654,7 @@ lemma theorem_3_1.{u} [hGS: Generates.{u}] (data: Theorem3_1_Input G) (d: ℕ) ( let N' := Subgroup.closure (Set.range (fun (a: Multiplicative data.φ.ker) => a ^ N.index)) - let new_N'_map : _ →* _ := { - toFun := fun (g: (Multiplicative ↥data.φ.ker)) => Additive.toMul (data.φ.ker.subtype g) - map_one' := rfl - map_mul' := by - intro x y - rfl - } - + let new_N'_map := kernelInclusion (hGS := hGS) data let new_N': Subgroup (data.G') := Subgroup.map new_N'_map N' @@ -357,8 +780,7 @@ lemma theorem_3_1.{u} [hGS: Generates.{u}] (data: Theorem3_1_Input G) (d: ℕ) ( -- The underlying element of `data.G'` of an element of `N'`, with every `Additive` / -- `Multiplicative` conversion spelled out instead of relying on definitional unfolding: -- `↥N' → Multiplicative ↥data.φ.ker → ↥data.φ.ker → Additive ↥data.G' → ↥data.G'`. - let N'_val : ↥N' →* ↥data.G' := - (AddMonoidHom.toMultiplicativeLeft data.φ.ker.subtype).comp N'.subtype + let N'_val : ↥N' →* ↥data.G' := kernelValue (hGS := hGS) data N' have gamma_conj_ker_apply: ∀ a: ↥data.φ.ker, data.φ.ker.subtype (gamma_conj_ker a) = γ + data.φ.ker.subtype a + -γ := by @@ -369,11 +791,10 @@ lemma theorem_3_1.{u} [hGS: Generates.{u}] (data: Theorem3_1_Input G) (d: ℕ) ( have gamma_conj_step: ∀ g: ↥N', N'_val (gamma_conj_N' g) = Additive.toMul γ * N'_val g * (Additive.toMul γ)⁻¹ := by intro g - simp only [N'_val, gamma_conj_N', gamma_conj_ker_mul, MonoidHom.coe_comp, Function.comp_apply, + simp only [N'_val, kernelValue, gamma_conj_N', gamma_conj_ker_mul, MonoidHom.coe_comp, Function.comp_apply, AddMonoidHom.coe_toMultiplicativeLeft, Subgroup.coe_subtype, MulAut.characteristic_apply_apply_coe, AddEquiv.toMultiplicative_apply_apply, - AddEquiv.toAddMonoidHom_eq_coe, AddMonoidHom.toMultiplicative_apply_apply, - AddMonoidHom.coe_coe, toAdd_ofAdd, gamma_conj_ker_apply, toMul_add, toMul_neg] + toAdd_ofAdd, gamma_conj_ker_apply, toMul_add, toMul_neg] have gamma_conj_iter_val: ∀ (n: ℕ), ∀ g: ↥N', N'_val (gamma_conj_N'^[n] g) @@ -424,146 +845,8 @@ lemma theorem_3_1.{u} [hGS: Generates.{u}] (data: Theorem3_1_Input G) (d: ℕ) ( intro n g exact Subtype.ext (conj_val_eq n g).symm - have gamma_conj_card: ∀ k: ℕ, (0 < k) → ∀ g, ∃ p q: ℕ, 0 < p ∧ ∀ b: ℕ, 0 < b → ∀ a: ℕ, (0 < a) → (a < b) → ((Finset.image (fun x ↦ (List.map (fun (i: Finset.Ico a b) ↦ (gamma_conj_N')^[k * ↑i] g) x.toList).prod)) - (Finset.Ico a b).attach.powerset).card ≤ p * (b^q) * (b - a)^q := by - - have s_poly := hGS.g_growth - unfold HasPolynomialGrowth at s_poly - obtain ⟨q, hq⟩ := s_poly - unfold HasPolynomialGrowthD at hq - obtain ⟨p, hp⟩ := hq - intro k k_pos x - - - obtain ⟨x_list, x_prod, x_list_prod⟩ := - word_norm_prod_self (hGS := hGS) x.val.toAdd.val.toMul.val - obtain ⟨gamma_list, gamma_prod, gamma_list_prod⟩ := - word_norm_prod_self (hGS := hGS) (Additive.toMul γ).val - - - -- `(hGS := hGS)` is required: `new_generates` shadows the ambient instance here, - -- so a bare `S` would resolve to `new_generates.S`. - have p_pos: 0 < p := growth_const_pos (hGS := hGS) hp - - have q_pos: 0 < q := growth_exponent_pos (hGS := hGS) ⟨p, hp⟩ - use p * (((max x_list.length gamma_list.length) * (4 * k)) ^ q) - use q - - - have gamma_len_pos: 1 ≤ gamma_list.length := by - by_contra! - simp at this - simp [ProdS, this] at gamma_prod - have gamma_eq: γ = 0 := by - have gamma_coe := Subtype.coe_eq_of_eq_mk gamma_prod.symm - apply_fun (fun a => Additive.ofMul a) at gamma_coe - rw [ofMul_toMul] at gamma_coe - exact gamma_coe - simp [gamma_eq] at hγ - - refine ⟨?_, ?_⟩ - . - apply mul_pos - . exact p_pos - . - rw [pow_pos_iff] - . - positivity - . grind - - - intro b hb - intro a ha hab - - have mul_nozero: 1 ≤ 2 * k * b := by - rw [mul_assoc] - apply one_le_mul - . simp - . apply one_le_mul - . grind - . grind - - - grw [← Finset.card_image_of_injOn (f := fun a => a.val.toAdd.val.toMul.val) (by simp)] - grw [Finset.card_le_card (t := hGS.S^((b - a) * ((max x_list.length gamma_list.length) * (4 * k * b)) ))] - · - - grw [hp] - . - rw [mul_pow] - ring - simp - . - simp - apply one_le_mul - . grind - . - rw [Nat.one_le_iff_ne_zero, ← Nat.pos_iff_ne_zero] - - - positivity - -- side goal from `card_le_card`: the image is contained in `hGS.S` - · - intro g hg - simp at hg - obtain ⟨s, hs, g_eq⟩ := hg - simp [ProdS] at x_prod - simp [ProdS] at gamma_prod - rw [eq_comm] at x_prod - rw [eq_comm] at gamma_prod - have gamma_eq := Subtype.coe_eq_of_eq_mk gamma_prod - apply_fun (fun a => Additive.ofMul a) at gamma_eq - rw [ofMul_toMul] at gamma_eq - - have x_eq := Subtype.coe_eq_of_eq_mk x_prod - apply_fun (fun a => Additive.ofMul a) at x_eq - rw [ofMul_toMul] at x_eq - have x_eq := Subtype.coe_eq_of_eq_mk x_eq - apply_fun (fun a => Multiplicative.ofAdd a) at x_eq - rw [ofAdd_toAdd] at x_eq - have x_eq := Subtype.coe_eq_of_eq_mk x_eq - simp_rw [x_eq] at g_eq - simp_rw [gamma_conj_iter] at g_eq - simp at g_eq - simp_rw [gamma_eq] at g_eq - rw [← g_eq] - rw [← closed_ball_eq_S_pow (hGS := hGS)] - simp [-le_sup_iff] - simp only [dist, WordDist_one] - norm_cast - simp_rw [Function.comp_def] - simp [-le_sup_iff] - grw [word_norm_list_prod_le (hGS := hGS)] - rw [List.unattach.eq_def (l := s.toList)] - nth_rw 2 [List.map_map] - grw [List.sum_le_sum (g := Function.const _ ((max x_list.length gamma_list.length) * (4 * k * b)))] - . - simp [-le_sup_iff] - grw [Finset.card_le_univ] - simp - . - intro y hy - simp at hy - obtain ⟨m, ⟨⟨m_range, m_mem⟩, y_eq⟩⟩ := hy - rw [← y_eq] - grw [word_norm_mul_le (hGS := hGS)] - grw [word_norm_mul_le (hGS := hGS)] - rw [← word_norm_inv (hGS := hGS)] - grw [word_norm_pow (hGS := hGS)] - rw [← gamma_prod, ← gamma_list_prod] - simp [N'_val] - rw [← x_prod, ← x_list_prod] - grw [m_range.2] - ring - have four_eq: 4 = (2 + 2) := by norm_num - rw [four_eq, mul_add] - apply add_le_add - . simp - grw [le_max_right (b := gamma_list.length)] - . grw [← le_max_left (a := x_list.length)] - ring - nlinarith - + have gamma_conj_card := conjugate_subproducts_growth (hGS := hGS) data N' γ hγ + gamma_conj_N' conj_mem_ker conj_mem_N' gamma_conj_iter obtain ⟨α, m, alpha_nonzero, alpha_is_unipotent_conj⟩ := exists_gamma_n_unipotent_N' (N' := N') N'_nilpotent N'_fg gamma_conj_N' gamma_conj_card 1 (by simp) simp_rw [mul_one] at alpha_is_unipotent_conj @@ -608,7 +891,7 @@ lemma theorem_3_1.{u} [hGS: Generates.{u}] (data: Theorem3_1_Input G) (d: ℕ) ( } - haveI : Subgroup.Characteristic N' := N'_char + have : Subgroup.Characteristic N' := N'_char have alpha_nilpotent := unipotent_commutator_trivial (G := data.G') (H := data.φ.ker.toSubgroup') (N' := N') (N'_char := N'_char) (N'_nilpotent := by exact N'_nilpotent ) (γ.toMul^α) (by @@ -680,300 +963,9 @@ lemma theorem_3_1.{u} [hGS: Generates.{u}] (data: Theorem3_1_Input G) (d: ℕ) ( . exact alpha_nilpotent . - rw [Subgroup.finiteIndex_iff] - rw [Subgroup.index_map] - simp - refine ⟨?_, ?_⟩ - . - - simp_rw [Set.insert_eq] + exact cyclic_kernel_finiteIndex (hGS := hGS) data γ hγ N' N'_fg α alpha_nonzero + (fun {_} => map_N'_invariant_gamma) - have gamma_alpha_le_gamma: (Subgroup.closure ({toMul γ ^ α} ∪ (new_N'_map '' (N'_fg.choose)) )) ≤ (Subgroup.closure ({toMul γ} ∪ (new_N'_map '' (N'_fg.choose)))) := by - simp - intro g hg - rw [Set.insert_eq] - cases hg - . rename_i g_eq_gamma - rw [Subgroup.closure_union] - apply Subgroup.mem_sup_left - rw [Subgroup.mem_closure_singleton] - use α - rw [g_eq_gamma] - simp - . rename_i g_mem_map - rw [Subgroup.closure_union] - apply Subgroup.mem_sup_right - apply Subgroup.mem_closure_of_mem - exact g_mem_map - - conv => - arg 1 - arg 1 - arg 1 - arg 1 - arg 2 - equals (new_N'_map '' (N'_fg.choose)) => rfl - rw [← Subgroup.relIndex_mul_index gamma_alpha_le_gamma] - simp - refine ⟨?_, ?_⟩ - . - unfold Subgroup.relIndex - rw [← ne_eq] - rw [← Subgroup.finiteIndex_iff] - apply Subgroup.finiteIndex_of_rightCoset_cover_const (s := Finset.Ioo (-α : ℤ) (α)) (g := fun a => ⟨a • γ, (by - rw [Set.insert_eq, Subgroup.closure_union] - apply Subgroup.mem_sup_left - rw [Subgroup.mem_closure_singleton] - use a - rfl - )⟩) - ext g - simp - have g_prop := g.property - simp_rw [Set.insert_eq, Subgroup.closure_union] at g_prop - rw [← MonoidHom.map_closure] at g_prop - simp at g_prop - rw [← SetLike.mem_coe] at g_prop - rw [sup_comm] at g_prop - - - rw [Subgroup.coe_mul_of_right_le_normalizer_left _ _ - (Subgroup.le_normalizer_of_conj_mem map_N'_invariant_gamma_one)] at g_prop - rw [Set.mem_mul] at g_prop - obtain ⟨b, hb, a, ha, g_eq⟩ := g_prop - simp at ha - rw [Subgroup.mem_closure_singleton] at ha - obtain ⟨z, hz⟩ := ha - use z % α - refine ⟨?_, ?_⟩ - . - have foo := Int.emod_lt_abs z (b := α) (by grind) - rw [lt_abs] at foo - refine ⟨?_, ?_⟩ - . - have bar := Int.emod_nonneg z (b := α) (by simpa using alpha_nonzero) - grind - . grind - . - rw [Set.mem_smul_set] - use ⟨(Additive.ofMul b) + (((α : ℤ) * (z / (α : ℤ))) • γ), ?_⟩ - . - refine ⟨?_, ?_⟩ - . - simp - rw [Subgroup.mem_subgroupOf] - simp_rw [Set.insert_eq, Subgroup.closure_union] - rw [← SetLike.mem_coe] - rw [sup_comm] - rw [Subgroup.coe_mul_of_right_le_normalizer_left _ _ (Subgroup.le_normalizer_of_conj_mem (by - simp_rw [← MonoidHom.map_closure] - apply map_N'_invariant_gamma - ))] - apply Set.mul_mem_mul - . - simp - rw [← MonoidHom.map_closure] - exact hb - . - simp - rw [Subgroup.mem_closure_singleton] - use (z / (α : ℤ)) - conv => - lhs - arg 1 - equals toMul γ ^ (α : ℤ) => - simp - - rw [← zpow_mul] - . - simp - rw [Subtype.ext_iff] - simp - rw [← g_eq, ←hz] - nth_rw 3 [← Int.mul_ediv_add_emod (a := z) (b := α)] - rw [← toMul_zsmul] - conv => - lhs - equals (ofMul b) + ((↑α * (z / ↑α)) • γ) + ((z % ↑α) • γ) => - rfl - - - rw [add_zsmul] - rw [add_assoc] - rfl - . - simp_rw [Set.insert_eq, Subgroup.closure_union] - rw [sup_comm] - rw [← SetLike.mem_coe] - - rw [Subgroup.coe_mul_of_right_le_normalizer_left _ _ (Subgroup.le_normalizer_of_conj_mem (by - simp_rw [← MonoidHom.map_closure] - apply map_N'_invariant_gamma_one - ))] - apply Set.mul_mem_mul - . - simp - rw [← MonoidHom.map_closure] - exact hb - . - simp [Subgroup.mem_closure_singleton] - . - obtain ⟨s, s_compl, s_cosets⟩ := Subgroup.exists_leftTransversal_of_FiniteIndex (D := N') (H := ⊤) (by simp) - simp at s_cosets - - rw [← ne_eq] - rw [← Subgroup.finiteIndex_iff] - apply Subgroup.finiteIndex_of_leftCoset_cover_const (s := s) (g := fun g => g.val.val.toMul) - simp_rw [Set.insert_eq, Subgroup.closure_union] - rename_bvar i → g - - - conv => - arg 1 - arg 1 - intro i - arg 1 - intro hi - rw [sup_comm] - rw [Subgroup.coe_mul_of_right_le_normalizer_left _ _ (Subgroup.le_normalizer_of_conj_mem (by - intro gamma_pow h_gamma_pow n hn - simp_rw [← MonoidHom.map_closure] at hn - simp_rw [← MonoidHom.map_closure] - apply map_N'_invariant_gamma_one _ h_gamma_pow _ hn - ))] - rw [set_smul_eq_mul] - rw [← mul_assoc] - rw [← set_smul_eq_mul] - - - simp_rw [← Set.iUnion_mul] - conv => - arg 1 - arg 1 - equals Additive.toMul '' data.φ.ker => - apply_fun (fun s => Additive.toMul '' (Subtype.val '' s)) at s_cosets - conv at s_cosets => - rhs - equals Additive.toMul '' data.φ.ker => - ext a - simp - rw [← s_cosets] - conv => - arg 1 - arg 1 - intro i - arg 1 - intro hi - arg 2 - - simp_rw [← MonoidHom.map_closure] - - simp only [Set.image_image] - first - | erw [Set.image_iUnion₂] - | rw [Set.image_iUnion₂] - | simp only [Set.image_iUnion] - apply Set.iUnion_congr - intro i - apply Set.iUnion_congr - intro hi - ext z - simp only [closure_eq, coe_map] - rw [Set.mem_smul_set] - rw [Set.mem_image] - refine ⟨?_, ?_⟩ - . - intro hy - obtain ⟨a, ha⟩ := hy - have foo := ha.1 - rw [Set.mem_image] at foo - obtain ⟨b, b_mem, a_eq_b⟩ := foo - have N'_gen := N'_fg.choose_spec - rw [N'_gen] at b_mem - refine ⟨(↑i : Multiplicative ↥data.φ.ker) • b, Set.smul_mem_smul_set b_mem, ?_⟩ - rw [← ha.2, ← a_eq_b] - rfl - . - intro hx - obtain ⟨x, hx, x_eq⟩ := hx - erw [Set.mem_smul_set] at hx - obtain ⟨n, hn, x_eq_n⟩ := hx - refine ⟨new_N'_map n, ?_, ?_⟩ - . - rw [Set.mem_image] - have N'_gen := N'_fg.choose_spec - rw [← N'_gen] at hn - exact ⟨n, hn, rfl⟩ - . rw [← x_eq, ← x_eq_n] - rfl - - - conv => - arg 1 - lhs - equals ↑data.φ.ker.toSubgroup' => - ext a - simp - - rw [← Subgroup.coe_mul_of_right_le_normalizer_left _ _] - . - simp - rw [eq_top_iff] - have ker_gen := e_i_and_gamma_generates_G data.φ γ hγ - have foo := new_generates.generates - simp at foo - rw [← foo, ← ker_gen] - simp_rw [Subgroup.closure_union] - conv => - lhs - arg 1 - equals Subgroup.closure {γ.toMul} => - simp [Subgroup.closure_union] - conv => - lhs - arg 1 - equals {γ.toMul, γ.toMul⁻¹} => rfl - rw [Set.insert_eq] - rw [Subgroup.closure_union] - simp - - simp_rw [← Subgroup.closure_union] - rw [Subgroup.closure_le] - rw [Set.union_subset_iff] - refine ⟨?_, ?_⟩ - . - intro a ha - simp at ha - simp - apply Subgroup.mem_sup_right - simp [ha] - . - intro a ha - apply Subgroup.mem_sup_left - simp - simp at ha - obtain ⟨p, hp, a_eq⟩ := ha - simp [e_i_with_gamma] at a_eq - rw [← a_eq] - conv => - arg 1 - arg 2 - equals (ofMul p) + -((data.φ (ofMul p)) • γ) => - rfl - - - simp [hγ] - . - apply Subgroup.le_normalizer_of_conj_mem - intro b hb a ha - rw [Subgroup.mem_closure_singleton] at hb - obtain ⟨n, b_eq⟩ := hb - simp [← b_eq] - simp at ha - exact ha - . have foo := data.finite_index - rw [Subgroup.finiteIndex_iff] at foo - exact foo -- Decompose list of {e_k, γ}: @@ -988,8 +980,6 @@ lemma theorem_3_1.{u} [hGS: Generates.{u}] (data: Theorem3_1_Input G) (d: ℕ) ( -- * If the head is γ^n e_i for some n (collecting up adjacent γ), then choose γ_n,i = γ^n * e_i * γ^(-n) -- * If the remaining list is just γ^n, then n must be 0 (since we maintained the invariant) -#print axioms three_two_gamma_m_generates -#print axioms three_two_ker_fg -- NOTE: from https://www.numdam.org/item/PMIHES_1981__53__53_0.pdf -- it looks like our definition of 'polynomial growth' should use `S ∪ S⁻¹` @@ -1023,7 +1013,5 @@ theorem main_gromov_theorem (n: ℕ) (h: HasPolynomialGrowthD S n): Group.IsVirt have prev := @ih Q_generates (n - 1) Q_poly (by omega) exact prev -#print sorries main_gromov_theorem -#print axioms main_gromov_theorem end GeneratesNS diff --git a/Gromov/GrowthZero.lean b/Gromov/GrowthZero.lean index 95e1ac0..95a2c15 100644 --- a/Gromov/GrowthZero.lean +++ b/Gromov/GrowthZero.lean @@ -11,9 +11,6 @@ public import Gromov.ThreeTwoGenerates public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false open Subgroup open scoped Finset @@ -28,9 +25,7 @@ include hGS open scoped RealInnerProductSpace -set_option synthInstance.maxHeartbeats 500000 -set_option maxHeartbeats 1000000 open MeasureTheory @@ -48,13 +43,12 @@ structure GeneratesWithParam (G: Type*) [Group G] [DecidableEq G] where has_inv: ∀ g ∈ S, g⁻¹ ∈ S g_infinite: Infinite G +omit hGS in lemma one_mem_S {G: Type*} [Group G] [DecidableEq G] {n: ℕ} (data: Theorem3_1_Input G) (hGS: GeneratesWithParam data.G') (γ: Additive data.G') (hγ: data.φ γ = 1): 0 ∈ S_n_ker_phi hGS.S data.φ γ hγ n := by simp [S_n_ker_phi] --- The generating set of `ker φ` used below, shared between the `new_g_growth` --- hypothesis and the `S` field so that `g_growth := new_g_growth` is definitionally --- trivial (avoids an expensive `whnf` on the two separately-elaborated `Finset`s). +-- A symmetric generating set for the kernel of the homomorphism to ℤ. omit hGS in @[expose] noncomputable def ker_S {G: Type*} [Group G] [DecidableEq G] (data: Theorem3_1_Input G) @@ -63,9 +57,8 @@ noncomputable def ker_S {G: Type*} [Group G] [DecidableEq G] (data: Theorem3_1_I (Finset.image Additive.toMul (S_n_ker_phi hGS.S data.φ γ hγ n)) ∪ (Finset.image Additive.toMul ((S_n_ker_phi hGS.S data.φ γ hγ n)))⁻¹ --- TODO - figure out how to make this a 'let' without adding it to typeclass search omit hGS in -@[expose] +@[expose, instance_reducible] noncomputable def ker_generates {n: ℕ} {G: Type*} [Group G] [DecidableEq G] (data: Theorem3_1_Input G) (hGS: GeneratesWithParam data.G') (γ: data.G') (hγ: data.φ γ = 1) (ker_infinite: Infinite (Multiplicative data.φ.ker)) (ker_generates: AddSubgroup.closure (Additive.ofMul '' (three_two_S_n hGS.S data.φ γ (n))) = data.φ.ker) @@ -104,13 +97,9 @@ noncomputable def ker_generates {n: ℕ} {G: Type*} [Group G] [DecidableEq G] (d simp at foo unfold S_n_ker_phi simp - first - | erw [Finset.coe_insert, Set.image_insert_eq, toMul_zero, Subgroup.closure_insert_one] - | rw [Finset.coe_insert, Set.image_insert_eq, toMul_zero, Subgroup.closure_insert_one] - | simp only [Finset.coe_insert, Set.image_insert_eq, toMul_zero, Subgroup.closure_insert_one] rw [← Subgroup.mem_map_iff_mem (f := f)] - . - simp only [f, Subgroup.subtype_apply] + · + simp only [f] rw [MonoidHom.map_closure] simp conv => @@ -131,7 +120,7 @@ noncomputable def ker_generates {n: ℕ} {G: Type*} [Group G] [DecidableEq G] (d have hbk : b ∈ three_two_S_n hGS.S data.φ γ n := by simpa using hb exact ⟨_, ⟨_, ⟨⟨b, hbk⟩, rfl⟩, rfl⟩, rfl⟩ exact foo - . simp [f] + · simp [f] intro x y hxy simpa using hxy simp @@ -140,7 +129,6 @@ noncomputable def ker_generates {n: ℕ} {G: Type*} [Group G] [DecidableEq G] (d rw [Finset.mem_image] use 0 simp - -- TODO - figure out wht 'apply one_mem_S' is slow exact one_mem_S data hGS γ hγ has_inv := by @@ -156,6 +144,231 @@ noncomputable def ker_generates {n: ℕ} {G: Type*} [Group G] [DecidableEq G] (d } +private lemma kernel_thickening_card (n r : ℕ) (φ : (Additive G) →+ ℤ) (γ : G) (hγ : φ γ = 1) : + let mul_by_i := fun (g : G) (i : Fin r) => g * (γ ^ i.val); + #((((((S_n_ker_phi S φ γ hγ n) ∪ (-(S_n_ker_phi S φ γ hγ n))).image Multiplicative.ofAdd) ^ r).image ofMul).biUnion (fun a => Finset.image (mul_by_i a.val) Finset.univ)) = r * #(r • ((S_n_ker_phi S φ γ hγ n) ∪ -((S_n_ker_phi S φ γ hγ n)))) := by + dsimp only + let mul_by_i := fun (g: G) (i: Fin r) => g * (γ ^ i.val) + change #((((((S_n_ker_phi S φ γ hγ n) ∪ (-(S_n_ker_phi S φ γ hγ n))).image Multiplicative.ofAdd) ^ r).image ofMul).biUnion (fun a => Finset.image (mul_by_i a.val) Finset.univ)) = r * #(r • ((S_n_ker_phi S φ γ hγ n) ∪ -((S_n_ker_phi S φ γ hγ n)))) + have new_phi_gamma: φ (Additive.ofMul γ) = 1 := hγ + have card_mul_range (g: G): #(Finset.image (mul_by_i g) Finset.univ) = r := by + rw [Finset.card_image_of_injOn] + · simp + · + + intro j _ k _ mul_eq + simp [mul_by_i] at mul_eq + apply_fun φ ∘ (Additive.ofMul) at mul_eq + simp [new_phi_gamma] at mul_eq + rw [Fin.ext_iff] + exact mul_eq + + + rw [Finset.card_biUnion] + · + simp_rw [card_mul_range] + simp + rw [mul_comm] + conv => + lhs + arg 2 + arg 1 + equals r • ((S_n_ker_phi S φ γ hγ n) ∪ -(S_n_ker_phi S φ γ hγ n)) => + ext a + rw [Finset.mem_image] + simp_rw [Finset.mem_pow] + refine Iff.trans ?_ Finset.mem_nsmul.symm + refine ⟨?_, ?_⟩ + · intro h + obtain ⟨b, ⟨f, hf⟩, b_eq_a⟩ := h + use (fun i => ⟨(f i).val, (by + have f_prop := (f i).property + rw [Finset.mem_image] at f_prop + obtain ⟨g, g_mem, hg⟩ := f_prop + rw [← hg] + exact g_mem + )⟩) + rw [← b_eq_a] + rw [← hf] + rfl + · intro h + obtain ⟨f, hf⟩ := h + use a + refine ⟨?_, rfl⟩ + use (fun i => ⟨(f i).val, (by + have f_prop := (f i).property + rw [Finset.mem_image] + use (f i).val + refine ⟨f_prop, ?_⟩ + rfl + )⟩) + rw [← hf] + rfl + + + · + intro a ha b hb hab x h_first h_second + simp at h_first + simp at h_second + simp + + by_contra! + obtain ⟨p, hp⟩ := this + have orig_h_first := h_first hp + have orig_h_second := h_second hp + specialize h_first hp + specialize h_second hp + + simp at h_first + simp at h_second + + obtain ⟨y, hy⟩ := h_first + obtain ⟨z, hz⟩ := h_second + + have orig_hy := hy + have orig_hz := hz + + rw [← hz] at hy + simp [mul_by_i] at hy + apply_fun φ ∘ (Additive.ofMul) at hy + simp [new_phi_gamma] at hy + + have a_ker: a.val ∈ φ.ker := by + simp + + have b_ker: b.val ∈ φ.ker := by + simp + + rw [AddMonoidHom.mem_ker] at a_ker + rw [AddMonoidHom.mem_ker] at b_ker + simp [ofMul] at hy + simp [a_ker, b_ker] at hy + + rw [← Fin.ext_iff] at hy + rw [hy] at orig_hy + rw [← orig_hy] at orig_hz + simp [mul_by_i] at orig_hz + rw [eq_comm] at orig_hz + contradiction + + + +private lemma kernel_thickening_bound (n r : ℕ) (φ : (Additive G) →+ ℤ) (γ : G) (hγ : φ γ = 1) : + let mul_by_i := fun (g : G) (i : Fin r) => g * (γ ^ i.val); + #((((((S_n_ker_phi S φ γ hγ n) ∪ -(S_n_ker_phi S φ γ hγ n)).image Multiplicative.ofAdd) ^ r).image ofMul).biUnion (fun a => Finset.image (mul_by_i a.val) Finset.univ)) ≤ #(((three_two_S_n S φ γ n) ∪ ((three_two_S_n S φ γ n)⁻¹) ∪ {γ} ∪ {1}) ^ (2 * r)) := by + dsimp only + let mul_by_i := fun (g : G) (i : Fin r) => g * (γ ^ i.val) + change #((((((S_n_ker_phi S φ γ hγ n) ∪ -(S_n_ker_phi S φ γ hγ n)).image Multiplicative.ofAdd) ^ r).image ofMul).biUnion (fun a => Finset.image (mul_by_i a.val) Finset.univ)) ≤ #(((three_two_S_n S φ γ n) ∪ ((three_two_S_n S φ γ n)⁻¹) ∪ {γ} ∪ {1}) ^ (2 * r)) + + grw [Finset.card_le_card] + intro a ha + rw [Finset.mem_biUnion] at ha + obtain ⟨s, s_mem, a_mem⟩ := ha + rw [Finset.mem_image] at a_mem + obtain ⟨k, _, hk⟩ := a_mem + simp [mul_by_i] at hk + rw [← hk] + rw [two_mul] + rw [pow_add] + apply Finset.mul_mem_mul + · + unfold S_n_ker_phi at s_mem + + rw [Finset.mem_image] at s_mem + obtain ⟨z, z_mem, hz⟩ := s_mem + rw [← hz] + + rw [Finset.mem_pow] at z_mem + obtain ⟨f, hf⟩ := z_mem + rw [Finset.mem_pow] + use (fun i => ⟨(f i).val.val, (by + have f_prop := (f i).property + rw [Finset.mem_image] at f_prop + obtain ⟨g, g_mem, hg⟩ := f_prop + rw [← hg] + simp at g_mem + cases g_mem + · + rename_i g_eq_zero + apply Finset.mem_union_right + rw [Finset.mem_singleton, g_eq_zero] + rfl + · rename_i g_eq_nonzero + cases g_eq_nonzero + · rename_i left + obtain ⟨z, z_mem, hz⟩ := left + rw [← hz] + apply Finset.mem_union_left + apply Finset.mem_union_left + apply Finset.mem_union_left + exact z_mem + · + rename_i right + obtain ⟨z, z_mem, hz⟩ := right + apply Finset.mem_union_left + apply Finset.mem_union_left + apply Finset.mem_union_right + simp + conv => + arg 2 + equals (-g).val => + rfl + rw [← hz] + exact z_mem + )⟩) + rw [← hf, ofMul_list_prod, List.map_ofFn] + erw [AddSubmonoidClass.coe_list_sum, List.map_ofFn] + rfl + · + + + have gamma_r_subset: ({γ, 1} : Finset G)^r ⊆ ((three_two_S_n S φ γ n) ∪ ((three_two_S_n S φ γ n)⁻¹) ∪ {γ} ∪ {1})^r := by + apply Finset.pow_subset_pow + · grind + · grind + · simp + + have gamma_subset: ({γ, 1} : Finset G)^k.val ⊆ ({γ, 1} : Finset G)^r := by + apply Finset.pow_subset_pow + · simp + · simp + · simp + + + have gamma_mem_self: γ^k.val ∈ ({γ, 1} : Finset G)^k.val := by + apply Finset.pow_mem_pow + simp + + grind + + + +omit hGS in +private lemma multiplicative_symm_pow {A : Type*} [AddGroup A] [DecidableEq A] + (s : Finset A) (r : ℕ) : + ((show Finset (Multiplicative A) from s) ∪ (show Finset (Multiplicative A) from s)⁻¹)^r = + (show Finset (Multiplicative A) from r • (s ∪ -s)) := by + ext a + rw [Finset.mem_pow] + refine Iff.trans ?_ (Finset.mem_nsmul (α := A) (s := s ∪ -s) (a := a.toAdd) (n := r)).symm + constructor + · rintro ⟨f, hf⟩ + exact ⟨f, hf⟩ + · rintro ⟨f, hf⟩ + exact ⟨f, hf⟩ + +omit hGS in +private lemma cancel_growth_factor {N r b d : ℕ} (hr : 0 < r) (hd : 1 ≤ d) + (h : r * N ≤ b * (2 * r)^d) : N ≤ (b * 2^d) * r^(d-1) := by + have hp : r^d = r * r^(d-1) := by + calc + r^d = r^((d-1)+1) := by rw [Nat.sub_add_cancel hd] + _ = r * r^(d-1) := by rw [pow_succ, mul_comm] + apply Nat.le_of_mul_le_mul_left (c := r) ?_ hr + calc + r * N ≤ b * (2*r)^d := h + _ = r * ((b * 2^d) * r^(d-1)) := by rw [mul_pow, hp]; ac_rfl + lemma three_two_kernel_poly_growth (d: ℕ) (hd: d >= 1) (n: ℕ) (hG: HasPolynomialGrowthD S d ) (φ: (Additive G) →+ ℤ) (γ: G) (hγ : φ γ = 1) : HasPolynomialGrowthD (G := Multiplicative φ.ker) (d - 1) (S := (S_n_ker_phi S φ γ hγ n) ∪ (S_n_ker_phi S φ γ hγ n)⁻¹) := by @@ -165,7 +378,7 @@ lemma three_two_kernel_poly_growth (d: ℕ) (hd: d >= 1) (n: ℕ) (hG: HasPolyn obtain ⟨a, ha⟩ := hG by_cases a_eq_zero: a = 0 - . + · simp [a_eq_zero] at ha specialize ha 1 (by simp) simp at ha @@ -186,236 +399,16 @@ lemma three_two_kernel_poly_growth (d: ℕ) (hd: d >= 1) (n: ℕ) (hG: HasPolyn specialize ker_poly (2 * r) (by omega) - let mul_by_i := fun (g: G) (i: Fin r) => g * (γ ^ i.val) - have new_phi_gamma: φ (Additive.ofMul γ) = 1 := hγ - have card_mul_range (g: G): #(Finset.image (mul_by_i g) Finset.univ) = r := by - rw [Finset.card_image_of_injOn] - . simp - . - - intro j _ k _ mul_eq - simp [mul_by_i] at mul_eq - apply_fun φ ∘ (Additive.ofMul) at mul_eq - simp [new_phi_gamma] at mul_eq - rw [Fin.ext_iff] - exact mul_eq - - have card_union: #((((((S_n_ker_phi S φ γ hγ n) ∪ (-(S_n_ker_phi S φ γ hγ n))).image Multiplicative.ofAdd) ^ r).image ofMul).biUnion (fun a => Finset.image (mul_by_i a.val) Finset.univ)) = r * #(r • ((S_n_ker_phi S φ γ hγ n) ∪ -((S_n_ker_phi S φ γ hγ n)))) := by - rw [Finset.card_biUnion] - . - simp_rw [card_mul_range] - simp - rw [mul_comm] - conv => - lhs - arg 2 - arg 1 - equals r • ((S_n_ker_phi S φ γ hγ n) ∪ -(S_n_ker_phi S φ γ hγ n)) => - ext a - rw [Finset.mem_image] - simp_rw [Finset.mem_pow] - refine Iff.trans ?_ Finset.mem_nsmul.symm - refine ⟨?_, ?_⟩ - . intro h - obtain ⟨b, ⟨f, hf⟩, b_eq_a⟩ := h - use (fun i => ⟨(f i).val, (by - have f_prop := (f i).property - rw [Finset.mem_image] at f_prop - obtain ⟨g, g_mem, hg⟩ := f_prop - rw [← hg] - exact g_mem - )⟩) - rw [← b_eq_a] - rw [← hf] - rfl - . intro h - obtain ⟨f, hf⟩ := h - use a - refine ⟨?_, rfl⟩ - use (fun i => ⟨(f i).val, (by - have f_prop := (f i).property - rw [Finset.mem_image] - use (f i).val - refine ⟨f_prop, ?_⟩ - rfl - )⟩) - rw [← hf] - rfl - - - . - intro a ha b hb hab x h_first h_second - simp at h_first - simp at h_second - simp - - by_contra! - obtain ⟨p, hp⟩ := this - have orig_h_first := h_first hp - have orig_h_second := h_second hp - specialize h_first hp - specialize h_second hp - - simp at h_first - simp at h_second - - obtain ⟨y, hy⟩ := h_first - obtain ⟨z, hz⟩ := h_second - - have orig_hy := hy - have orig_hz := hz - - rw [← hz] at hy - simp [mul_by_i] at hy - apply_fun φ ∘ (Additive.ofMul) at hy - simp [new_phi_gamma] at hy - - have a_ker: a.val ∈ φ.ker := by - simp - - have b_ker: b.val ∈ φ.ker := by - simp - - rw [AddMonoidHom.mem_ker] at a_ker - rw [AddMonoidHom.mem_ker] at b_ker - simp [ofMul] at hy - simp [a_ker, b_ker] at hy - - rw [← Fin.ext_iff] at hy - rw [hy] at orig_hy - rw [← orig_hy] at orig_hz - simp [mul_by_i] at orig_hz - rw [eq_comm] at orig_hz - contradiction - - - have card_union_le: #((((((S_n_ker_phi S φ γ hγ n) ∪ -(S_n_ker_phi S φ γ hγ n)).image Multiplicative.ofAdd) ^ r).image ofMul).biUnion (fun a => Finset.image (mul_by_i a.val) Finset.univ)) ≤ #(((three_two_S_n S φ γ n) ∪ ((three_two_S_n S φ γ n)⁻¹) ∪ {γ} ∪ {1}) ^ (2 * r)) := by - grw [Finset.card_le_card] - intro a ha - rw [Finset.mem_biUnion] at ha - obtain ⟨s, s_mem, a_mem⟩ := ha - rw [Finset.mem_image] at a_mem - obtain ⟨k, _, hk⟩ := a_mem - simp [mul_by_i] at hk - rw [← hk] - rw [two_mul] - rw [pow_add] - apply Finset.mul_mem_mul - . - unfold S_n_ker_phi at s_mem - - rw [Finset.mem_image] at s_mem - obtain ⟨z, z_mem, hz⟩ := s_mem - rw [← hz] - - rw [Finset.mem_pow] at z_mem - obtain ⟨f, hf⟩ := z_mem - rw [Finset.mem_pow] - use (fun i => ⟨(f i).val.val, (by - have f_prop := (f i).property - rw [Finset.mem_image] at f_prop - obtain ⟨g, g_mem, hg⟩ := f_prop - rw [← hg] - simp at g_mem - cases g_mem - . - rename_i g_eq_zero - apply Finset.mem_union_right - rw [Finset.mem_singleton, g_eq_zero] - first | rfl | simp - . rename_i g_eq_nonzero - cases g_eq_nonzero - . rename_i left - obtain ⟨z, z_mem, hz⟩ := left - rw [← hz] - apply Finset.mem_union_left - apply Finset.mem_union_left - apply Finset.mem_union_left - exact z_mem - . - rename_i right - obtain ⟨z, z_mem, hz⟩ := right - apply Finset.mem_union_left - apply Finset.mem_union_left - apply Finset.mem_union_right - simp - conv => - arg 2 - equals (-g).val => - rfl - rw [← hz] - exact z_mem - )⟩) - rw [← hf, ofMul_list_prod, List.map_ofFn] - first - | (erw [AddSubmonoidClass.coe_list_sum, List.map_ofFn]; rfl) - | (rw [AddSubmonoidClass.coe_list_sum, List.map_ofFn]; rfl) - | (simp only [AddSubmonoidClass.coe_list_sum, List.map_ofFn]; rfl) - . - - - have gamma_r_subset: ({γ, 1} : Finset G)^r ⊆ ((three_two_S_n S φ γ n) ∪ ((three_two_S_n S φ γ n)⁻¹) ∪ {γ} ∪ {1})^r := by - apply Finset.pow_subset_pow - . grind - . grind - . simp - - have gamma_subset: ({γ, 1} : Finset G)^k.val ⊆ ({γ, 1} : Finset G)^r := by - apply Finset.pow_subset_pow - . simp - . simp - . simp - - - have gamma_mem_self: γ^k.val ∈ ({γ, 1} : Finset G)^k.val := by - apply Finset.pow_mem_pow - simp - - grind - + let mul_by_i := fun (g : G) (i : Fin r) => g * (γ ^ i.val) + have card_union := kernel_thickening_card n r φ γ hγ + have card_union_le := kernel_thickening_bound n r φ γ hγ + dsimp only at card_union card_union_le rw [card_union] at card_union_le - grw [ker_poly] at card_union_le - rw [mul_pow] at card_union_le - rw [← mul_assoc] at card_union_le - rw [mul_comm] at card_union_le - rw [← Nat.le_div_iff_mul_le] at card_union_le - . - rw [Nat.mul_div_assoc] at card_union_le - . - nth_rw 3 [← pow_one (a := r)] at card_union_le - rw [Nat.pow_div] at card_union_le - . - -- TODO - get rid of this obnoxious Additive/Multiplicative defeq abuse - conv => - lhs - arg 1 - equals r • ((S_n_ker_phi S φ γ hγ n) ∪ -(S_n_ker_phi S φ γ hγ n)) => - ext a - rw [Finset.mem_pow] - -- TODO - why do we need explicit args here - refine Iff.trans ?_ Finset.mem_nsmul.symm - refine ⟨?_, ?_⟩ - . - intro hf - obtain ⟨f, hf⟩ := hf - use f - exact hf - . intro hf - obtain ⟨f, hf⟩ := hf - use f - exact hf - exact card_union_le - . omega - . omega - - . - nth_rw 1 [← pow_one (a := r)] - apply Nat.pow_dvd_pow - omega - . omega - -#print axioms three_two_kernel_poly_growth + have hbound := cancel_growth_factor (by omega : 0 < r) hd (card_union_le.trans ker_poly) + rw [multiplicative_symm_pow] + exact hbound + omit hGS in @@ -436,7 +429,6 @@ lemma finite_of_growth_zero (h: HasPolynomialGrowthD S 0): Finite G := by have S_closure := hGS.generates let pow_cards := Set.range (fun (n: ℕ) => #(S ^ n)) - -- TODO - this can probably be much simpler have pow_cards_bounded: ∃ y, ∀ n ∈ pow_cards, n ≤ y := by use a intro n hn @@ -445,9 +437,8 @@ lemma finite_of_growth_zero (h: HasPolynomialGrowthD S 0): Finite G := by rw [← hy] by_cases y_eq_zero: y = 0 - . simp [y_eq_zero] + · simp [y_eq_zero] - -- TODO - deduplicate this have a_ne_zero: a ≠ 0 := by by_contra! rw [this] at ha @@ -458,20 +449,20 @@ lemma finite_of_growth_zero (h: HasPolynomialGrowthD S 0): Finite G := by simp at one_mem omega - . by_cases y_eq_one: y = 1 - . + · by_cases y_eq_one: y = 1 + · simp [y_eq_one] have card_mono := Finset.card_pow_mono (s := S) (m := 1) (n := 2) (by simp) (by simp) have card_two_le := ha 2 (by simp) simp at card_mono linarith - . + · exact ha y (by omega) classical have max_card_mem := Nat.sSup_mem (s := pow_cards) ?_ ?_ - . simp [pow_cards] at max_card_mem + · simp [pow_cards] at max_card_mem obtain ⟨y, hy⟩ := max_card_mem @@ -483,7 +474,7 @@ lemma finite_of_growth_zero (h: HasPolynomialGrowthD S 0): Finite G := by exact Generates.one_mem | mem x hx => by_cases y_eq_zero: y = 0 - . + · rw [y_eq_zero] rw [y_eq_zero] at hy simp at hy @@ -492,27 +483,27 @@ lemma finite_of_growth_zero (h: HasPolynomialGrowthD S 0): Finite G := by have find_le := Nat.find_spec pow_cards_bounded rw [← y_eq] at find_le have S_one_le := find_le #(S) ?_ - . + · simp [pow_cards] at S_one_le rw [← hy] at S_one_le rw [Finset.card_le_one] at S_one_le have one_mem: 1 ∈ S := by exact Generates.one_mem have x_eq := S_one_le 1 one_mem x hx apply x_eq.symm - . simp [pow_cards] + · simp [pow_cards] use 1 simp - . + · have pow_mono := Finset.pow_subset_pow_right (s := S) (Generates.one_mem) (n := y) (m := 1) (by omega) simp at pow_mono apply pow_mono hx | mul a b a_mem_closure b_mem_closure a_mem_pow b_mem_pow => by_cases y_eq_zero: y = 0 - . + · simp [y_eq_zero] simp [y_eq_zero] at a_mem_pow b_mem_pow simp [a_mem_pow, b_mem_pow] - . + · by_contra! have a_b_mem_two: a * b ∈ (S ^ (y * 2)) := by have mem_mul := Finset.mul_mem_mul a_mem_pow b_mem_pow @@ -535,10 +526,10 @@ lemma finite_of_growth_zero (h: HasPolynomialGrowthD S 0): Finite G := by have find_le := Nat.find_spec pow_cards_bounded rw [← y_eq] at find_le have reverse_le := find_le #(S ^ (y * 2)) ?_ - . + · simp [pow_cards] at reverse_le linarith - . simp [pow_cards] + · simp [pow_cards] | inv a ha a_mem_pow => rw [← Finset.mem_inv'] rw [← inv_pow] @@ -559,11 +550,11 @@ lemma finite_of_growth_zero (h: HasPolynomialGrowthD S 0): Finite G := by rw [← S_closure] ext a refine ⟨?_, ?_⟩ - . intro ha + · intro ha simp at ha rw [← Finset.coe_pow] exact all_closure_mem a ha - . intro ha + · intro ha simp exact mem_closure a @@ -571,10 +562,10 @@ lemma finite_of_growth_zero (h: HasPolynomialGrowthD S 0): Finite G := by rw [← Finset.coe_pow] exact Finset.finite_toSet (S ^ y) exact G_finite - . + · simp [pow_cards] apply Set.range_nonempty - . + · rw [bddAbove_def] exact pow_cards_bounded @@ -599,6 +590,5 @@ lemma growth_exponent_pos {d : ℕ} (h: HasPolynomialGrowthD S d): 0 < d := by have := hGS.g_infinite exact (not_finite G) --- TODO - add an explicit top-level universe parameter to avoid this 'omit hGS' hack end GeneratesNS diff --git a/Gromov/Harmonic.lean b/Gromov/Harmonic.lean index 939cd59..b28dc07 100644 --- a/Gromov/Harmonic.lean +++ b/Gromov/Harmonic.lean @@ -8,13 +8,10 @@ public import Gromov.Harmonic.CaseOne `nontrivial_harmonic_case_two` and the main result `exists_nontrivial_harmonic`. -Root of the `Gromov.Harmonic` hierarchy. -/ public section -set_option linter.style.cdot false -set_option linter.style.whitespace false attribute [local implicit_reducible] Additive namespace GeneratesNS @@ -32,12 +29,10 @@ open MeasureTheory open scoped RealInnerProductSpace -set_option maxHeartbeats 2000000 in lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun n: ℕ => MeasureTheory.eLpNorm (f_n n - (Conv (f_n n) (delta s.val))) 1 MeasureTheory.volume) Filter.atTop (nhds 0))): ∃ F: LipschitzH , ∀ z: ℝ, F ≠ ConstLipschitzH z := by obtain ⟨s, hs⟩ := f_n_limit let H_n := fun n g => if ((f_n n g⁻¹) - (Conv (f_n n) (delta s.val)) g⁻¹) ≠ 0 then ((f_n n g⁻¹) - (Conv (f_n n) (delta s.val)) g⁻¹) / |((f_n n g⁻¹) - (Conv (f_n n) (delta s.val)) g⁻¹)| else 1 - -- TODO - why can't we write '∞' here have H_n_norm: ∀ n: ℕ, MeasureTheory.eLpNorm (H_n n) (p := ⊤) MeasureTheory.volume = 1 := by intro n simp [H_n] @@ -49,24 +44,24 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun simp [H_n] intro g split_ifs - . simp - . + · simp + · rename_i foo by_cases val_pos: 0 ≤ ((f_n n g⁻¹) - (Conv (f_n n) (delta s.val)) g⁻¹) - . + · rw [abs_of_nonneg val_pos] rw [div_self] - . simp - . exact foo - . + · simp + · exact foo + · rw [abs_of_neg] - . + · rw [div_neg_self] - . + · simp - . exact foo - . linarith + · exact foo + · linarith unfold H_n at h_norm_one simp at h_norm_one @@ -78,21 +73,21 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun simp [H_n] simp [f_conv_delta] split_ifs - . linarith - . + · linarith + · rename_i diff_zero by_cases val_pos: 0 ≤ f_n n g - f_n n ((↑s)⁻¹ * g) - . + · rw [abs_of_nonneg val_pos] rw [div_self] - . linarith - . assumption - . + · linarith + · assumption + · rw [abs_of_neg] - . rw [div_neg_self] - . linarith - . assumption - . + · rw [div_neg_self] + · linarith + · assumption + · simpa using val_pos have fn_sub_norm: ∀ n: ℕ, eLpNorm (f_n n - (Conv (f_n n) (delta s.val))) 1 = ENNReal.ofReal |((Conv (H_n n) (f_n n)) 1) - ((Conv (H_n n) (f_n n)) s⁻¹)| := by @@ -108,26 +103,26 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun equals (H_n n g⁻¹) * (f_n n g - (Conv (f_n n) (delta s.val)) g) => simp [H_n] split_ifs - . + · rename_i diff_eq_zero simp [diff_eq_zero] - . + · rename_i diff_ne_zero by_cases val_pos: 0 ≤ ((f_n n g) - (Conv (f_n n) (delta s.val)) g) - . + · rw [abs_of_nonneg] - . + · rw [div_self] simp apply diff_ne_zero - . exact val_pos - . + · exact val_pos + · rw [abs_of_neg] - . + · rw [div_neg_self] simp exact diff_ne_zero - . + · simpa using val_pos rw [conv_eq_sum (by @@ -138,8 +133,8 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun apply Set.Finite.inter_of_right apply Set.Finite.subset (hs := ?_) (ht := Finset.support_sum _ _) refine Set.Finite.biUnion' ?_ ?_ - . exact Set.toFinite (Membership.mem Finset.univ.val) - . intro m hm + · exact Set.toFinite (Membership.mem Finset.univ.val) + · intro m hm apply mu_conv_finsupp )] @@ -151,8 +146,8 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun apply Set.Finite.inter_of_right apply Set.Finite.subset (hs := ?_) (ht := Finset.support_sum _ _) refine Set.Finite.biUnion' ?_ ?_ - . exact Set.toFinite (Membership.mem Finset.univ.val) - . intro m hm + · exact Set.toFinite (Membership.mem Finset.univ.val) + · intro m hm apply mu_conv_finsupp )] @@ -171,14 +166,14 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun apply Set.Finite.inter_of_right apply Set.Finite.subset (hs := ?_) (ht := Finset.support_sum _ _) refine Set.Finite.biUnion' ?_ ?_ - . exact Set.toFinite (Membership.mem Finset.univ.val) - . + · exact Set.toFinite (Membership.mem Finset.univ.val) + · intro m hm apply Set.Finite.of_injOn (f := fun a => ((Additive.toMul a))⁻¹) (ht := mu_conv_finsupp m) - . + · intro a ha exact ha - . intro a ha b hb + · intro a ha b hb simp ) (by apply summable_of_hasFiniteSupport @@ -190,14 +185,14 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun apply Set.Finite.inter_of_right apply Set.Finite.subset (hs := ?_) (ht := Finset.support_sum _ _) refine Set.Finite.biUnion' ?_ ?_ - . exact Set.toFinite (Membership.mem Finset.univ.val) - . + · exact Set.toFinite (Membership.mem Finset.univ.val) + · intro m hm apply Set.Finite.of_injOn (f := fun a => s.val⁻¹ * ((Additive.toMul a))⁻¹ ) (ht := mu_conv_finsupp m) - . + · intro a ha exact ha - . intro a ha b hb + · intro a ha b hb simp )] simp_rw [mul_sub] @@ -208,25 +203,25 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun simp rw [abs_of_nonneg] rfl - . + · apply tsum_nonneg apply H_n_diff_pos n - . + · simp apply Function.Injective.comp - . exact neg_injective - . exact fun ⦃a₁ a₂⦄ a ↦ a - . + · exact neg_injective + · exact fun ⦃a₁ a₂⦄ a ↦ a + · simp intro g hg use g⁻¹ simp - . + · apply tsum_nonneg apply H_n_diff_pos n - . simp - . apply H_n_diff_pos n - . + · simp + · apply H_n_diff_pos n + · simp_rw [← mul_sub] apply summable_of_hasFiniteSupport change (Function.support _).Finite @@ -235,12 +230,12 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun apply Set.Finite.subset (hs := ?_) (ht := Function.support_sub _ _) simp refine ⟨?_, ?_⟩ - . apply f_n_fin_supp - . + · apply f_n_fin_supp + · apply Set.Finite.of_injOn (f := fun a => s.val⁻¹ * a) (ht := f_n_fin_supp n) - . intro a ha + · intro a ha simpa using ha - . simp + · simp have haar_eq_haar_add : myHaar = myHaarAddOpp := by @@ -267,7 +262,7 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun have conv_laplce_norm (n: ℕ): eLpNorm ((Laplace_b ((Conv (H_n n)) (f_n n)))) ⊤ (μ := volume (α := G)) ≤ eLpNorm (H_n n) ⊤ * (eLpNorm (Laplace_b (f_n n)) 1 (μ := volume (α := G))) := by rw [laplace_conv_eq_laplace_right] - . + · unfold Conv eta_reduce simp only [volume] @@ -288,12 +283,12 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun calc ‖ContinuousLinearMap.mul ℝ ℝ‖ₑ * eLpNorm (H_n n) ⊤ myHaarAddOpp * eLpNorm (Laplace_b (f_n n)) 1 myHaarAddOpp ≤ 1 * eLpNorm (H_n n) ⊤ myHaarAddOpp * eLpNorm (Laplace_b (f_n n)) 1 myHaarAddOpp := by gcongr _ = eLpNorm (H_n n) ⊤ myHaarAddOpp * eLpNorm (Laplace_b (f_n n)) 1 myHaarAddOpp := by rw [one_mul] - . + · apply conv_exists_fin_supp right exact f_n_fin_supp n - . apply f_n_nonneg - . exact f_n_fin_supp n + · apply f_n_nonneg + · exact f_n_fin_supp n let conv_h_n_cont (n: ℕ): C(G, ℝ) := { @@ -311,7 +306,6 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun rw [count_ae_everywhere] at ae_le simp_rw [Real.enorm_eq_ofReal_abs] at ae_le simp_rw [Real.enorm_eq_ofReal_abs] at norm_bound - norm_cast at ae_le simp [volume] at norm_bound rw [my_haar_eq_count] at norm_bound specialize ae_le g @@ -323,8 +317,8 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun simp [LipschitzWith] intro x y by_cases x_eq_y: x = y - . simp [x_eq_y] - . + · simp [x_eq_y] + · norm_cast rw [edist_dist] rw [Real.dist_eq] @@ -333,10 +327,10 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun rhs equals ENNReal.ofReal (2 * (dist x y)) => rw [ENNReal.ofReal_mul] - . simp - . linarith + · simp + · linarith rw [ENNReal.ofReal_le_ofReal_iff] - . + · grw [abs_sub] grw [abs_conv_le_one x] grw [abs_conv_le_one y] @@ -347,7 +341,7 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun exact dist_ne_zero.mpr x_eq_y simp [dist] at dist_ne_zero omega - . simp [dist] + · simp [dist] have compact_closure_f: IsCompact (closure ( (Set.range (fun n => (Conv (H_n n) (f_n n)))))) := by @@ -388,8 +382,8 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun obtain ⟨F, F_mem, seq, seq_mono, tendsto_F⟩ := h_n_pointwise_converge let F_lipschitzh := nontrivial_harmonic_common 2 (eps_seq ∘ seq) (by apply Filter.Tendsto.comp (x := Filter.atTop) (y := Filter.atTop) - . exact StrictMono.tendsto_atTop mono_eps_seq - . exact StrictMono.tendsto_atTop seq_mono + · exact StrictMono.tendsto_atTop mono_eps_seq + · exact StrictMono.tendsto_atTop seq_mono ) F H_n conv_h_n_lipschitz tendsto_F H_n_norm use F_lipschitzh intro z @@ -416,7 +410,6 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun contradiction by_contra! - -- TODO - there must be a cleaner way have app_one_eq: F_lipschitzh 1 = ConstLipschitzH z (1: G) := by rw [this] unfold F_lipschitzh ConstLipschitzH at app_one_eq @@ -427,19 +420,17 @@ lemma nontrivial_harmonic_case_two (f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun unfold F_lipschitzh ConstLipschitzH at app_s_inv_eq simp [DFunLike.coe] at app_s_inv_eq rw [← app_one_eq] at app_s_inv_eq - norm_cast at app_s_inv_eq rw [eq_comm] at app_s_inv_eq simp [nontrivial_harmonic_common] at app_s_inv_eq contradiction -#synth OrderTopology ENNReal -- Theorem 3.6 - a non-constant harmonic function exists on G theorem exists_nontrivial_harmonic: ∃ F: LipschitzH , ∀ z: ℝ, F ≠ ConstLipschitzH z := by by_cases f_n_limit: ∃ s: S, ¬(Filter.Tendsto (fun n: ℕ => MeasureTheory.eLpNorm (f_n n - (Conv (f_n n) (delta s.val))) 1 MeasureTheory.volume) Filter.atTop (nhds 0)) - . exact nontrivial_harmonic_case_two f_n_limit - . + · exact nontrivial_harmonic_case_two f_n_limit + · simp at f_n_limit exact nontrivial_harmonic_case_one (by intro s diff --git a/Gromov/Harmonic/CaseOne.lean b/Gromov/Harmonic/CaseOne.lean index 4363fa4..0b27514 100644 --- a/Gromov/Harmonic/CaseOne.lean +++ b/Gromov/Harmonic/CaseOne.lean @@ -11,8 +11,6 @@ public import Gromov.Harmonic.Proposition318 public section -set_option linter.style.cdot false -set_option linter.style.whitespace false attribute [local implicit_reducible] Additive namespace GeneratesNS @@ -30,8 +28,6 @@ open MeasureTheory open scoped RealInnerProductSpace -set_option maxRecDepth 100000 in -set_option maxHeartbeats 1000000 in lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: ℕ => MeasureTheory.eLpNorm (f_n n - (Conv (f_n n) (delta s.val))) 1 MeasureTheory.volume) Filter.atTop (nhds 0))): ∃ F: LipschitzH , ∀ z: ℝ, F ≠ ConstLipschitzH z := by @@ -85,12 +81,12 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: rw [← conv_smul] rw [ ← smul_conv] rw [conv_assoc_of_lp2] - . + · rw [← conv_add_right] - . + · rw [← ENNReal.ofReal_le_ofReal_iff] - . - rw [ofReal_norm_eq_enorm] + · + rw [ofReal_norm] grw [counting_le_essSup] rw [essSup_eq_elpNorm_top] simp only [volume] @@ -110,10 +106,10 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: exact my_add_haar_eq_count.symm refine le_trans (ENNReal.eLpNorm_top_convolution_le (μ := myHaarAddOpp) (c := 1) (p := 2) (q := 2) (hpq := inferInstance) (by apply AEMeasurable.of_discrete) (by apply AEMeasurable.of_discrete) (by intro a b; simp)) ?_ - . - simp [norm, volume] at H_n_norm + · + simp [volume] at H_n_norm rw [my_add_haar_eq_count] - simp [H_n_norm] + simp have sum_norm := proposition_3_18 (G'_n f_n_limit) have g_inner_laplace := MeasureTheory.L2.inner_def (Laplace (G'_n f_n_limit)) (G'_n f_n_limit) (𝕜 := ℝ) (α := G) @@ -124,11 +120,11 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: rw [inv_mul_eq_div] at g_inner_laplace rw [eq_div_iff_mul_eq] at g_inner_laplace - . + · simp [eLpNorm, eLpNorm'] simp [-AddSubgroupClass.coe_sub, -AddSubgroup.coe_sub, MeasureTheory.Lp.norm_def, eLpNorm, eLpNorm', conv_finsupp_lp2] at g_inner_laplace rw [← ENNReal.ofReal_rpow_of_pos] - . + · have hkey : (∫⁻ (a : Additive G), ‖(H_n (seq n) s : Additive G → ℝ) a‖ₑ ^ 2 ∂Measure.count) ^ (2 : ℝ)⁻¹ = 1 := by have h := H_n_norm n show (∫⁻ (a : G), ‖(H_n (seq n) s : G → ℝ) a‖ₑ ^ 2 ∂Measure.count) ^ (2 : ℝ)⁻¹ = 1 @@ -136,9 +132,8 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: my_haar_eq_count] using h rw [hkey, one_mul] apply ENNReal.rpow_le_rpow - . + · generalize_proofs p_1 p_2 p_3 - -- TODO - make this less horrible grw [Finset.single_le_sum (f := (fun g => ∫⁻ (a : Additive G), ‖(G_n ((seq n) + 1) (by simp) f_n_limit) a + Conv (-↑↑(G_n ((seq n) + 1) (by simp) f_n_limit)) (delta g) a‖ₑ ^ 2 ∂Measure.count)) (s := S) (hf := by simp) (h := (by rw [S_eq_Sinv]; simp [hy]))] @@ -158,9 +153,8 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: apply_fun ENNReal.ofReal at g_inner_laplace simp at g_inner_laplace rw [g_inner_laplace] - norm_cast rw [ENNReal.ofReal_sum_of_nonneg] - . + · conv => rhs arg 2 @@ -172,53 +166,53 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: ) (G_n ((seq n) + 1) (by simp) f_n_limit))) rw [ae_eq_everywhere.mp (Lp.coeFn_sub _ _)] at g_norm rw [ae_eq_everywhere.mp (MeasureTheory.Lp.coeFn_compMeasurePreserving _ _)] at g_norm - simp [eLpNorm, eLpNorm', Lp.compMeasurePreserving] at g_norm + simp [eLpNorm, eLpNorm'] at g_norm rw [ENNReal.rpow_lt_top_iff_of_pos (by simp)] at g_norm grind )] simp [volume] simp_rw [my_haar_eq_count] apply le_refl - . simp - . simp - . + · simp + · simp + · simpa using S_nonempty -- Finset.single_le_sum - . simp + · simp grind - . + · apply MeasureTheory.Integrable.of_integral_ne_zero rw [← g_inner_laplace] simp [G'_n] have foo := g_n_conv_norm (seq (n) + 1) (by simp) f_n_limit grind - . + · exact NNReal.coe_nonneg _ - . + · simp [ConvExists] rw [my_add_haar_eq_count] apply ENNReal.ConvolutionExists.of_memLp_memLp (p := 2) (q := 2) (μ := Measure.count) - . infer_instance - . simp - . apply AEStronglyMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . rw [← my_add_haar_eq_count] + · infer_instance + · simp + · apply AEStronglyMeasurable.of_discrete + · apply AEStronglyMeasurable.of_discrete + · rw [← my_add_haar_eq_count] apply Lp.memLp - . rw [← my_add_haar_eq_count] + · rw [← my_add_haar_eq_count] apply Lp.memLp - . + · simp [ConvExists] rw [my_add_haar_eq_count] apply ENNReal.ConvolutionExists.of_memLp_memLp (p := 2) (q := 2) (μ := Measure.count) - . infer_instance - . simp - . apply AEStronglyMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . rw [← my_add_haar_eq_count] + · infer_instance + · simp + · apply AEStronglyMeasurable.of_discrete + · apply AEStronglyMeasurable.of_discrete + · rw [← my_add_haar_eq_count] apply Lp.memLp - . - refine ⟨by apply AEStronglyMeasurable.of_discrete, ?_⟩ + · + unfold MemLp rw [← my_add_haar_eq_count] rw [← neg_one_smul ℝ] rw [conv_smul] @@ -227,7 +221,7 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: simp [Conv] rw [← Function.comp_def (β := Additive G)] rw [MeasureTheory.eLpNorm_comp_measurePreserving (ν := Measure.count)] - . + · conv => arg 1 arg 1 @@ -244,44 +238,43 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: rw [← my_add_haar_eq_count] grw [ENNReal.eLpNorm_convolution_le_enorm_mul (p := 2) (q := 1)] - . + · refine ENNReal.mul_lt_top (ENNReal.mul_lt_top (by simp) ?_) ?_ · exact MeasureTheory.MemLp.eLpNorm_lt_top (MeasureTheory.MemLp.comp_measurePreserving (ν := volume) (Lp.memLp _) measure_preserving_unop_tomul) · refine MeasureTheory.MemLp.eLpNorm_lt_top (MeasureTheory.MemLp.comp_measurePreserving (ν := volume) ?_ measure_preserving_unop_tomul) apply Continuous.memLp_of_hasCompactSupport · fun_prop · simp [HasCompactSupport, tsupport] - . simp - . simp - . simp - . simp - . apply AEMeasurable.of_discrete - . apply AEMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . rw [my_add_haar_eq_count] + · simp + · simp + · simp + · simp + · apply AEMeasurable.of_discrete + · apply AEMeasurable.of_discrete + · apply AEStronglyMeasurable.of_discrete + · rw [my_add_haar_eq_count] apply MeasurePreserving.id - . rw [← my_haar_eq_count] + · rw [← my_haar_eq_count] apply Lp.memLp - . rw [← my_haar_eq_count] + · rw [← my_haar_eq_count] simp apply MemLp.neg apply Lp.memLp - . simp + · simp -- Now rename Hn ∗Gn such that we have added a constant so that Hn ∗Gn(e) = 0 let new_seq: ℕ → ℕ := seq let H_G_conv_zero (n: ℕ) (g: G) := ((Conv (H_n ((new_seq n)) s) (G_n ((new_seq n) + 1) (by simp) f_n_limit)) g) - (Conv (H_n ((new_seq n)) s) (G_n ((new_seq n) + 1) (by simp) f_n_limit) 1) - -- TODO - can the lipschitz constant can be improved? have H_G_conv_zero_lipschitz: ∀ n: ℕ, LipschitzWith ((((2 * #(S))^((2 : ℝ)⁻¹))) + 0) (H_G_conv_zero n) := by intro n simp only [H_G_conv_zero] simp only [new_seq] apply LipschitzWith.sub - . + · apply h_n_f_lipschitz - . apply LipschitzWith.const + · apply LipschitzWith.const have H_n_conv_zero_eq: ∀ n: ℕ, (H_G_conv_zero (n) 1) - (H_G_conv_zero (n) s⁻¹) = ‖(G_n ((new_seq n) + 1) (by simp) f_n_limit) - (conv_finsupp_lp2 (((G_n ((new_seq n) + 1) (by simp) f_n_limit))) (delta s) (by simp [delta]))‖ := by @@ -297,9 +290,9 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: rw [← conv_smul] rw [ ← smul_conv] rw [conv_assoc_of_lp2] - . + · rw [← conv_add_right] - . + · simp [H_n, conv_finsupp_lp2] rw [ae_eq_everywhere.mp (MeasureTheory.Lp.coeFn_smul _ _)] rw [conv_smul] @@ -313,7 +306,7 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: rw [ae_eq_everywhere.mp (MeasureTheory.Lp.coeFn_compMeasurePreserving _ _)] rw [ae_eq_everywhere.mp (MeasureTheory.Lp.coeFn_compMeasurePreserving _ _)] simp only [convolution, - ContinuousLinearMap.coe_sub', ContinuousLinearMap.mul_apply', Pi.smul_apply, smul_eq_mul] + ContinuousLinearMap.mul_apply', Pi.smul_apply, smul_eq_mul] simp have t_fake_inv: ∀ (t: G), (t: (Additive G))⁻¹ = -(Additive.ofMul t) := by intro t @@ -346,8 +339,8 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: rw [f_conv_delta_helper] rw [← Function.comp_def] apply MeasureTheory.MemLp.comp_measurePreserving (ν := volume) - . apply MeasureTheory.Lp.memLp - . + · apply MeasureTheory.Lp.memLp + · exact measurePreserving_mul_left volume s⁻¹ )] rw [ae_eq_everywhere.mp (MeasureTheory.Lp.coeFn_neg _)] @@ -373,8 +366,8 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: rw [f_conv_delta_helper] rw [← Function.comp_def] apply MeasureTheory.MemLp.comp_measurePreserving (ν := volume) - . apply MeasureTheory.Lp.memLp - . + · apply MeasureTheory.Lp.memLp + · exact measurePreserving_mul_left volume s⁻¹ ))‖^2 => rw [← real_inner_self_eq_norm_sq] @@ -390,59 +383,58 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: · simp [h] · field_simp exact key _ - . + · simp [ConvExists] rw [my_add_haar_eq_count] apply ENNReal.ConvolutionExists.of_memLp_memLp (p := 2) (q := 2) (μ := Measure.count) - . infer_instance - . simp - . apply AEStronglyMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . rw [← Function.comp_def] + · infer_instance + · simp + · apply AEStronglyMeasurable.of_discrete + · apply AEStronglyMeasurable.of_discrete + · rw [← Function.comp_def] apply MeasureTheory.MemLp.comp_measurePreserving - . apply Lp.memLp - . simp [volume] + · apply Lp.memLp + · simp [volume] rw [my_haar_eq_count] apply MeasureTheory.MeasurePreserving.id - . + · apply MeasureTheory.MemLp.comp_measurePreserving - . apply Lp.memLp - . simp [volume] + · apply Lp.memLp + · simp [volume] rw [my_haar_eq_count] apply MeasureTheory.MeasurePreserving.id - . - -- TODO - deduplicate this + · simp [f_conv_delta_helper] simp [ConvExists] rw [my_add_haar_eq_count] apply ENNReal.ConvolutionExists.of_memLp_memLp (p := 2) (q := 2) (μ := Measure.count) - . infer_instance - . simp - . apply AEStronglyMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . rw [← Function.comp_def] + · infer_instance + · simp + · apply AEStronglyMeasurable.of_discrete + · apply AEStronglyMeasurable.of_discrete + · rw [← Function.comp_def] apply MeasureTheory.MemLp.comp_measurePreserving - . apply Lp.memLp - . simp [volume] + · apply Lp.memLp + · simp [volume] rw [my_haar_eq_count] apply MeasureTheory.MeasurePreserving.id - . + · apply MeasureTheory.MemLp.neg rw [← Function.comp_def] apply MeasureTheory.MemLp.comp_measurePreserving - . apply Lp.memLp - . + · apply Lp.memLp + · simp [volume] rw [my_haar_eq_count] refine MeasurePreserving.mul_left Measure.count s⁻¹ ?_ apply MeasureTheory.MeasurePreserving.id - . rw [← my_haar_eq_count] + · rw [← my_haar_eq_count] apply Lp.memLp - . rw [← my_haar_eq_count] + · rw [← my_haar_eq_count] simp apply MemLp.neg apply Lp.memLp - . simp [delta] + · simp [delta] have compact_with_fixed_g (g: G): IsCompact (closure ( (Set.range (fun n => H_G_conv_zero n g)))) := by @@ -468,7 +460,7 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: rw [dist_comm] at bar grw [bar] simp [H_G_conv_zero] - ring + ring_nf simp have new_compact_closure: IsCompact (closure (Set.range (fun n => H_G_conv_zero n))) := by @@ -494,7 +486,7 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: rw [dist_comm] at bar grw [bar] simp [H_G_conv_zero] - ring + ring_nf simp have arzela_tendsto := IsCompact.tendsto_subseq new_compact_closure (x := fun n => ( @@ -528,9 +520,9 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: have new_tendsto_sub := (abs_tendsto _).comp ((tendsto_arzela_lim x).sub (tendsto_arzela_lim y)) have sub_le := le_of_tendsto new_tendsto_sub (b := ((↑(#S) * 2) ^ (2 : ℝ)⁻¹) * (dist x y)) ?_ - . norm_cast + · norm_cast norm_cast at sub_le - . apply Filter.Eventually.of_forall + · apply Filter.Eventually.of_forall intro n have foo := (H_G_conv_zero_lipschitz (arzela_seq n)).dist_le_mul x y rw [Real.dist_eq] at foo @@ -547,7 +539,7 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: intro x rw [← sub_eq_zero] - have sum_lim := tendsto_finset_sum (s := S) (fun s hs => tendsto_arzela_lim (s * x)) + have sum_lim := tendsto_finsetSum (s := S) (fun s hs => tendsto_arzela_lim (s * x)) have tendsto_sub := (tendsto_arzela_lim x).sub (sum_lim.const_mul ((#S : ℝ))⁻¹) norm_cast @@ -555,13 +547,13 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: (f := (fun x_1 ↦ |((fun n ↦ H_G_conv_zero n) ∘ arzela_seq) x_1 x - (↑(#S))⁻¹ * ∑ c ∈ S, ((fun n ↦ H_G_conv_zero n) ∘ arzela_seq) x_1 (c * x)|)) (g := fun n => (1 / (n + 1))) ?_ ?_ ?_ - . + · have target_eq_zero := tendsto_nhds_unique ((abs_tendsto _).comp tendsto_sub) (lim_zero) rw [abs_eq_zero] at target_eq_zero rw [sub_eq_zero] at target_eq_zero simp [target_eq_zero] - . simp - . intro n + · simp + · intro n simp conv => lhs @@ -588,7 +580,7 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: grw [abs_add_le] simp rw [laplace_conv_eq_laplace_right_of_lp2] - . + · simp [Conv] grw [ENNReal.ofReal_add_le] rw [← Real.enorm_eq_ofReal_abs] @@ -619,7 +611,7 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: · rw [ENNReal.inv_top, zero_add]; exact ENNReal.inv_two_add_inv_two · apply AEMeasurable.of_discrete · apply AEMeasurable.of_discrete - . + · conv => lhs arg 1 @@ -661,32 +653,31 @@ lemma nontrivial_harmonic_case_one (f_n_limit: ∀ s: S, (Filter.Tendsto (fun n: omega - . - -- TODO - deduplicate this + · simp [ConvExists] rw [my_add_haar_eq_count] apply ENNReal.ConvolutionExists.of_memLp_memLp (p := 2) (q := 2) (μ := Measure.count) - . infer_instance - . simp - . apply AEStronglyMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . rw [← Function.comp_def] + · infer_instance + · simp + · apply AEStronglyMeasurable.of_discrete + · apply AEStronglyMeasurable.of_discrete + · rw [← Function.comp_def] apply MeasureTheory.MemLp.comp_measurePreserving - . apply Lp.memLp - . simp [volume] + · apply Lp.memLp + · simp [volume] rw [my_haar_eq_count] apply MeasureTheory.MeasurePreserving.id - . + · apply MeasureTheory.MemLp.comp_measurePreserving - . apply Lp.memLp - . simp [volume] + · apply Lp.memLp + · simp [volume] rw [my_haar_eq_count] apply MeasureTheory.MeasurePreserving.id - . rw [← my_haar_eq_count] + · rw [← my_haar_eq_count] apply Lp.memLp - . rw [← my_haar_eq_count] + · rw [← my_haar_eq_count] apply Lp.memLp - . + · simp simp_rw [inv_eq_one_div] apply tendsto_one_div_add_atTop_nhds_zero_nat diff --git a/Gromov/Harmonic/Convolution.lean b/Gromov/Harmonic/Convolution.lean index 9721ae6..c14260c 100644 --- a/Gromov/Harmonic/Convolution.lean +++ b/Gromov/Harmonic/Convolution.lean @@ -19,8 +19,6 @@ multiplication, and `laplace_conv_eq_laplace_right`. public section -set_option linter.style.cdot false -set_option linter.style.whitespace false attribute [local implicit_reducible] Additive namespace GeneratesNS @@ -49,30 +47,28 @@ lemma harmonic_maximum_implies_const (f: G → ℝ) (hf: Laplace_b f = 0) (a: G rw [ih] at f_at_l field_simp at f_at_l - -- TODO - is there a 'Finset.expect' theorem we can use? - -- TODO - upstream this to mathlib in some form have f_s_eq: ∀ s: S, f a = f (s * (l.unattach.prod * a)) := by by_contra! simp at this obtain ⟨s, s_mem_s, hs⟩ := this by_cases val_le_max: f (s * (l.unattach.prod * a)) ≤ f a - . + · have val_lt_max: f (s * (l.unattach.prod * a)) < f a := by exact lt_of_le_of_ne (h_max (↑s * (l.unattach.prod * a))) (id (Ne.symm hs)) have sum_strict_lt := Finset.sum_lt_sum (f := fun x => f (x * (l.unattach.prod * a))) (g := fun x => f a) (s := S) ?_ ?_ - . + · simp at sum_strict_lt rw [mul_comm] at sum_strict_lt rw [← div_lt_iff₀] at sum_strict_lt - . + · apply ne_of_gt at sum_strict_lt contradiction - . simpa using S_nonempty - . intro s hs + · simpa using S_nonempty + · intro s hs apply h_max - . use s - . + · use s + · have val_gt := h_max (s * (l.unattach.prod * a)) simp at val_le_max linarith @@ -102,7 +98,7 @@ open scoped Convolution open MeasureTheory -lemma laplace_b_const (k: ℝ): Laplace_b (fun g => k) = 0 := by +lemma laplace_b_const (k: ℝ): Laplace_b (fun _g => k) = 0 := by simp [Laplace_b] simp [f_conv_mu] ext a @@ -111,8 +107,8 @@ lemma laplace_b_const (k: ℝ): Laplace_b (fun g => k) = 0 := by rw [← mul_assoc] rw [inv_mul_cancel₀] - . simp - . simp + · simp + · simp have foo := S_nonempty grind @@ -129,9 +125,9 @@ lemma conv_add_right {f g h: G → ℝ} (h_fg: ConvExists f g) (h_fh : ConvExist rfl rw [MeasureTheory.ConvolutionExists.distrib_add] - . rfl - . exact h_fg - . exact h_fh + · rfl + · exact h_fg + · exact h_fh lemma conv_add_left {f g h: G → ℝ} (h_fh: ConvExists f h) (h_gh : ConvExists g h): Conv (f + g) h = Conv f h + Conv g h := by unfold Conv @@ -143,9 +139,9 @@ lemma conv_add_left {f g h: G → ℝ} (h_fh: ConvExists f h) (h_gh : ConvExists rfl rw [MeasureTheory.ConvolutionExists.add_distrib] - . rfl - . exact h_fh - . exact h_gh + · rfl + · exact h_fh + · exact h_gh lemma conv_smul {f h: G → ℝ} (k: ℝ): Conv (k • f) h = k • Conv f h := by funext g @@ -176,7 +172,6 @@ lemma laplace_conv_eq_laplace_right_of_lp2 (f g: G → ℝ) (hfg: ConvExists f g nth_rw 2 [sub_eq_add_neg] rw [conv_add_right] - -- TODO - figure out how to do this without a 'conv' block conv => rhs rhs @@ -184,24 +179,24 @@ lemma laplace_conv_eq_laplace_right_of_lp2 (f g: G → ℝ) (hfg: ConvExists f g simp rw [smul_conv] simp - . rw [← sub_eq_add_neg] - . exact hfg - . + · rw [← sub_eq_add_neg] + · exact hfg + · simp [ConvExists, MeasureTheory.ConvolutionExists, MeasureTheory.ConvolutionExistsAt] intro a simp_rw [f_conv_mu] simp_rw [← mul_assoc, mul_comm, mul_assoc] apply MeasureTheory.Integrable.const_mul simp_rw [Finset.mul_sum] - apply MeasureTheory.integrable_finset_sum + apply MeasureTheory.integrable_finsetSum intro s hs simp [ConvExists, MeasureTheory.ConvolutionExists, MeasureTheory.ConvolutionExistsAt] at hfg specialize hfg (s * a) simp_rw [mul_div] exact hfg - . exact hf - . exact hg - . apply mu_finsupp + · exact hf + · exact hg + · apply mu_finsupp lemma laplace_conv_eq_laplace_right (f g: G → ℝ) (hfg: ConvExists f g) (g_nonneg: ∀ a: G, 0 ≤ g a) (g_finsupp: g.support.Finite): Laplace_b (Conv f g) = Conv f (Laplace_b g) := by @@ -210,7 +205,6 @@ lemma laplace_conv_eq_laplace_right (f g: G → ℝ) (hfg: ConvExists f g) (g_no nth_rw 2 [sub_eq_add_neg] rw [conv_add_right] - -- TODO - figure out how to do this without a 'conv' block conv => rhs rhs @@ -218,34 +212,33 @@ lemma laplace_conv_eq_laplace_right (f g: G → ℝ) (hfg: ConvExists f g) (g_no simp rw [smul_conv] simp - . rw [← sub_eq_add_neg] - . exact hfg - . + · rw [← sub_eq_add_neg] + · exact hfg + · simp [ConvExists, MeasureTheory.ConvolutionExists, MeasureTheory.ConvolutionExistsAt] intro a simp_rw [f_conv_mu] simp_rw [← mul_assoc, mul_comm, mul_assoc] apply MeasureTheory.Integrable.const_mul simp_rw [Finset.mul_sum] - apply MeasureTheory.integrable_finset_sum + apply MeasureTheory.integrable_finsetSum intro s hs simp [ConvExists, MeasureTheory.ConvolutionExists, MeasureTheory.ConvolutionExistsAt] at hfg specialize hfg (s * a) simp_rw [mul_div] exact hfg - . exact hfg - . + · exact hfg + · apply conv_exists_fin_supp right exact mu_finsupp - . apply g_finsupp - . exact g_nonneg - . exact mu_finsupp - . intro a + · apply g_finsupp + · exact g_nonneg + · exact mu_finsupp + · intro a simp [mu] positivity -#print axioms laplace_conv_eq_laplace_right -- simp_rw [tsum_eq_sum] @@ -257,14 +250,13 @@ lemma f_n_fin_supp (n: ℕ): (f_n n).support.Finite := by apply Set.Finite.inter_of_right apply Set.Finite.subset (hs := ?_) (ht := Finset.support_sum _ _) refine Set.Finite.biUnion' ?_ ?_ - . exact Set.toFinite (Membership.mem Finset.univ.val) - . intro m hm + · exact Set.toFinite (Membership.mem Finset.univ.val) + · intro m hm apply mu_conv_finsupp -- The expression 'Σ s_1, ..., s_n ∈ S, f(s_1 * ... * s_n)' -- This is a sum over all n-tuples of elements in S, where each term in is f (s_1 * ... * s_n) --- TODO - is there aless horrible way to write in in mathlib? @[expose] def NTupleSum (n: ℕ) (f: G → ℝ): ℝ := ∑ s : (Fin n → S), f ((List.ofFn s).unattach.prod) diff --git a/Gromov/Harmonic/LaplaceLinear.lean b/Gromov/Harmonic/LaplaceLinear.lean index 81f7578..50a9795 100644 --- a/Gromov/Harmonic/LaplaceLinear.lean +++ b/Gromov/Harmonic/LaplaceLinear.lean @@ -11,17 +11,15 @@ public import Gromov.Harmonic.MuConv public section -set_option linter.style.cdot false -set_option linter.style.whitespace false attribute [local implicit_reducible] Additive namespace GeneratesNS open Generates -variable [hGS: Generates] +variable [hGS : Generates] include hGS -variable {V: Submodule ℝ LipschitzH} [V_finite: FiniteDimensional ℝ V] [Nontrivial V] +variable {V : Submodule ℝ LipschitzH} [V_finite : FiniteDimensional ℝ V] [Nontrivial V] open scoped Finset open scoped Pointwise @@ -30,20 +28,20 @@ open MeasureTheory set_option maxHeartbeats 60000 in @[expose] -noncomputable def nontrivial_harmonic_common (k: ℕ) (seq: ℕ → ℕ) (h_seq: Filter.Tendsto seq Filter.atTop Filter.atTop) (F: G → ℝ) (H_n: ℕ → G → ℝ) (h_conv_lipschitz: ∀ n, LipschitzWith k (Conv (H_n n) (f_n n))) -(tendsto_F: Filter.Tendsto ((fun n ↦ Conv (H_n (seq n)) (f_n (seq n)))) Filter.atTop (nhds F)) -(H_n_norm: ∀ n: ℕ, MeasureTheory.eLpNorm (H_n n) (p := ⊤) MeasureTheory.volume = 1): LipschitzH := by +noncomputable def nontrivial_harmonic_common (k : ℕ) (seq : ℕ → ℕ) (h_seq : Filter.Tendsto seq Filter.atTop Filter.atTop) (F : G → ℝ) (H_n : ℕ → G → ℝ) (h_conv_lipschitz : ∀ n, LipschitzWith k (Conv (H_n n) (f_n n))) +(tendsto_F : Filter.Tendsto ((fun n ↦ Conv (H_n (seq n)) (f_n (seq n)))) Filter.atTop (nhds F)) +(H_n_norm : ∀ n : ℕ, MeasureTheory.eLpNorm (H_n n) (p := ⊤) MeasureTheory.volume = 1) : LipschitzH := by - let conv_h_n_cont (n: ℕ): C(G, ℝ) := { + let conv_h_n_cont (n : ℕ) : C(G, ℝ) := { toFun := Conv (H_n (seq n)) (f_n (seq n)), continuous_toFun := by exact continuous_of_discreteTopology } - let F_lipschitzh: LipschitzH := { - toFun := (fun (g: G) => F g), + let F_lipschitzh : LipschitzH := { + toFun := (fun (g : G) => F g), lipschitz := by use k - have closed_lipschitz := isClosed_setOf_lipschitzWith (α := G) (β := ℝ) k + have closed_lipschitz := isClosed_setOfPred_lipschitzWith (α := G) (β := ℝ) k apply IsClosed.isSeqClosed at closed_lipschitz simp [IsSeqClosed] at closed_lipschitz have F_lipschitz := closed_lipschitz (p := F) (x := (fun n ↦ Conv (H_n (seq n)) (f_n (seq n)))) (by @@ -55,20 +53,16 @@ noncomputable def nontrivial_harmonic_common (k: ℕ) (seq: ℕ → ℕ) (h_seq: simp [Harmonic] intro g rw [tendsto_pi_nhds] at tendsto_F - have lim_f_sum := tendsto_finset_sum (ι := S) (M := ℝ) (s := Finset.univ) (a := fun s => F (s.val * g)) (f := (fun (s: S) n ↦ Conv (H_n (seq n)) (f_n (seq n)) (s.val *g))) (x := Filter.atTop (α := ℕ)) ?_ - - -- TODO - figure out why lean hangs without this + have lim_f_sum := tendsto_finsetSum (ι := S) (M := ℝ) (s := Finset.univ) (a := fun s => F (s.val * g)) (f := (fun (s : S) n ↦ Conv (H_n (seq n)) (f_n (seq n)) (s.val *g))) (x := Filter.atTop (α := ℕ)) ?_ have my_mul : ContinuousMul ℝ := instIsTopologicalRingReal.toContinuousMul have lim_f_mul_sum := Filter.Tendsto.const_mul ((#S) : ℝ)⁻¹ lim_f_sum - . - have lim_f_g := tendsto_F g + · have lim_f_g := tendsto_F g have lim_f_g_sub := Filter.Tendsto.sub lim_f_g lim_f_mul_sum - have laplace_conv_tendsto_zero: Filter.Tendsto (fun n => eLpNorm (Laplace_b (Conv (H_n (seq n)) (f_n (seq n)))) ⊤) Filter.atTop (nhds 0) := by - apply tendsto_of_tendsto_of_tendsto_of_le_of_le (g := fun n => 0) (h := fun (n: ℕ) => ENNReal.ofReal ((2: ℝ) / ((seq n) + 1) : ℝ)) - . simp - . - rw [← ENNReal.tendsto_toReal_iff] + have laplace_conv_tendsto_zero : Filter.Tendsto (fun n => eLpNorm (Laplace_b (Conv (H_n (seq n)) (f_n (seq n)))) ⊤) Filter.atTop (nhds 0) := by + apply tendsto_of_tendsto_of_tendsto_of_le_of_le (g := fun n => 0) (h := fun (n : ℕ) => ENNReal.ofReal ((2 : ℝ) / ((seq n) + 1) : ℝ)) + · simp + · rw [← ENNReal.tendsto_toReal_iff] conv => arg 1 intro n @@ -80,36 +74,34 @@ noncomputable def nontrivial_harmonic_common (k: ℕ) (seq: ℕ → ℕ) (h_seq: arg 1 intro n rhs - equals ((((((seq n) + 1): ℕ)) : ℕ ) : ℝ) => simp + equals ((((((seq n) + 1) : ℕ)) : ℕ ) : ℝ) => simp conv => arg 1 - equals (fun (n: ℕ) => (2 : ℝ) / (n) ) ∘ (fun n => (seq n) + 1) => + equals (fun (n : ℕ) => (2 : ℝ) / (n) ) ∘ (fun n => (seq n) + 1) => ext n simp apply Filter.Tendsto.comp - . - conv => + · conv => arg 1 - equals (fun (n: ℕ) => (2 : ℝ) / ((n) : ℕ)) => + equals (fun (n : ℕ) => (2 : ℝ) / ((n) : ℕ)) => ext n simp apply tendsto_const_div_atTop_nhds_zero_nat - . - apply Filter.Tendsto.comp - . conv => + · apply Filter.Tendsto.comp + · conv => arg 1 equals fun n => n + 1 => simp apply Filter.tendsto_add_atTop_nat - . simp + · simp exact h_seq - . simp - . simp - . rw [Pi.le_def] + · simp + · simp + · rw [Pi.le_def] intro x simp - . rw [Pi.le_def] + · rw [Pi.le_def] intro n simp have bound_by_norm_one := conv_laplce_norm (seq n) @@ -118,7 +110,7 @@ noncomputable def nontrivial_harmonic_common (k: ℕ) (seq: ℕ → ℕ) (h_seq: simp at bound_by_norm_one grw [bound_by_norm_one] have h_norm := H_n_norm (seq n) - simp [eLpNorm, eLpNorm'] at h_norm + simp [eLpNorm] at h_norm rw [h_norm] simp simp_rw [Laplace_b] @@ -127,33 +119,30 @@ noncomputable def nontrivial_harmonic_common (k: ℕ) (seq: ℕ → ℕ) (h_seq: rw [← ENNReal.tendsto_toReal_iff] at laplace_conv_tendsto_zero - have laplace_real_tendsto_zero: Filter.Tendsto (fun n => |(Laplace_b (Conv (H_n (seq n)) (f_n (seq n))) (g))|) Filter.atTop (nhds 0) := by + have laplace_real_tendsto_zero : Filter.Tendsto (fun n => |(Laplace_b (Conv (H_n (seq n)) (f_n (seq n))) (g))|) Filter.atTop (nhds 0) := by apply squeeze_zero (g := fun n => (eLpNorm (Laplace_b (Conv (H_n (seq n)) (f_n (seq n)))) ⊤ volume).toReal) - . - intro n + · intro n simp - . intro n + · intro n have ae_le := ENNReal.ae_le_essSup (fun x ↦ ‖Laplace_b (Conv (H_n (seq n)) (f_n (seq n))) x‖ₑ) (μ := volume) simp [volume] at ae_le rw [my_haar_eq_count] at ae_le rw [count_ae_everywhere] at ae_le specialize ae_le g - simp [eLpNorm, eLpNorm'] + simp [eLpNorm] simp [eLpNormEssSup] rw [← ENNReal.toReal_le_toReal] at ae_le - simp only [toReal_enorm, Real.norm_eq_abs, OrderTop.bddAbove] at ae_le + simp only [toReal_enorm, Real.norm_eq_abs] at ae_le simp [volume] rw [my_haar_eq_count] exact ae_le - . simp - . - -- TODO - deduplicate this - have bound_by_norm_one := conv_laplce_norm (seq n) H_n + · simp + · have bound_by_norm_one := conv_laplce_norm (seq n) H_n have norm_le_two_div := f_n_sub_conv (seq n) nth_rw 1 [eLpNorm] at bound_by_norm_one simp at bound_by_norm_one have h_norm := H_n_norm (seq n) - simp [eLpNorm, eLpNorm'] at h_norm + simp [eLpNorm] at h_norm rw [h_norm] at bound_by_norm_one simp only [eLpNormEssSup] at bound_by_norm_one simp [volume] at bound_by_norm_one @@ -165,11 +154,10 @@ noncomputable def nontrivial_harmonic_common (k: ℕ) (seq: ℕ → ℕ) (h_seq: rw [my_haar_eq_count] at norm_le_two_div grw [norm_le_two_div] apply ENNReal.ofReal_lt_top - . apply laplace_conv_tendsto_zero + · apply laplace_conv_tendsto_zero simp_rw [Laplace_b] at laplace_real_tendsto_zero simp_rw [f_conv_mu] at laplace_real_tendsto_zero - beta_reduce at laplace_real_tendsto_zero conv at laplace_real_tendsto_zero => arg 1 rw [← Function.comp_def] @@ -191,17 +179,15 @@ noncomputable def nontrivial_harmonic_common (k: ℕ) (seq: ℕ → ℕ) (h_seq: rw [eq_comm] at lim_eq rw [sub_eq_zero] at lim_eq rw [lim_eq] - norm_cast rw [← Finset.sum_subtype (s := S) (f := fun i => (F (i * g)))] simp - . intro n - -- TODO - deduplicate this. I'm sure there's lots of other versions of it scattered around this file + · intro n rw [← lt_top_iff_ne_top] grw [conv_laplce_norm] rw [H_n_norm] simp simp_rw [Laplace_b] - grw [MeasureTheory.eLpNorm_sub_le] + grw [MeasureTheory.eLpNorm_sub_le (by norm_num)] rw [f_n_norm_one] simp_rw [f_conv_mu] simp_rw [← smul_eq_mul] @@ -216,8 +202,7 @@ noncomputable def nontrivial_harmonic_common (k: ℕ) (seq: ℕ → ℕ) (h_seq: funext g simp - - grw [MeasureTheory.eLpNorm_sum_le] + grw [MeasureTheory.eLpNorm_sum_le (by norm_num)] simp_rw [← Function.comp_def] conv => lhs @@ -241,26 +226,17 @@ noncomputable def nontrivial_harmonic_common (k: ℕ) (seq: ℕ → ℕ) (h_seq: norm_cast rw [Real.enorm_eq_ofReal_abs] simp - norm_cast apply ENNReal.mul_lt_top - . simp - . simp - . - intro s hs - apply AEStronglyMeasurable.of_discrete - . simp - . apply AEStronglyMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . simp - - - . simp - . intro s hs + · simp + · simp + + · simp + · intro s hs apply tendsto_F } exact F_lipschitzh -lemma counting_le_essSup (f: G → ℝ): ∀ g : G, ‖f g‖ₑ ≤ essSup (fun g => ‖f g‖ₑ) volume := by +lemma counting_le_essSup (f : G → ℝ) : ∀ g : G, ‖f g‖ₑ ≤ essSup (fun g => ‖f g‖ₑ) volume := by intro g have ae_le := ENNReal.ae_le_essSup (fun g => ‖f g‖ₑ) (μ := volume) simp [MeasureTheory.volume] at ae_le @@ -272,12 +248,12 @@ lemma counting_le_essSup (f: G → ℝ): ∀ g : G, ‖f g‖ₑ ≤ essSup (fu rw [my_haar_eq_count] exact ae_le -lemma essSup_eq_elpNorm_top (f: G → ℝ): (essSup (fun g => ‖f g‖ₑ) volume) = (eLpNorm f ⊤ volume) := by +lemma essSup_eq_elpNorm_top (f : G → ℝ) : (essSup (fun g => ‖f g‖ₑ) volume) = (eLpNorm f ⊤ volume) := by + rw [MeasureTheory.eLpNorm_exponent_top (by apply AEStronglyMeasurable.of_discrete)] rfl - @[expose] -noncomputable def Laplace_linear: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G))) →ₗ[ℝ] (MeasureTheory.Lp ℝ 2 (μ := volume (α := G))) := { +noncomputable def Laplace_linear : (MeasureTheory.Lp ℝ 2 (μ := volume (α := G))) →ₗ[ℝ] (MeasureTheory.Lp ℝ 2 (μ := volume (α := G))) := { toFun := Laplace map_add' := by intro x y @@ -300,13 +276,12 @@ noncomputable def Laplace_linear: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G )] rw [MeasureTheory.MemLp.toLp_add] - . abel - . - have foo := MeasureTheory.Lp.memLp (conv_mu_lp2 x) + · abel_nf + · have foo := MeasureTheory.Lp.memLp (conv_mu_lp2 x) simp [conv_mu_lp2] at foo rw [ae_eq_everywhere.mp (MeasureTheory.MemLp.coeFn_toLp _)] at foo exact foo - . have foo := MeasureTheory.Lp.memLp (conv_mu_lp2 y) + · have foo := MeasureTheory.Lp.memLp (conv_mu_lp2 y) simp [conv_mu_lp2] at foo rw [ae_eq_everywhere.mp (MeasureTheory.MemLp.coeFn_toLp _)] at foo exact foo @@ -321,9 +296,8 @@ noncomputable def Laplace_linear: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G rw [smul_sub] } - @[expose] -instance volume_finite_compact: IsFiniteMeasureOnCompacts (volume (α := G)) := by +instance volume_finite_compact : IsFiniteMeasureOnCompacts (volume (α := G)) := by simp [volume] rw [my_haar_eq_count] exact { @@ -333,18 +307,15 @@ instance volume_finite_compact: IsFiniteMeasureOnCompacts (volume (α := G)) := exact Measure.count_apply_lt_top.mpr finite } - -lemma finsupp_lp_top (f: G → ℝ) (hf: f.support.Finite) (p: ENNReal): MeasureTheory.MemLp f p (Measure.count) := by +lemma finsupp_lp_top (f : G → ℝ) (hf : f.support.Finite) (p : ENNReal) : MeasureTheory.MemLp f p (Measure.count) := by rw [← my_haar_eq_count] apply Continuous.memLp_of_hasCompactSupport - . apply continuous_of_discreteTopology - . - simp [HasCompactSupport] + · apply continuous_of_discreteTopology + · simp [HasCompactSupport] rw [isCompact_iff_finite] simp [tsupport] exact hf - @[expose] noncomputable def F_n (n : ℕ) := Real.sqrt ∘ (f_n n) @[expose] @@ -354,32 +325,29 @@ noncomputable def F_n_lp2 (n : ℕ) := MeasureTheory.MemLp.toLp (F_n n) (by apply finsupp_lp_top simp [F_n] apply Set.Finite.subset (s := (f_n n).support) - . - unfold f_n + · unfold f_n apply f_n_fin_supp - . - apply Function.support_comp_subset + · apply Function.support_comp_subset simp ) (μ := volume (α := G)) (p := 2) - @[expose] -instance volume_mul_left_invariant: (volume (α := G)).IsMulLeftInvariant := by +instance volume_mul_left_invariant : (volume (α := G)).IsMulLeftInvariant := by simp [volume] rw [my_haar_eq_count] infer_instance omit hGS in -lemma abs_sub_le_abs_add (a b: ℝ) (ha: 0 ≤ a) (hb: 0 ≤ b): |a - b| ≤ |a + b| := by +lemma abs_sub_le_abs_add (a b : ℝ) (ha : 0 ≤ a) (hb : 0 ≤ b) : |a - b| ≤ |a + b| := by rw [abs_sub_le_iff] refine ⟨?_, ?_⟩ - . - rw [le_abs] + · rw [le_abs] grind - . rw [le_abs] + · rw [le_abs] grind -lemma norm_sub_squared_le (a b : ℝ) (ha: 0 ≤ a) (hb: 0 ≤ b): (a - b)^2 ≤ |a^2 - b^2| := by +omit hGS in +lemma norm_sub_squared_le [_hGS : Generates] (a b : ℝ) (ha : 0 ≤ a) (hb : 0 ≤ b) : (a - b)^2 ≤ |a^2 - b^2| := by conv => lhs rw [← sq_abs] @@ -388,56 +356,46 @@ lemma norm_sub_squared_le (a b : ℝ) (ha: 0 ≤ a) (hb: 0 ≤ b): (a - b)^2 ≤ rw [sq_sub_sq] rw [abs_mul] nth_rw 2 [mul_comm] - -- TODO - why doesn't grw work here? apply mul_le_mul - . simp - . apply abs_sub_le_abs_add a b ha hb - . simp - . simp - + · simp + · apply abs_sub_le_abs_add a b ha hb + · simp + · simp @[expose] -def f_n_conv_delta_tendsto: Prop := ∀ s: S, Filter.Tendsto (fun n: ℕ => MeasureTheory.eLpNorm (f_n n - (Conv (f_n n) (delta s.val))) 1 MeasureTheory.volume) Filter.atTop (nhds 0) - +def f_n_conv_delta_tendsto : Prop := ∀ s : S, Filter.Tendsto (fun n : ℕ => MeasureTheory.eLpNorm (f_n n - (Conv (f_n n) (delta s.val))) 1 MeasureTheory.volume) Filter.atTop (nhds 0) -lemma f_conv_delta_helper (f: G → ℝ) (s: G): (Conv f (delta s)) = fun g => f (s⁻¹ * g) := by +lemma f_conv_delta_helper (f : G → ℝ) (s : G) : (Conv f (delta s)) = fun g => f (s⁻¹ * g) := by funext g exact f_conv_delta f g s - -- Lemma 3.16 in Vikman -- The case split statement in Vikman -lemma F_n_conv_mu_lim (f_n_limit: f_n_conv_delta_tendsto): - Filter.Tendsto (fun n => ‖(F_n_lp2 n) - conv_mu_lp2 (F_n_lp2 n)‖ₑ) Filter.atTop (nhds 0) := by +lemma F_n_conv_mu_lim (f_n_limit : f_n_conv_delta_tendsto) : Filter.Tendsto (fun n => ‖(F_n_lp2 n) - conv_mu_lp2 (F_n_lp2 n)‖ₑ) Filter.atTop (nhds 0) := by - have f_n_sub_norm: ∀ s ∈ S, ∀ (i : ℕ), ∑' (g : G), ‖f_n i g - f_n i (s * g)‖ₑ ≠ ⊤ := by + have f_n_sub_norm : ∀ s ∈ S, ∀ (i : ℕ), ∑' (g : G), ‖f_n i g - f_n i (s * g)‖ₑ ≠ ⊤ := by intro s hs n have foo := f_n_norm_one n rw [← lt_top_iff_ne_top] - rw [MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm (by simp) (by simp)] at foo + rw [MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm_toReal (by simp) (by simp) (by apply AEStronglyMeasurable.of_discrete)] at foo rw [lintegral_g_eq_add] at foo simp at foo grw [ENNReal.tsum_le_tsum (g := fun g => ‖f_n n g‖ₑ + ‖(f_n n (s * g))‖ₑ)] - . - rw [ENNReal.tsum_add] + · rw [ENNReal.tsum_add] rw [ENNReal.add_lt_top] - . refine ⟨?_, ?_⟩ - . simp [foo] - . - grw [ENNReal.tsum_comp_le_tsum_of_injective (g := fun a => ‖f_n n a‖ₑ)] - . - simp [foo] - . intro a b hab + · refine ⟨?_, ?_⟩ + · simp [foo] + · grw [ENNReal.tsum_comp_le_tsum_of_injective (g := fun a => ‖f_n n a‖ₑ)] + · simp [foo] + · intro a b hab simpa using hab - . - intro a + · intro a grw [enorm_sub_le] rw [← ENNReal.tendsto_toReal_iff] - . - have S_ne: (#S : ℝ) ≠ 0 := by + · have S_ne : (#S : ℝ) ≠ 0 := by simp have foo := hGS.hS simp at foo @@ -476,57 +434,38 @@ lemma F_n_conv_mu_lim (f_n_limit: f_n_conv_delta_tendsto): simp_rw [← Finset.sum_sub_distrib] rw [ENNReal.toReal_zero] - - apply squeeze_zero (g := fun n => (1 / ↑(#S : ℝ)) • ∑ x ∈ S, (eLpNorm ((F_n_lp2 n).val.cast - (fun (g: G) => (F_n_lp2 n) (x * g))) 2 volume).toReal) - . simp - . - intro n + apply squeeze_zero (g := fun n => (1 / ↑(#S : ℝ)) • ∑ x ∈ S, (eLpNorm ((F_n_lp2 n).val.cast - (fun (g : G) => (F_n_lp2 n) (x * g))) 2 volume).toReal) + · simp + · intro n rw [eLpNorm_const_smul] - grw [eLpNorm_sum_le] - . - simp + grw [eLpNorm_sum_le (by norm_num)] + · simp rw [ENNReal.toReal_sum] intro s hs rw [← lt_top_iff_ne_top] - grw [eLpNorm_sub_le] - . - rw [ENNReal.add_lt_top] - . refine ⟨?_, ?_⟩ - . exact Lp.eLpNorm_lt_top (F_n_lp2 n) - . - simp_rw [← Function.comp_def] + grw [eLpNorm_sub_le (by norm_num)] + · rw [ENNReal.add_lt_top] + · refine ⟨?_, ?_⟩ + · exact Lp.eLpNorm_lt_top (F_n_lp2 n) + · simp_rw [← Function.comp_def] rw [MeasureTheory.eLpNorm_comp_measurePreserving] - . exact Lp.eLpNorm_lt_top (F_n_lp2 n) - . apply AEStronglyMeasurable.of_discrete - . exact measurePreserving_mul_left volume s - . apply AEStronglyMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . simp - . - apply ENNReal.mul_ne_top (by simp) + · exact Lp.eLpNorm_lt_top (F_n_lp2 n) + · apply AEStronglyMeasurable.of_discrete + · exact measurePreserving_mul_left volume s + · apply ENNReal.mul_ne_top (by simp) rw [ENNReal.sum_ne_top] - -- TODO - deduplicate this intro s hs rw [← lt_top_iff_ne_top] - grw [eLpNorm_sub_le] - . - rw [ENNReal.add_lt_top] - . refine ⟨?_, ?_⟩ - . exact Lp.eLpNorm_lt_top (F_n_lp2 n) - . - simp_rw [← Function.comp_def] + grw [eLpNorm_sub_le (by norm_num)] + · rw [ENNReal.add_lt_top] + · refine ⟨?_, ?_⟩ + · exact Lp.eLpNorm_lt_top (F_n_lp2 n) + · simp_rw [← Function.comp_def] rw [MeasureTheory.eLpNorm_comp_measurePreserving] - . exact Lp.eLpNorm_lt_top (F_n_lp2 n) - . apply AEStronglyMeasurable.of_discrete - . exact measurePreserving_mul_left volume s - . apply AEStronglyMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . simp - . intro s hs - apply AEStronglyMeasurable.of_discrete - . simp - . - conv => + · exact Lp.eLpNorm_lt_top (F_n_lp2 n) + · apply AEStronglyMeasurable.of_discrete + · exact measurePreserving_mul_left volume s + · conv => rhs equals nhds ((1 / ↑(#S : ℝ)) • 0) => simp @@ -534,7 +473,7 @@ lemma F_n_conv_mu_lim (f_n_limit: f_n_conv_delta_tendsto): apply Filter.Tendsto.const_smul conv => rhs - equals nhds (∑ x_1 ∈ S⁻¹, (0: ℝ)) => + equals nhds (∑ x_1 ∈ S⁻¹, (0 : ℝ)) => simp conv => arg 1 @@ -542,30 +481,26 @@ lemma F_n_conv_mu_lim (f_n_limit: f_n_conv_delta_tendsto): arg 1 equals S⁻¹ => apply S_eq_Sinv - apply tendsto_finset_sum + apply tendsto_finsetSum intro s hs conv => arg 1 intro n - rw [MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm (by simp) (by simp)] + rw [MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm_toReal (by simp) (by simp) (by apply AEStronglyMeasurable.of_discrete)] rw [lintegral_g_eq_add] simp apply squeeze_zero (g := (fun n ↦ ((∑' (g : G), ‖(f_n n) g - (f_n n) (s * g)‖ₑ) ^ (2 : ℝ)⁻¹).toReal)) - . simp - . - intro n + · simp + · intro n rw [ENNReal.toReal_le_toReal] - . - apply ENNReal.rpow_le_rpow - . - apply ENNReal.tsum_le_tsum + · apply ENNReal.rpow_le_rpow + · apply ENNReal.tsum_le_tsum intro g rw [Real.enorm_eq_ofReal_abs] rw [Real.enorm_eq_ofReal_abs] rw [← ENNReal.ofReal_pow] - . - apply ENNReal.ofReal_le_ofReal + · apply ENNReal.ofReal_le_ofReal simp [F_n_lp2] simp [ae_eq_everywhere.mp (MeasureTheory.MemLp.coeFn_toLp _)] simp [F_n] @@ -574,47 +509,39 @@ lemma F_n_conv_mu_lim (f_n_limit: f_n_conv_delta_tendsto): arg 1 equals (Real.sqrt (f_n n g))^2 - (Real.sqrt (f_n n (s * g)))^2 => rw [Real.sq_sqrt] - . - rw [Real.sq_sqrt] - . apply f_n_nonneg - . apply f_n_nonneg + · rw [Real.sq_sqrt] + · apply f_n_nonneg + · apply f_n_nonneg apply norm_sub_squared_le - . simp - . simp - . simp - . simp - . - rw [← lt_top_iff_ne_top] - have norm_sub_lt: eLpNorm (((F_n_lp2 n).val.cast) - ((F_n_lp2 n) ∘ fun a ↦ s * a)) 2 volume < ⊤ := by - grw [eLpNorm_sub_le] + · simp + · simp + · simp + · simp + · rw [← lt_top_iff_ne_top] + have norm_sub_lt : eLpNorm (((F_n_lp2 n).val.cast) - ((F_n_lp2 n) ∘ fun a ↦ s * a)) 2 volume < ⊤ := by + grw [eLpNorm_sub_le (by norm_num)] rw [ENNReal.add_lt_top] refine ⟨?_, ?_⟩ - . exact Lp.eLpNorm_lt_top (F_n_lp2 n) - . - rw [MeasureTheory.eLpNorm_comp_measurePreserving] - . exact Lp.eLpNorm_lt_top (F_n_lp2 n) - . apply AEStronglyMeasurable.of_discrete - . exact measurePreserving_mul_left volume s - . apply AEStronglyMeasurable.of_discrete - . apply AEStronglyMeasurable.of_discrete - . simp - rw [MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm (by simp) (by simp)] at norm_sub_lt + · exact Lp.eLpNorm_lt_top (F_n_lp2 n) + · rw [MeasureTheory.eLpNorm_comp_measurePreserving] + · exact Lp.eLpNorm_lt_top (F_n_lp2 n) + · apply AEStronglyMeasurable.of_discrete + · exact measurePreserving_mul_left volume s + rw [MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm_toReal (by simp) (by simp) (by apply AEStronglyMeasurable.of_discrete)] at norm_sub_lt rw [lintegral_g_eq_add] at norm_sub_lt simp at norm_sub_lt exact norm_sub_lt - . - apply ENNReal.rpow_ne_top_of_nonneg - . simp - . apply f_n_sub_norm s (by rw [S_eq_Sinv]; simp [hs]) - . - unfold f_n_conv_delta_tendsto at f_n_limit + · apply ENNReal.rpow_ne_top_of_nonneg + · simp + · apply f_n_sub_norm s (by rw [S_eq_Sinv]; simp [hs]) + · unfold f_n_conv_delta_tendsto at f_n_limit simp at hs specialize f_n_limit ⟨s⁻¹, hs⟩ conv at f_n_limit => arg 1 intro n - rw [MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm (by simp) (by simp)] + rw [MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm_toReal (by simp) (by simp) (by apply AEStronglyMeasurable.of_discrete)] rw [lintegral_g_eq_add] simp_rw [f_conv_delta_helper] at f_n_limit @@ -625,20 +552,14 @@ lemma F_n_conv_mu_lim (f_n_limit: f_n_conv_delta_tendsto): simp simp_rw [← ENNReal.toReal_rpow] apply Filter.Tendsto.rpow_const - . - rw [← ENNReal.tendsto_toReal_iff] at f_n_limit - . exact f_n_limit - . - apply f_n_sub_norm s (by rw [S_eq_Sinv]; simp [hs]) - . simp - . simp - . intro n + · rw [← ENNReal.tendsto_toReal_iff] at f_n_limit + · exact f_n_limit + · apply f_n_sub_norm s (by rw [S_eq_Sinv]; simp [hs]) + · simp + · simp + · intro n rw [MeasureTheory.Lp.enorm_def] apply MeasureTheory.Lp.eLpNorm_ne_top - . simp - -#print axioms F_n_conv_mu_lim - -#synth TopologicalSpace ↥(Lp ℝ 2 volume (α := G)) + · simp end GeneratesNS diff --git a/Gromov/Harmonic/MuConv.lean b/Gromov/Harmonic/MuConv.lean index 0524576..18a9cf4 100644 --- a/Gromov/Harmonic/MuConv.lean +++ b/Gromov/Harmonic/MuConv.lean @@ -12,8 +12,6 @@ the telescoping identity `f_n_sub_conv`. public section -set_option linter.style.cdot false -set_option linter.style.whitespace false attribute [local implicit_reducible] Additive namespace GeneratesNS @@ -35,7 +33,7 @@ theorem mu_conv_eq_sum (m: ℕ): muConv m = fun g => (((1 : ℝ) / (#(S) : ℝ)) funext g simp [muConv, NTupleSum, mu, delta, Pi.single, Function.update] by_cases g_in_s: g ∈ S - . + · simp [g_in_s] conv => rhs @@ -46,21 +44,21 @@ theorem mu_conv_eq_sum (m: ℕ): muConv m = fun g => (((1 : ℝ) / (#(S) : ℝ)) ext a simp refine ⟨?_, ?_⟩ - . intro a_zero_eq + · intro a_zero_eq ext x simp have x_eq_zero: x = 0 := by exact Fin.fin_one_eq_zero x rw [x_eq_zero] exact a_zero_eq - . intro a_eq + · intro a_eq simp [a_eq] simp - . + · simp [g_in_s] right by_contra this - . + · simp at this obtain ⟨x, hx⟩ := this rw [← hx] at g_in_s @@ -77,7 +75,7 @@ theorem mu_conv_eq_sum (m: ℕ): muConv m = fun g => (((1 : ℝ) / (#(S) : ℝ)) rw [Summable.tsum_mul_left] simp_rw [Finset.sum_mul] rw [Summable.tsum_finsetSum] - . + · conv => lhs rhs @@ -85,11 +83,11 @@ theorem mu_conv_eq_sum (m: ℕ): muConv m = fun g => (((1 : ℝ) / (#(S) : ℝ)) intro x equals (Conv (muConv n) (delta x) ) g => rw [conv_eq_sum] - . + · unfold muConv unfold delta simp_rw [mul_comm] - . + · apply conv_exists_fin_supp right simp [delta] @@ -116,51 +114,51 @@ theorem mu_conv_eq_sum (m: ℕ): muConv m = fun g => (((1 : ℝ) / (#(S) : ℝ)) nth_rw 2 [pow_succ] simp rw [mul_comm] - simp only [mul_eq_mul_left_iff, inv_eq_zero, ne_eq, Nat.add_eq_zero, one_ne_zero, and_false, + simp only [mul_eq_mul_left_iff, inv_eq_zero, ne_eq, Nat.add_eq_zero_iff, one_ne_zero, and_false, and_self, not_false_eq_true, pow_eq_zero_iff, Nat.cast_eq_zero, Finset.card_eq_zero] left rw [← Finset.sum_attach] rw [← Finset.sum_product'] apply Fintype.sum_bijective (e := fun (x) => (fun (i: Fin (n + 1 + 1)) => if hi: i.val = 0 then x.fst else x.snd ⟨i - 1, by omega⟩)) - . + · refine ⟨?_, ?_⟩ - . + · intro a b hab simp at hab ext p - . + · have fst_eq := congrFun hab (⟨0, by omega⟩) simp at fst_eq rw [fst_eq] - . + · have p_lt_n_plus := p.prop have p_val_neq: p.val ≠ n + 1 := by omega have snd_eq := congrFun hab (⟨p + 1, by omega⟩) by_cases p_eq_zero: p = 0 - . + · simp [p_eq_zero] at snd_eq rw [p_eq_zero] rw [snd_eq] - . + · simp [p_eq_zero] at snd_eq rw [snd_eq] - . + · intro f use ((f (⟨0, by omega⟩)), fun i => f (⟨i + 1, by omega⟩)) funext i simp by_cases i_eq_zero: i = 0 - . simp [i_eq_zero] - . + · simp [i_eq_zero] + · simp [i_eq_zero] have i_val_neq_zero: i.val ≠ 0 := by simp [i_eq_zero] have one_le_i: 1 ≤ i.val := by omega simp [Nat.sub_add_cancel one_le_i] - . + · intro x simp only [delta] rw [Pi.single_apply] @@ -168,10 +166,10 @@ theorem mu_conv_eq_sum (m: ℕ): muConv m = fun g => (((1 : ℝ) / (#(S) : ℝ)) split_ifs - . + · rename _ => hi - simp [hi] - . + simp + · rename_i g_eq g_mul_neq apply_fun (fun y => (x.fst.val) * y ) at g_eq rw [← mul_assoc] at g_eq @@ -186,63 +184,62 @@ theorem mu_conv_eq_sum (m: ℕ): muConv m = fun g => (((1 : ℝ) / (#(S) : ℝ)) contradiction - . rename_i g_mul_neq g_eq + · rename_i g_mul_neq g_eq simp [List.ofFn_succ] at g_eq rw [← g_eq] at g_mul_neq simp at g_mul_neq - . rfl - . intro s hs + · rfl + · intro s hs simp [Pi.single_apply] rw [← summable_norm_iff] apply Summable.of_nonneg_of_le (f := fun a => ‖(fun f ↦ Conv f mu)^[n] mu ((Additive.toMul a))‖) - . + · intro x simp - . intro x + · intro x split_ifs - . rfl - . simp - . + · rfl + · simp + · rw [summable_norm_iff] have conv_finsupp := mu_conv_finsupp n unfold muConv at conv_finsupp apply summable_of_hasFiniteSupport apply Set.Finite.of_injOn (f := fun a => ( (Additive.toMul a))) (ht := conv_finsupp) - . + · intro a ha exact ha - . intro a ha b hb + · intro a ha b hb simp - -- TODO - deduplicate this with the above goal - . + · simp [Pi.single_apply] rw [← summable_norm_iff] apply Summable.of_nonneg_of_le (f := fun a => ‖(fun f ↦ Conv f mu)^[n] mu ((Additive.toMul a))‖) - . + · intro x simp - . intro x + · intro x split_ifs - . rfl - . simp - . + · rfl + · simp + · rw [summable_norm_iff] have conv_finsupp := mu_conv_finsupp n unfold muConv at conv_finsupp apply summable_of_hasFiniteSupport apply Set.Finite.of_injOn (f := fun a => ( (Additive.toMul a))) (ht := conv_finsupp) - . + · intro a ha exact ha - . intro a ha b hb + · intro a ha b hb simp - . + · apply conv_exists_fin_supp right - simp [delta] + simp apply Set.Finite.subset (ht := Function.support_const_smul_subset _ _) have supp_sum := Finset.support_sum (s := S) (f := fun s => Pi.single (M := fun _ : G => ℝ) s (1: ℝ)) conv => @@ -262,34 +259,34 @@ lemma mu_conv_nonneg (n: ℕ): ∀ g, 0 ≤ muConv n g := by | zero => simp [muConv, mu] split_ifs - . simp - . simp + · simp + · simp | succ n ih => rw [mu_conv_eq_sum] apply mul_nonneg - . simp - . + · simp + · simp [NTupleSum] apply Finset.sum_nonneg intro i hi simp [delta, Pi.single_apply] split_ifs - . simp - . simp + · simp + · simp lemma f_n_nonneg: ∀ n: ℕ, ∀ g: G, 0 ≤ f_n n g := by intro n g simp [f_n] apply mul_nonneg - . positivity - . apply Finset.sum_nonneg + · positivity + · apply Finset.sum_nonneg intro i hi apply mu_conv_nonneg lemma conv_laplce_norm (n: ℕ) (H_n: ℕ → G → ℝ): eLpNorm ((Laplace_b ((Conv (H_n n)) (f_n n)))) ⊤ (μ := volume (α := G)) ≤ eLpNorm (H_n n) ⊤ * (eLpNorm (Laplace_b (f_n n)) 1 (μ := volume (α := G))) := by rw [laplace_conv_eq_laplace_right] - . + · unfold Conv eta_reduce simp only [volume] @@ -307,16 +304,16 @@ lemma conv_laplce_norm (n: ℕ) (H_n: ℕ → G → ℝ): eLpNorm ((Laplace_b (( refine le_trans my_norm ?_ have hmul : ‖ContinuousLinearMap.mul ℝ ℝ‖ₑ ≤ 1 := by - rw [← ofReal_norm_eq_enorm, ENNReal.ofReal_le_one] + rw [← ofReal_norm, ENNReal.ofReal_le_one] exact ContinuousLinearMap.opNorm_mul_le ℝ ℝ rw [mul_assoc] exact le_trans (mul_le_mul_left hmul _) (le_of_eq (one_mul _)) - . + · apply conv_exists_fin_supp right exact f_n_fin_supp n - . apply f_n_nonneg - . exact f_n_fin_supp n + · apply f_n_nonneg + · exact f_n_fin_supp n lemma lintegral_g_eq_add (f: G → ENNReal): (∫⁻ (g: G), f g) = (∑' (g : G), f g) := by @@ -325,11 +322,11 @@ lemma lintegral_g_eq_add (f: G → ENNReal): (∫⁻ (g: G), f g) = (∑' (g : G lemma integral_eq_eq_sum (f: G → ℝ) (hf: Integrable f): (∫ (g: G), f g) = (∑' (g : G), f g) := by rw [MeasureTheory.integral_countable] - . + · simp [MeasureTheory.volume] simp_rw [my_haar_eq_count] simp - . apply hf + · apply hf lemma mu_norm_one (m: ℕ): MeasureTheory.eLpNorm (muConv m) 1 = 1 := by @@ -349,35 +346,35 @@ lemma mu_norm_one (m: ℕ): MeasureTheory.eLpNorm (muConv m) 1 = 1 := by rw [Real.enorm_of_nonneg (by apply Finset.sum_nonneg intro x hx - simp [delta, Pi.single_apply] + simp [Pi.single_apply] split_ifs - . simp - . simp + · simp + · simp )] rw [← ENNReal.ofReal_tsum_of_nonneg] simp [Pi.single_apply] - . intro g + · intro g apply Finset.sum_nonneg intro i simp [Pi.single_apply] split_ifs - . simp - . simp - . + · simp + · simp + · apply summable_sum intro i hi simp only [Pi.single_apply] apply summable_of_hasFiniteSupport apply Set.Finite.subset (s := {(List.ofFn i).unattach.prod}) - . simp - . intro a ha + · simp + · intro a ha simp simp at ha rw [ha] rw [Summable.tsum_finsetSum] - . + · conv => lhs rhs @@ -394,19 +391,18 @@ lemma mu_norm_one (m: ℕ): MeasureTheory.eLpNorm (muConv m) 1 = 1 := by rw [← ENNReal.ofReal_natCast] rw [← ENNReal.ofReal_pow] rw [← ENNReal.ofReal_mul] - . + · field_simp simp exact Finset.nonempty_iff_ne_empty.mp S_nonempty - . simp - . simp - . - -- TODO - deduplicate this with the above goal + · simp + · simp + · intro a ha apply summable_of_hasFiniteSupport apply Set.Finite.subset (s := {(List.ofFn a).unattach.prod}) - . simp - . intro a ha + · simp + · intro a ha simp simp at ha rw [ha] @@ -444,7 +440,7 @@ theorem f_n_norm_one (n: ℕ): MeasureTheory.eLpNorm (f_n n) 1 = 1 := by )] rw [Summable.tsum_finsetSum] - . + · have mu_norm := mu_norm_one simp [MeasureTheory.eLpNorm, MeasureTheory.eLpNorm'] at mu_norm simp_rw [lintegral_g_eq_add] at mu_norm @@ -457,12 +453,12 @@ theorem f_n_norm_one (n: ℕ): MeasureTheory.eLpNorm (f_n n) 1 = 1 := by )] rw [← ENNReal.ofReal_natCast] rw [← ENNReal.ofReal_mul] - . + · field_simp simp - . simp + · simp linarith - . + · simp @@ -507,7 +503,7 @@ theorem f_n_sub_conv (n: ℕ): MeasureTheory.eLpNorm ((f_n n) - (Conv (f_n n) simp rw [conv_sum] - . + · rw [← smul_sub] rw [← Finset.sum_sub_distrib] conv => @@ -553,8 +549,8 @@ theorem f_n_sub_conv (n: ℕ): MeasureTheory.eLpNorm ((f_n n) - (Conv (f_n n) simp simp at hx split_ifs - . simp - . omega + · simp + · omega )] @@ -567,11 +563,8 @@ theorem f_n_sub_conv (n: ℕ): MeasureTheory.eLpNorm ((f_n n) - (Conv (f_n n) _ ≤ ‖((n + 1): ℝ)⁻¹‖ₑ * MeasureTheory.eLpNorm ((mu - muConv (n + 1))) 1 MeasureTheory.volume := by apply MeasureTheory.eLpNorm_const_smul_le _ ≤ ‖((n + 1): ℝ)⁻¹‖ₑ * (MeasureTheory.eLpNorm ((mu)) 1 MeasureTheory.volume + (MeasureTheory.eLpNorm ((muConv (n + 1))) 1 MeasureTheory.volume)) := by - have sub_le := MeasureTheory.eLpNorm_sub_le (p := 1) (f := mu ) (g := muConv (n + 1)) (μ := MeasureTheory.volume) ?_ ?_ (by simp) - . - apply mul_le_mul_right sub_le - . apply MeasureTheory.AEStronglyMeasurable.of_discrete - . apply MeasureTheory.AEStronglyMeasurable.of_discrete + exact mul_le_mul' le_rfl (MeasureTheory.eLpNorm_sub_le (p := 1) + (f := mu) (g := muConv (n + 1)) (μ := MeasureTheory.volume) (by simp)) _ ≤ ENNReal.ofReal ((2: ℝ) / ((n + 1): ℝ)) := by rw [mu_norm_one] have mu_single_norm := mu_norm_one 0 @@ -590,11 +583,8 @@ theorem f_n_sub_conv (n: ℕ): MeasureTheory.eLpNorm ((f_n n) - (Conv (f_n n) field_simp simp positivity - . exact mu_finsupp + · exact mu_finsupp -#print axioms mu_conv_eq_sum -#print axioms f_n_norm_one -#print axioms f_n_sub_conv end GeneratesNS diff --git a/Gromov/Harmonic/Proposition318.lean b/Gromov/Harmonic/Proposition318.lean index 7d7da9c..c36f3cc 100644 --- a/Gromov/Harmonic/Proposition318.lean +++ b/Gromov/Harmonic/Proposition318.lean @@ -12,8 +12,6 @@ sequence. public section -set_option linter.style.cdot false -set_option linter.style.whitespace false attribute [local implicit_reducible] Additive namespace GeneratesNS @@ -31,176 +29,164 @@ open MeasureTheory open scoped RealInnerProductSpace -set_option maxHeartbeats 600000 in -lemma laplace_g_n (n: ℕ) (hn: 0 < n) (hf: f_n_conv_delta_tendsto): ∃ g: (Lp ℝ 2 volume (α := G)), ‖Laplace g‖ ≤ (1 : ℝ) / n ∧ ⟪Laplace g, g⟫ = 1 := by - - let eps := ((1: ℝ) / n)^2 - -- selfAdjoint.mem_spectrum_eq_re +private lemma laplace_spectrum_nonisolated (n : ℕ) (hn : 0 < n) + (hf : f_n_conv_delta_tendsto) : + spectrum ℝ (Laplace_linear.mkContinuous _ laplace_bounded') ∩ + Set.Ioo 0 (((1 : ℝ) / n)^2) ≠ ∅ := by + let eps := ((1 : ℝ) / n)^2 + let Δ := Laplace_linear.mkContinuous _ laplace_bounded' + change spectrum ℝ Δ ∩ Set.Ioo 0 eps ≠ ∅ - let P: Polynomial ℝ := (Polynomial.X^2 - eps • Polynomial.X) + by_contra! + have zero_isolated: spectrum ℝ Δ ∩ (Set.Ico 0 eps) = {0} := by + ext a + simp + refine ⟨?_, ?_⟩ + · + intro ha + obtain ⟨a_mem_spec, a_range⟩ := ha + by_contra a_nonzero + have a_mem: a ∈ Set.Ioo 0 eps := by + grind - let Δ := Laplace_linear.mkContinuous _ (laplace_bounded') + have a_mem_empty: a ∈ (∅ : Set ℝ) := by + rw [← this] + grind - have spec_inter: spectrum ℝ Δ ∩ Set.Ioo 0 eps ≠ ∅ := by - by_contra! - have zero_isolated: spectrum ℝ Δ ∩ (Set.Ico 0 eps) = {0} := by - ext a - simp - refine ⟨?_, ?_⟩ - . - intro ha - obtain ⟨a_mem_spec, a_range⟩ := ha - by_contra a_nonzero - have a_mem: a ∈ Set.Ioo 0 eps := by - grind + simp at a_mem_empty + · + intro ha + simp [ha] + refine ⟨?_, by simp [eps, hn]⟩ + apply laplace_spectrum_contains_zero hf + + have zero_mem := laplace_spectrum_contains_zero hf + rw [spectrum.mem_iff] at zero_mem + simp at zero_mem + + let ramp: ℝ → ℝ := fun x => max 0 (min 1 (x / eps)) + + have self_adjoint_cx_del: IsSelfAdjoint (Cx.mapCLM Δ) := by + apply Cx.isSelfAdjoint_mapCLM + apply Δ_symmetric.isSelfAdjoint + + + let Q := cfc (1 - ramp) (Cx.mapCLM Δ) + have laplace_q: (Cx.mapCLM Δ) * Q = cfc (0: ℝ → ℝ) (Cx.mapCLM Δ) := by + unfold Q + nth_rw 1 [← cfc_id (a := Cx.mapCLM Δ) ℝ] + rw [← cfc_mul (hf := by exact continuousOn_id) (hg := by fun_prop)] + apply cfc_congr + intro x hx + simp [ramp, max_def'] + norm_num + split_ifs + · + rw [Cx.spectrum_mapCLM] at hx + rename_i x_div + apply Δ_spectrum_subset at hx + simp [eps] at x_div + have x_nonpos := nonpos_of_mul_nonpos_left x_div (by simp [hn]) + left + simp at hx + grind + · simp [min_def'] + split_ifs + · - have a_mem_empty: a ∈ (∅ : Set ℝ) := by - rw [← this] - grind + by_cases x_eq: x = eps + · simp [x_eq, eps] + field_simp + simp + · + rename_i x_div_le + rw [div_le_one₀ (by simp [eps]; positivity)] at x_div_le + have x_lt: x < eps := by + grind - simp at a_mem_empty - . - intro ha - simp [ha] - refine ⟨?_, by simp [eps, hn]⟩ - apply laplace_spectrum_contains_zero hf - - have zero_mem := laplace_spectrum_contains_zero hf - rw [spectrum.mem_iff] at zero_mem - simp at zero_mem - - let ramp: ℝ → ℝ := fun x => max 0 (min 1 (x / eps)) - - have self_adjoint_cx_del: IsSelfAdjoint (Cx.mapCLM Δ) := by - apply Cx.isSelfAdjoint_mapCLM - apply Δ_symmetric.isSelfAdjoint - - - let Q := cfc (1 - ramp) (Cx.mapCLM Δ) - have laplace_q: (Cx.mapCLM Δ) * Q = cfc (0: ℝ → ℝ) (Cx.mapCLM Δ) := by - unfold Q - nth_rw 1 [← cfc_id (a := Cx.mapCLM Δ) ℝ] - rw [← cfc_mul (hf := by exact continuousOn_id) (hg := by fun_prop)] - apply cfc_congr - intro x hx - simp [ramp, max_def'] - norm_num - split_ifs - . - rw [Cx.spectrum_mapCLM] at hx - rename_i x_div - apply Δ_spectrum_subset at hx - simp [eps] at x_div - have x_nonpos := nonpos_of_mul_nonpos_left x_div (by simp [hn]) - left - simp at hx - grind - . simp [min_def'] - split_ifs - . - by_cases x_eq: x = eps - . simp [x_eq, eps] - field_simp + have x_mem_zero: x ∈ ({0} : Set ℝ) := by + rw [← zero_isolated] simp - . - rename_i x_div_le - rw [div_le_one₀ (by simp [eps]; positivity)] at x_div_le - have x_lt: x < eps := by + refine ⟨?_, ?_⟩ + · + rw [Cx.spectrum_mapCLM] at hx + exact hx + · + rw [Cx.spectrum_mapCLM] at hx + apply Δ_spectrum_subset at hx + simp at hx grind + simp at x_mem_zero + simp [x_mem_zero] + · simp - have x_mem_zero: x ∈ ({0} : Set ℝ) := by - rw [← zero_isolated] - simp - refine ⟨?_, ?_⟩ - . - rw [Cx.spectrum_mapCLM] at hx - exact hx - . - rw [Cx.spectrum_mapCLM] at hx - apply Δ_spectrum_subset at hx - simp at hx - grind - - simp at x_mem_zero - simp [x_mem_zero] - . simp - - - simp at laplace_q - have one_mem_q_spec: 1 ∈ spectrum ℝ Q := by - rw [cfc_map_spectrum (hf := by fun_prop)] - simp [ramp] - use 0 - rw [Cx.spectrum_mapCLM] - refine ⟨laplace_spectrum_contains_zero hf, ?_⟩ - right - simp - have nontrivial_cx: Nontrivial (Cx ↥(Lp ℝ 2 volume (α := G)) →L[ℂ] Cx ↥(Lp ℝ 2 volume (α := G))) := by + simp at laplace_q + have one_mem_q_spec: 1 ∈ spectrum ℝ Q := by + rw [cfc_map_spectrum (hf := by fun_prop)] + simp [ramp] + use 0 + rw [Cx.spectrum_mapCLM] + refine ⟨laplace_spectrum_contains_zero hf, ?_⟩ + right + simp - use 1 - use 0 - simp - rw [ContinuousLinearMap.ext_iff] - simp - let hf := (finsupp_lp_top (Pi.single 1 1) (by - simp - ) 2) - rw [← my_haar_eq_count] at hf - use (hf.toLp, 0) - apply_fun (fun a => a.fst) - simp - rw [MeasureTheory.Lp.ext_iff] - have haar_eq_volume: myHaar = volume := by - simp [volume] - simp_rw [haar_eq_volume] - rw [ae_eq_everywhere.mp (MeasureTheory.MemLp.coeFn_toLp _)] - simp - rw [funext_iff] - simp - use 1 + have nontrivial_cx: Nontrivial (Cx ↥(Lp ℝ 2 volume (α := G)) →L[ℂ] Cx ↥(Lp ℝ 2 volume (α := G))) := by + + use 1 + use 0 + simp + rw [ContinuousLinearMap.ext_iff] + simp + let hf := (finsupp_lp_top (Pi.single 1 1) (by simp + ) 2) + rw [← my_haar_eq_count] at hf + use (hf.toLp, 0) + apply_fun (fun a => a.fst) + simp + rw [MeasureTheory.Lp.ext_iff] + have haar_eq_volume: myHaar = volume := by + simp [volume] + simp_rw [haar_eq_volume] + rw [ae_eq_everywhere.mp (MeasureTheory.MemLp.coeFn_toLp _)] + simp + rw [funext_iff] + simp + use 1 + simp - have Q_nonzero: Q ≠ 0 := by - by_contra! - simp [this] at one_mem_q_spec - - apply ContinuousLinearMap.exists_ne_zero at Q_nonzero - obtain ⟨x, hx⟩ := Q_nonzero - have laplace_q_x: (Cx.mapCLM Δ) (Q x) = 0 := by - rw [← ContinuousLinearMap.mul_apply] - simp [laplace_q] - - by_cases fst_nonzero: (Q x).fst ≠ 0 - . - simp at laplace_q_x - apply_fun (fun a => a.fst) at laplace_q_x - simp at laplace_q_x - simp [Δ, LinearMap.mkContinuous, Laplace_linear] at laplace_q_x - apply laplace_zero_iff_zero at laplace_q_x - contradiction - . - have snd_nonzero: (Q x).snd ≠ 0 := by - by_contra! - simp at fst_nonzero - have Q_zero: (Q x) = 0 := by - apply Cx.ext - all_goals { - simp - grind - } - contradiction + have Q_nonzero: Q ≠ 0 := by + by_contra! + simp [this] at one_mem_q_spec + + apply ContinuousLinearMap.exists_ne_zero at Q_nonzero + obtain ⟨x, hx⟩ := Q_nonzero + have laplace_q_x: (Cx.mapCLM Δ) (Q x) = 0 := by + rw [← mul_apply_eq_comp] + simp [laplace_q] + + have hfst : Laplace (Q x).fst = 0 := by + have h := congrArg Cx.fst laplace_q_x + simpa [Δ, LinearMap.mkContinuous, Laplace_linear] using h + have hsnd : Laplace (Q x).snd = 0 := by + have h := congrArg Cx.snd laplace_q_x + simpa [Δ, LinearMap.mkContinuous, Laplace_linear] using h + have hz : Q x = 0 := Cx.ext (laplace_zero_iff_zero _ hfst) (laplace_zero_iff_zero _ hsnd) + exact hx hz + +lemma laplace_g_n (n: ℕ) (hn: 0 < n) (hf: f_n_conv_delta_tendsto): ∃ g: (Lp ℝ 2 volume (α := G)), ‖Laplace g‖ ≤ (1 : ℝ) / n ∧ ⟪Laplace g, g⟫ = 1 := by - -- TODO - deduplicate this - simp at laplace_q_x - apply_fun (fun a => a.snd) at laplace_q_x - simp at laplace_q_x - simp [Δ, LinearMap.mkContinuous, Laplace_linear] at laplace_q_x - apply laplace_zero_iff_zero at laplace_q_x - contradiction + let eps := ((1: ℝ) / n)^2 + -- selfAdjoint.mem_spectrum_eq_re + + let P: Polynomial ℝ := (Polynomial.X^2 - eps • Polynomial.X) + + let Δ := Laplace_linear.mkContinuous _ (laplace_bounded') + have spec_inter := laplace_spectrum_nonisolated n hn hf rw [← Set.nonempty_iff_ne_empty] at spec_inter obtain ⟨a, ha⟩ := spec_inter @@ -217,21 +203,21 @@ lemma laplace_g_n (n: ℕ) (hn: 0 < n) (hf: f_n_conv_delta_tendsto): ∃ g: (Lp have p_a_neg: P.eval a < 0 := by simp [P] - simp at ha - nlinarith + change 0 < a ∧ a < eps at a_lt + nlinarith [a_lt.1, a_lt.2] have eval_symm: (((Polynomial.aeval Δ) P)).IsSymmetric := by simp [P] apply LinearMap.IsSymmetric.sub - . apply LinearMap.IsSymmetric.pow + · apply LinearMap.IsSymmetric.pow apply Δ_symmetric - . apply LinearMap.IsSymmetric.smul - . simp - . apply Δ_symmetric + · apply LinearMap.IsSymmetric.smul + · simp + · apply Δ_symmetric have not_pos := ContinuousLinearMap.IsPositive.spectrumRestricts (f := (Polynomial.aeval Δ P)).mt ?_ - . + · simp [ContinuousLinearMap.IsPositive, eval_symm] at not_pos obtain ⟨x, hx, x_inner⟩ := not_pos simp [ContinuousLinearMap.reApplyInnerSelf, P] at x_inner @@ -253,7 +239,7 @@ lemma laplace_g_n (n: ℕ) (hn: 0 < n) (hf: f_n_conv_delta_tendsto): ∃ g: (Lp use ((√⟪Laplace ⟨x, hx⟩, ⟨x, hx⟩⟫)⁻¹) • ⟨x, hx⟩ rw [inner_sub_left] at x_inner refine ⟨?_, ?_⟩ - . + · rw [norm_eq_sqrt_real_inner] simp [Δ, LinearMap.mkContinuous, Laplace_linear] at x_inner rw [← laplace_self_adjoint] at x_inner @@ -263,19 +249,19 @@ lemma laplace_g_n (n: ℕ) (hn: 0 < n) (hf: f_n_conv_delta_tendsto): ∃ g: (Lp rw [norm_smul] simp rw [← Real.lt_sqrt] at x_inner - . grw [x_inner] + · grw [x_inner] rw [Real.sqrt_mul] - ring + ring_nf rw [abs_of_nonneg] - . + · field_simp simp [eps] grind - . simp - . simp [eps] - . simp + · simp + · simp [eps] + · simp - . + · rw [laplace_smul] rw [inner_smul_left, inner_smul_right] simp @@ -283,7 +269,7 @@ lemma laplace_g_n (n: ℕ) (hn: 0 < n) (hf: f_n_conv_delta_tendsto): ∃ g: (Lp rw [Real.sq_sqrt] rw [← laplace_self_adjoint] apply laplace_positive_semidefinite - . rw [SpectrumRestricts.nnreal_iff] + · rw [SpectrumRestricts.nnreal_iff] simp use P.eval a @@ -297,7 +283,6 @@ lemma laplace_g_n (n: ℕ) (hn: 0 < n) (hf: f_n_conv_delta_tendsto): ∃ g: (Lp -- This whole proof is completely wrong - it needs to use the spectral theorem -#print axioms laplace_g_n lemma measure_preserving_inv: MeasurePreserving Inv.inv ((MeasureTheory.volume (α := G))) (MeasureTheory.volume (α := G)) := { @@ -318,7 +303,7 @@ noncomputable def G_n (n: ℕ) (hn: 0 < n) (hf: f_n_conv_delta_tendsto) := Class lemma lp_summable {p: ℕ} (hp: 0 < p) (f: (Lp ℝ p volume (α := G))): Summable (fun g: G => |(f g)|^p) := by - have f_norm := (MeasureTheory.Lp.memLp f).2 + have f_norm := (MeasureTheory.Lp.memLp f).eLpNorm_lt_top simp [eLpNorm, eLpNorm'] at f_norm have not_le: ¬(p = 0) := by linarith simp [not_le] at f_norm @@ -353,9 +338,9 @@ lemma lp2_summable (f: (Lp ℝ 2 volume (α := G))): Summable (fun g: G => (f g) lemma summable_f_mul_translate (f: (Lp ℝ 2 volume (α := G))) (i: G): Summable (fun x => (f x) * (f (i * x))) := by - have lp_mul := (MeasureTheory.MemLp.mul (φ := f) (f := fun x => f (i * x)) (p := 2) (q := 2) (r := 1) (μ := volume) ?_ ?_).2 - . - simp [MemLp, eLpNorm, eLpNorm'] at lp_mul + have lp_mul := (MeasureTheory.MemLp.mul (φ := f) (f := fun x => f (i * x)) (p := 2) (q := 2) (r := 1) (μ := volume) ?_ ?_).eLpNorm_lt_top + · + simp [eLpNorm, eLpNorm'] at lp_mul rw [lintegral_g_eq_add] at lp_mul simp [Real.enorm_eq_ofReal_abs] at lp_mul simp [← ENNReal.ofReal_mul] at lp_mul @@ -366,23 +351,22 @@ lemma summable_f_mul_translate (f: (Lp ℝ 2 volume (α := G))) (i: G): Summable intro x rw [ENNReal.toReal_ofReal (by apply mul_nonneg - . simp - . simp + · simp + · simp )] apply Summable.of_abs simp_rw [abs_mul] exact lp_mul - . + · apply Lp.memLp f + · rw [← Function.comp_def] apply MeasureTheory.MemLp.comp_measurePreserving (ν := volume) - . apply MeasureTheory.Lp.memLp f - . exact measurePreserving_mul_left volume i - . apply Lp.memLp f + · apply MeasureTheory.Lp.memLp f + · exact measurePreserving_mul_left volume i -- Note - this is stated incorrectly in Vikman -- The RHS should have a squared norm -set_option maxRecDepth 40000 in lemma proposition_3_18 (f: (Lp ℝ 2 volume (α := G))): (∑' g: G, (f g) * (Laplace f) g) = ((2) * (#(S) : ℝ))⁻¹ * ∑ s ∈ S, ‖(f - (conv_finsupp_lp2 f (delta s) (by simp [delta])))‖^2 := by simp_rw [Laplace] simp_rw [conv_mu_lp2] @@ -431,7 +415,7 @@ lemma proposition_3_18 (f: (Lp ℝ 2 volume (α := G))): (∑' g: G, (f g) * (La rw [Summable.tsum_mul_left] rw [Summable.tsum_mul_left] - have f_norm := MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm (p := 2) (by simp) (by simp) (f := f.val.cast) (μ := volume (α := G)) + have f_norm := MeasureTheory.eLpNorm_eq_lintegral_rpow_enorm_toReal (p := 2) (by simp) (by simp) (f := f.val.cast) (μ := volume (α := G)) (MeasureTheory.Lp.aestronglyMeasurable f) simp_rw [lintegral_g_eq_add] at f_norm simp [enorm] at f_norm apply_fun ENNReal.toReal at f_norm @@ -488,21 +472,19 @@ lemma proposition_3_18 (f: (Lp ℝ 2 volume (α := G))): (∑' g: G, (f g) * (La conv at inner_f_conv => intro a rhs - -- TODO - deduplicate this with the 'have lp_mul' block above rw [MeasureTheory.integral_countable (by simp [f_conv_delta] simp [Integrable] - refine ⟨by apply AEStronglyMeasurable.of_discrete, ?_⟩ simp [HasFiniteIntegral] simp [Real.enorm_eq_ofReal_abs] rw [lintegral_g_eq_add] rw [lt_top_iff_ne_top] simp_rw [← ENNReal.ofReal_mul (abs_nonneg _), ← abs_mul] rw [← ENNReal.ofReal_tsum_of_nonneg] - . apply ENNReal.ofReal_ne_top - . intro n + · apply ENNReal.ofReal_ne_top + · intro n positivity - . + · apply Summable.abs simp_rw [mul_comm] apply summable_f_mul_translate @@ -545,28 +527,28 @@ lemma proposition_3_18 (f: (Lp ℝ 2 volume (α := G))): (∑' g: G, (f g) * (La rw [Finset.sum_add_distrib, Finset.sum_sub_distrib, ← Finset.mul_sum] eta_reduce ring - . apply summable_sum + · apply summable_sum intro s hs simp_rw [f_conv_delta] apply summable_f_mul_translate - . + · apply tsum_nonneg intro g apply sq_nonneg - . simp - . apply summable_sum + · simp + · apply summable_sum intro s hs apply lp2_summable - . + · apply Summable.mul_left apply summable_sum intro s hs apply lp2_summable - . simp_rw [mul_assoc] + · simp_rw [mul_assoc] apply Summable.mul_left simp_rw [← pow_two] apply lp2_summable - . simp_rw [mul_assoc] + · simp_rw [mul_assoc] apply Summable.mul_left rw [ae_eq_everywhere.mp (MeasureTheory.MemLp.coeFn_toLp _)] simp_rw [← mul_assoc] @@ -578,14 +560,14 @@ lemma proposition_3_18 (f: (Lp ℝ 2 volume (α := G))): (∑' g: G, (f g) * (La simp_rw [mul_assoc] apply Summable.mul_left apply summable_f_mul_translate - . + · apply Summable.mul_left rw [ae_eq_everywhere.mp (MeasureTheory.MemLp.coeFn_toLp _)] simp_rw [mul_sub] apply Summable.sub - . simp_rw [← pow_two] + · simp_rw [← pow_two] apply lp2_summable - . + · simp_rw [← mul_assoc] simp_rw [Finset.mul_sum] apply summable_sum @@ -611,8 +593,6 @@ lemma g_n_conv_norm (n: ℕ) (hn: 0 < n) (hf: f_n_conv_delta_tendsto): ⟪Laplac exact g_n_prop.2 -#print sorries proposition_3_18 -#print axioms proposition_3_18 lemma g_sub_norm_gt (hf: f_n_conv_delta_tendsto) (n: ℕ) : ∃ s ∈ S, ‖(G_n (n + 1) (by simp) hf) - (conv_finsupp_lp2 (G_n (n + 1) (by simp) hf) (delta s) (by simp [delta]))‖^2 > 1 := by @@ -623,7 +603,7 @@ lemma g_sub_norm_gt (hf: f_n_conv_delta_tendsto) (n: ℕ) : ∃ s ∈ S, ‖(G_n have g_n_prop := (Classical.choose_spec (laplace_g_n (n + 1) (by simp) hf)).2 have real_inner : ∀ a b : ℝ, ⟪a, b⟫ = b * a := fun a b => rfl rw [integral_eq_eq_sum] at g_inner_laplace - . + · simp_rw [real_inner] at g_inner_laplace simp_rw [← g_inner_laplace] at sum_norm nth_rw 1 [G_n] at sum_norm @@ -634,15 +614,15 @@ lemma g_sub_norm_gt (hf: f_n_conv_delta_tendsto) (n: ℕ) : ∃ s ∈ S, ‖(G_n rw [← sum_norm] at card_le simp at card_le rw [mul_le_iff_le_one_left] at card_le - . norm_num at card_le - . simp + · norm_num at card_le + · simp have foo := S_nonempty grind - . + · simp grind - . + · rw [MeasureTheory.L2.inner_def] at g_n_prop apply MeasureTheory.integrable_of_integral_eq_one at g_n_prop exact g_n_prop @@ -704,14 +684,14 @@ lemma laplace_b_sub (f g: G → ℝ): Laplace_b (f - g) = Laplace_b f - Laplace_ simp [Laplace_b] nth_rw 3 [sub_eq_add_neg] rw [conv_add_left] - . + · rw [conv_neg_left] ring_nf - . + · apply conv_exists_fin_supp right apply mu_finsupp - . apply conv_exists_fin_supp + · apply conv_exists_fin_supp right apply mu_finsupp diff --git a/Gromov/Harmonic/SelfAdjoint.lean b/Gromov/Harmonic/SelfAdjoint.lean index af09060..21e136c 100644 --- a/Gromov/Harmonic/SelfAdjoint.lean +++ b/Gromov/Harmonic/SelfAdjoint.lean @@ -12,38 +12,34 @@ public import Gromov.Harmonic.LaplaceLinear public section -set_option linter.style.cdot false -set_option linter.style.whitespace false attribute [local implicit_reducible] Additive namespace GeneratesNS open Generates -variable [hGS: Generates] +variable [hGS : Generates] include hGS -variable {V: Submodule ℝ LipschitzH} [V_finite: FiniteDimensional ℝ V] [Nontrivial V] +variable {V : Submodule ℝ LipschitzH} [V_finite : FiniteDimensional ℝ V] [Nontrivial V] open scoped Finset open scoped Pointwise open scoped Convolution open MeasureTheory -lemma laplace_smul (k: ℝ) (f: (Lp ℝ 2 volume (α := G))): Laplace (k • f) = k • (Laplace f) := by +lemma laplace_smul (k : ℝ) (f : (Lp ℝ 2 volume (α := G))) : Laplace (k • f) = k • (Laplace f) := by simp [Laplace, conv_mu_lp2] simp_rw [ae_eq_everywhere.mp (MeasureTheory.Lp.coeFn_smul _ _)] simp_rw [conv_smul] rw [MeasureTheory.MemLp.toLp_const_smul] rw [smul_sub] - -lemma norm_conv_mu_le (f: (Lp ℝ 2 volume (α := G))): ‖conv_mu_lp2 f‖ ≤ ‖f‖ := by +lemma norm_conv_mu_le (f : (Lp ℝ 2 volume (α := G))) : ‖conv_mu_lp2 f‖ ≤ ‖f‖ := by simp [conv_mu_lp2] simp [f_conv_mu] simp_rw [← smul_eq_mul] rw [← Pi.smul_def] rw [MeasureTheory.eLpNorm_const_smul] - -- TODO - deduplicate this with 'laplace_bounded' conv => lhs rhs @@ -53,13 +49,13 @@ lemma norm_conv_mu_le (f: (Lp ℝ 2 volume (α := G))): ‖conv_mu_lp2 f‖ ≤ funext g simp - have card_s_ne: (#S : ℝ) ≠ 0 := by + have card_s_ne : (#S : ℝ) ≠ 0 := by simp have foo := hS simp at foo exact Finset.nonempty_iff_ne_empty.mp foo - grw [MeasureTheory.eLpNorm_sum_le] + grw [MeasureTheory.eLpNorm_sum_le (by norm_num)] simp_rw [← Function.comp_def] conv => lhs @@ -77,16 +73,13 @@ lemma norm_conv_mu_le (f: (Lp ℝ 2 volume (α := G))): ‖conv_mu_lp2 f‖ ≤ simp [MeasureTheory.volume] } )] - . simp + · simp field_simp rfl - . - apply WithTop.mul_ne_top - . - rw [Real.enorm_of_nonneg (by simp)] + · apply WithTop.mul_ne_top + · rw [Real.enorm_of_nonneg (by simp)] apply ENNReal.ofReal_ne_top - . - apply ENNReal.sum_ne_top.mpr + · apply ENNReal.sum_ne_top.mpr intro s hs rw [← Function.comp_def] conv => @@ -101,19 +94,14 @@ lemma norm_conv_mu_le (f: (Lp ℝ 2 volume (α := G))): ‖conv_mu_lp2 f‖ ≤ } )] rw [← lt_top_iff_ne_top] - apply (MeasureTheory.Lp.memLp f).2 - . intro s hs - apply AEStronglyMeasurable.of_discrete - . - simp + exact MeasureTheory.Lp.eLpNorm_lt_top f open scoped RealInnerProductSpace -lemma inner_laplace_zero (f: (Lp ℝ 2 volume (α := G))) (hf: ⟪Laplace f, f⟫ = 0): Laplace f = 0 := by +lemma inner_laplace_zero (f : (Lp ℝ 2 volume (α := G))) (hf : ⟪Laplace f, f⟫ = 0) : Laplace f = 0 := by have inner_le := real_inner_le_norm (conv_mu_lp2 f) f - by_cases norm_f_zero: ‖f‖ = 0 - . - simp at norm_f_zero + by_cases norm_f_zero : ‖f‖ = 0 + · simp at norm_f_zero simp [Laplace, conv_mu_lp2] simp [f_conv_mu] simp_rw [norm_f_zero] @@ -132,7 +120,7 @@ lemma inner_laplace_zero (f: (Lp ℝ 2 volume (α := G))) (hf: ⟪Laplace f, f nth_rw 2 [mul_comm] at inner_le rw [mul_le_mul_iff_of_pos_left] at inner_le have conv_le_f := norm_conv_mu_le f - have f_norm_eq: ‖f‖ = ‖conv_mu_lp2 f‖ := by + have f_norm_eq : ‖f‖ = ‖conv_mu_lp2 f‖ := by linarith have f_sub_norm := norm_sub_sq_real f (conv_mu_lp2 f) @@ -147,8 +135,7 @@ lemma inner_laplace_zero (f: (Lp ℝ 2 volume (α := G))) (hf: ⟪Laplace f, f simpa [Laplace] using f_sub_norm simpa using norm_f_zero - -lemma F_n_norm_eq_one: ∀ n, MeasureTheory.eLpNorm (F_n n) 2 MeasureTheory.volume (α := G) = 1 := by +lemma F_n_norm_eq_one : ∀ n, MeasureTheory.eLpNorm (F_n n) 2 MeasureTheory.volume (α := G) = 1 := by simp [eLpNorm, eLpNorm', lintegral_g_eq_add] simp [F_n, Real.enorm_eq_ofReal_abs, ← ENNReal.ofReal_pow] @@ -160,41 +147,36 @@ lemma F_n_norm_eq_one: ∀ n, MeasureTheory.eLpNorm (F_n n) 2 MeasureTheory.volu simp [f_n_nonneg, abs_of_nonneg] at norm_one simp [norm_one] - -lemma harmonic_abs_max_implies_const (f: G → ℝ) (hf: Laplace_b f = 0) (a: G) (h_max: ∀ g: G, |f g| ≤ |f a|): f = fun _ => f a := by - by_cases f_a_pos: 0 ≤ f a - . - have lt_f_a: ∀ g: G, f g ≤ f a := by +lemma harmonic_abs_max_implies_const (f : G → ℝ) (hf : Laplace_b f = 0) (a : G) (h_max : ∀ g : G, |f g| ≤ |f a|) : f = fun _ => f a := by + by_cases f_a_pos : 0 ≤ f a + · have lt_f_a : ∀ g : G, f g ≤ f a := by intro g - by_cases f_g_pos: 0 ≤ f g - . specialize h_max g + by_cases f_g_pos : 0 ≤ f g + · specialize h_max g rw [abs_eq_self.mpr ?_] at h_max rw [abs_eq_self.mpr f_a_pos] at h_max - . exact h_max - . exact f_g_pos - . linarith + · exact h_max + · exact f_g_pos + · linarith exact harmonic_maximum_implies_const f hf a lt_f_a - . - have f_neg_le: ∀ g, (-f) g ≤ (-f) a := by + · have f_neg_le : ∀ g, (-f) g ≤ (-f) a := by intro g simp at f_a_pos simp specialize h_max g rw [abs_of_neg f_a_pos] at h_max - by_cases f_g_pos: 0 ≤ f g - . rw [abs_of_nonneg f_g_pos] at h_max + by_cases f_g_pos : 0 ≤ f g + · rw [abs_of_nonneg f_g_pos] at h_max linarith - . simp at f_g_pos + · simp at f_g_pos rw [abs_of_neg f_g_pos] at h_max linarith have neg_const := harmonic_maximum_implies_const (-f) ?_ a f_neg_le - . - apply_fun (fun h => -h) at neg_const + · apply_fun (fun h => -h) at neg_const simp at neg_const rw [Pi.neg_def] at neg_const simpa using neg_const - . - simp_rw [Laplace_b] + · simp_rw [Laplace_b] simp_rw [Laplace_b] at hf conv => lhs @@ -210,13 +192,10 @@ lemma harmonic_abs_max_implies_const (f: G → ℝ) (hf: Laplace_b f = 0) (a: G rw [sub_eq_zero] at hf exact hf.symm - -set_option maxHeartbeats 500000 in -lemma laplace_zero_iff_zero (g: (Lp ℝ 2 volume (α := G))) (eq_zero: Laplace g = 0): g = 0 := by - by_cases g_has_maximum: ∃ a: G, ∀ b: G, ‖g b‖ ≤ ‖g a‖ - . - obtain ⟨a, ha⟩ := g_has_maximum - have laplace_b_zero: Laplace_b g = 0 := by +lemma laplace_zero_iff_zero (g : (Lp ℝ 2 volume (α := G))) (eq_zero : Laplace g = 0) : g = 0 := by + by_cases g_has_maximum : ∃ a : G, ∀ b : G, ‖g b‖ ≤ ‖g a‖ + · obtain ⟨a, ha⟩ := g_has_maximum + have laplace_b_zero : Laplace_b g = 0 := by simp [Laplace, conv_mu_lp2, f_conv_mu] at eq_zero simp_rw [Laplace_b, f_conv_mu] apply_fun (fun f => f.val.cast) at eq_zero @@ -245,8 +224,7 @@ lemma laplace_zero_iff_zero (g: (Lp ℝ 2 volume (α := G))) (eq_zero: Laplace g rw [← not_infinite_iff_finite] at new_g_const_zero simp [hGS.g_infinite] at new_g_const_zero - - have g_eq_zero: g.val.cast = 0 := by + have g_eq_zero : g.val.cast = 0 := by rw [g_const] rw [new_g_const_zero] ext a @@ -256,16 +234,15 @@ lemma laplace_zero_iff_zero (g: (Lp ℝ 2 volume (α := G))) (eq_zero: Laplace g rw [ae_eq_everywhere] rw [ae_eq_everywhere.mp (MeasureTheory.Lp.coeFn_zero _ _ _)] exact g_eq_zero - . rename _ => g_no_maximum + · rename _ => g_no_maximum simp at g_no_maximum - have integrable_g := MeasureTheory.MemLp.integrable_sq (MeasureTheory.Lp.memLp g) - simp [Integrable, HasFiniteIntegral] at integrable_g - obtain ⟨_, integral_lt⟩ := integrable_g + have integral_lt := MeasureTheory.MemLp.integrable_sq (MeasureTheory.Lp.memLp g) + simp [Integrable, HasFiniteIntegral] at integral_lt rw [lintegral_g_eq_add] at integral_lt rw [lt_top_iff_ne_top] at integral_lt by_contra g_ne_zero simp at g_ne_zero - have nonzero_val: ∃ a: G, g a ≠ 0 := by + have nonzero_val : ∃ a : G, g a ≠ 0 := by rw [MeasureTheory.Lp.ext_iff] at g_ne_zero rw [ae_eq_everywhere] at g_ne_zero rw [ae_eq_everywhere.mp (MeasureTheory.Lp.coeFn_zero _ _ _)] at g_ne_zero @@ -284,26 +261,20 @@ lemma laplace_zero_iff_zero (g: (Lp ℝ 2 volume (α := G))) (eq_zero: Laplace g -- Obtain an element greater than the maximum obtain ⟨p, hp⟩ := g_no_maximum m have p_gt := hm (j := p) ?_ ?_ - . - have not_g_le := not_lt_of_ge p_gt + · have not_g_le := not_lt_of_ge p_gt contradiction - . - simp + · simp grw [m_in_g] rw [← ENNReal.toReal_le_toReal] - . - simp + · simp rw [sq_le_sq] linarith - . simp - . simp + · simp + · simp linarith - --- Proposition 3.17.1: "∆ is bounded" from Vikman --- The paper also proves that the Laplace operator is self-adjoint as part of this step, --- but we split it out -lemma laplace_bounded (f: (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G)))): ‖(Laplace f)‖ₑ ≤ 2 * ‖f‖ₑ := by +-- Proposition 3.17.1 : "∆ is bounded" from Vikman +lemma laplace_bounded (f : (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G)))) : ‖(Laplace f)‖ₑ ≤ 2 * ‖f‖ₑ := by unfold Laplace unfold conv_mu_lp2 simp_rw [f_conv_mu] @@ -326,7 +297,7 @@ lemma laplace_bounded (f: (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G simp rw [MeasureTheory.Lp.enorm_toLp] - grw [MeasureTheory.eLpNorm_sum_le] + grw [MeasureTheory.eLpNorm_sum_le (by norm_num)] simp_rw [← Function.comp_def] conv => lhs @@ -358,52 +329,38 @@ lemma laplace_bounded (f: (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G )] simp rw [two_mul] - . rw [← MeasureTheory.Lp.enorm_def] - -- TODO - inline these in the right places - . simp - . - intro i hs - apply MeasureTheory.AEStronglyMeasurable.of_discrete - . norm_num - . - apply MeasureTheory.memLp_finsetSum + · rw [← MeasureTheory.Lp.enorm_def] + · simp + · apply MeasureTheory.memLp_finsetSum intro s hs rw [← Function.comp_def] apply MeasureTheory.MemLp.comp_of_map - . - simp [MeasureTheory.volume] + · simp [MeasureTheory.volume] apply MeasureTheory.Lp.memLp f - . apply AEMeasurable.of_discrete - + · apply AEMeasurable.of_discrete -lemma laplace_bounded' (f: (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G)))): ‖(Laplace f)‖ ≤ 2 * ‖f‖ := by +lemma laplace_bounded' (f : (MeasureTheory.Lp ℝ 2 (MeasureTheory.volume (α := G)))) : ‖(Laplace f)‖ ≤ 2 * ‖f‖ := by have bounded := laplace_bounded f - rw [← ofReal_norm_eq_enorm] at bounded - rw [← ofReal_norm_eq_enorm] at bounded + rw [← ofReal_norm] at bounded + rw [← ofReal_norm] at bounded simp_rw [← ENNReal.ofReal_ofNat] at bounded rw [← ENNReal.ofReal_mul] at bounded - . - rw [ENNReal.ofReal_le_ofReal_iff] at bounded - . exact bounded - . simp - . simp + · rw [ENNReal.ofReal_le_ofReal_iff] at bounded + · exact bounded + · simp + · simp -lemma tolp_apply (f: G → ℝ) {p: ENNReal} (hf: MeasureTheory.MemLp f p) (g: G): (MeasureTheory.MemLp.toLp f hf) g = f g := by +lemma tolp_apply (f : G → ℝ) {p : ENNReal} (hf : MeasureTheory.MemLp f p) (g : G) : (MeasureTheory.MemLp.toLp f hf) g = f g := by have eq_fun := MeasureTheory.AEEqFun.coeFn_mk f (μ := MeasureTheory.volume (α := G)) (by apply MeasureTheory.AEStronglyMeasurable.of_discrete) rw [ae_eq_everywhere] at eq_fun nth_rw 2 [← eq_fun] rfl - open scoped RealInnerProductSpace -lemma laplace_self_adjoint (f h: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G)))): ⟪f, (Laplace h)⟫ = ⟪(Laplace f), h⟫ := by +lemma laplace_self_adjoint (f h : (MeasureTheory.Lp ℝ 2 (μ := volume (α := G)))) : ⟪f, (Laplace h)⟫ = ⟪(Laplace f), h⟫ := by simp [MeasureTheory.L2.inner_def] - - - -- MeasureTheory.Lp.coeFn_smul - conv => lhs arg 2 @@ -434,7 +391,6 @@ lemma laplace_self_adjoint (f h: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G) simp_rw [mul_assoc] simp_rw [Finset.mul_sum] - conv => lhs arg 2 @@ -445,10 +401,9 @@ lemma laplace_self_adjoint (f h: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G) arg 1 intro i - simp_rw [tolp_apply] rw [integral_sub] - rw [MeasureTheory.integral_finset_sum] + rw [MeasureTheory.integral_finsetSum] conv => lhs rhs @@ -456,7 +411,7 @@ lemma laplace_self_adjoint (f h: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G) intro s rw [← MeasureTheory.integral_mul_left_eq_self (g := s⁻¹)] simp - rw [← MeasureTheory.integral_finset_sum] + rw [← MeasureTheory.integral_finsetSum] conv => lhs rhs @@ -465,13 +420,13 @@ lemma laplace_self_adjoint (f h: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G) rw [← Finset.mul_sum] rw [Finset.sum_bijective (s := S) (t := S) (e := fun s => s⁻¹) (g := fun i => (f (i * g) * (h g))) (by refine ⟨?_, ?_⟩ - . exact inv_injective - . exact inv_surjective + · exact inv_injective + · exact inv_surjective ) (by intro a refine ⟨?_, ?_⟩ - . apply hGS.has_inv a - . simpa using (hGS.has_inv a⁻¹) + · apply hGS.has_inv a + · simpa using (hGS.has_inv a⁻¹) ) (by simp )] @@ -488,7 +443,6 @@ lemma laplace_self_adjoint (f h: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G) rw [mul_comm] rw [← mul_sub] - conv => rhs arg 2 @@ -499,67 +453,59 @@ lemma laplace_self_adjoint (f h: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G) simp [f_conv_mu] rw [tolp_apply] - simp_rw [Finset.mul_sum] - . - have prod_lp1 := MeasureTheory.MemLp.smul (φ := f) (f := h) (p := 2) (q := 2) (r := 1) (μ := volume) (MeasureTheory.Lp.memLp h) (MeasureTheory.Lp.memLp f) + · have prod_lp1 := MeasureTheory.MemLp.smul (φ := f) (f := h) (p := 2) (q := 2) (r := 1) (μ := volume) (MeasureTheory.Lp.memLp f) (MeasureTheory.Lp.memLp h) rw [MeasureTheory.memLp_one_iff_integrable] at prod_lp1 - exact prod_lp1 - . - apply MeasureTheory.integrable_finset_sum + simpa only [Pi.smul_apply, smul_eq_mul, Pi.mul_def, Function.comp_apply] using prod_lp1 + · apply MeasureTheory.integrable_finsetSum intro s hs apply MeasureTheory.Integrable.const_mul - have mem_lp_f_comp: MemLp (f ∘ (fun x => s * x)) 2 := by + have mem_lp_f_comp : MemLp (f ∘ (fun x => s * x)) 2 := by apply MeasureTheory.MemLp.comp_measurePreserving (ν := volume) - . apply MeasureTheory.Lp.memLp f - . exact measurePreserving_mul_left volume s + · apply MeasureTheory.Lp.memLp f + · exact measurePreserving_mul_left volume s - have prod_lp1 := MeasureTheory.MemLp.smul (f := h) (p := 2) (q := 2) (r := 1) (μ := volume) (MeasureTheory.Lp.memLp h) mem_lp_f_comp + have prod_lp1 := MeasureTheory.MemLp.smul (f := h) (p := 2) (q := 2) (r := 1) (μ := volume) mem_lp_f_comp (MeasureTheory.Lp.memLp h) rw [MeasureTheory.memLp_one_iff_integrable] at prod_lp1 - exact prod_lp1 - . - intro s hs + simpa only [Pi.smul_apply, smul_eq_mul, Pi.mul_def, Function.comp_apply] using prod_lp1 + · intro s hs apply MeasureTheory.Integrable.const_mul - have mem_lp_f_comp: MemLp (f ∘ (fun x => s⁻¹ * x)) 2 := by + have mem_lp_f_comp : MemLp (f ∘ (fun x => s⁻¹ * x)) 2 := by apply MeasureTheory.MemLp.comp_measurePreserving (ν := volume) - . apply MeasureTheory.Lp.memLp f - . exact measurePreserving_mul_left volume s⁻¹ - have prod_lp1 := MeasureTheory.MemLp.smul (f := h) (p := 2) (q := 2) (r := 1) (μ := volume) (MeasureTheory.Lp.memLp h) mem_lp_f_comp + · apply MeasureTheory.Lp.memLp f + · exact measurePreserving_mul_left volume s⁻¹ + have prod_lp1 := MeasureTheory.MemLp.smul (f := h) (p := 2) (q := 2) (r := 1) (μ := volume) mem_lp_f_comp (MeasureTheory.Lp.memLp h) rw [MeasureTheory.memLp_one_iff_integrable] at prod_lp1 - exact prod_lp1 - . - intro s hs + simpa only [Pi.smul_apply, smul_eq_mul, Pi.mul_def, Function.comp_apply] using prod_lp1 + · intro s hs apply MeasureTheory.Integrable.const_mul - have mem_lp_h_comp: MemLp (h ∘ (fun x => s * x)) 2 := by + have mem_lp_h_comp : MemLp (h ∘ (fun x => s * x)) 2 := by apply MeasureTheory.MemLp.comp_measurePreserving (ν := volume) - . apply MeasureTheory.Lp.memLp h - . exact measurePreserving_mul_left volume s + · apply MeasureTheory.Lp.memLp h + · exact measurePreserving_mul_left volume s - have prod_lp1 := MeasureTheory.MemLp.smul (p := 2) (q := 2) (r := 1) (μ := volume) mem_lp_h_comp (MeasureTheory.Lp.memLp f) + have prod_lp1 := MeasureTheory.MemLp.smul (p := 2) (q := 2) (r := 1) (μ := volume) (MeasureTheory.Lp.memLp f) mem_lp_h_comp rw [MeasureTheory.memLp_one_iff_integrable] at prod_lp1 - exact prod_lp1 - . - have prod_lp1 := MeasureTheory.MemLp.smul (φ := f) (f := h) (p := 2) (q := 2) (r := 1) (μ := volume) (MeasureTheory.Lp.memLp h) (MeasureTheory.Lp.memLp f) + simpa only [Pi.smul_apply, smul_eq_mul, Pi.mul_def, Function.comp_apply] using prod_lp1 + · have prod_lp1 := MeasureTheory.MemLp.smul (φ := f) (f := h) (p := 2) (q := 2) (r := 1) (μ := volume) (MeasureTheory.Lp.memLp f) (MeasureTheory.Lp.memLp h) rw [MeasureTheory.memLp_one_iff_integrable] at prod_lp1 - exact prod_lp1 - . - apply MeasureTheory.integrable_finset_sum + simpa only [Pi.smul_apply, smul_eq_mul, Pi.mul_def, Function.comp_apply] using prod_lp1 + · apply MeasureTheory.integrable_finsetSum intro s hs apply MeasureTheory.Integrable.const_mul - have mem_lp_h_comp: MemLp (h ∘ (fun x => s * x)) 2 := by + have mem_lp_h_comp : MemLp (h ∘ (fun x => s * x)) 2 := by apply MeasureTheory.MemLp.comp_measurePreserving (ν := volume) - . apply MeasureTheory.Lp.memLp h - . exact measurePreserving_mul_left volume s + · apply MeasureTheory.Lp.memLp h + · exact measurePreserving_mul_left volume s - have prod_lp1 := MeasureTheory.MemLp.smul (p := 2) (q := 2) (r := 1) (μ := volume) mem_lp_h_comp (MeasureTheory.Lp.memLp f) + have prod_lp1 := MeasureTheory.MemLp.smul (p := 2) (q := 2) (r := 1) (μ := volume) (MeasureTheory.Lp.memLp f) mem_lp_h_comp rw [MeasureTheory.memLp_one_iff_integrable] at prod_lp1 - exact prod_lp1 - + simpa only [Pi.smul_apply, smul_eq_mul, Pi.mul_def, Function.comp_apply] using prod_lp1 set_option maxHeartbeats 200000 in -lemma laplace_positive_semidefinite (f: (MeasureTheory.Lp ℝ 2 (μ := volume (α := G)))): 0 ≤ ⟪f, (Laplace f)⟫ := by +lemma laplace_positive_semidefinite (f : (MeasureTheory.Lp ℝ 2 (μ := volume (α := G)))) : 0 ≤ ⟪f, (Laplace f)⟫ := by unfold Laplace rw [inner_sub_right] rw [real_inner_self_eq_norm_sq] @@ -571,23 +517,22 @@ lemma laplace_positive_semidefinite (f: (MeasureTheory.Lp ℝ 2 (μ := volume ( simp_rw [inner_smul_right] simp_rw [inner_sum] rw [integral_const_mul] - rw [MeasureTheory.integral_finset_sum] + rw [MeasureTheory.integral_finsetSum] - -- I couldn't figure how to to handle 'toLp (∑ x ∈ S), so I ended up manipulating the integral to avoid dealing with it - have comp_smul_left (i: G) := MeasureTheory.Lp.coeFn_compMeasurePreserving (g := f) (f := fun a => i * a) (μ := volume) (by + -- Finite-sum integral identities express the quadratic form on L². + have comp_smul_left (i : G) := MeasureTheory.Lp.coeFn_compMeasurePreserving (g := f) (f := fun a => i * a) (μ := volume) (by exact measurePreserving_mul_left volume i ) simp_rw [ae_eq_everywhere] at comp_smul_left - have congr_comp (i: G) (x: G) := congrFun (comp_smul_left i) x + have congr_comp (i : G) (x : G) := congrFun (comp_smul_left i) x simp only [Function.comp_apply] at congr_comp simp_rw [smul_eq_mul] simp_rw [← congr_comp] simp_rw [← MeasureTheory.L2.inner_def] - let f_eq_coe: f = f := by rfl + let f_eq_coe : f = f := by rfl nth_rw 1 [← MeasureTheory.Lp.toLp_coeFn (f := f) (hf := Lp.memLp f)] at f_eq_coe - conv => rhs rhs @@ -598,19 +543,15 @@ lemma laplace_positive_semidefinite (f: (MeasureTheory.Lp ℝ 2 (μ := volume ( rw [MeasureTheory.Lp.toLp_compMeasurePreserving] simp + -- Translation invariance identifies the summands as L² inner products. - -- We've now packed everything back up in an inner product - - -- we no longer need to deal with commuting toLp and Finset.sum - - - let conv_f_delta_lp (i: G) := MemLp.toLp (Conv (f) (delta i⁻¹)) (μ := volume) (p := 2) (by + let conv_f_delta_lp (i : G) := MemLp.toLp (Conv (f) (delta i⁻¹)) (μ := volume) (p := 2) (by simp_rw [f_conv_delta_helper] apply MeasureTheory.MemLp.comp_measurePreserving (ν := volume) - . apply MeasureTheory.Lp.memLp f - . exact measurePreserving_mul_left volume _ + · apply MeasureTheory.Lp.memLp f + · exact measurePreserving_mul_left volume _ ) - have sum_le := Finset.sum_le_sum (g := fun i => ‖f‖ * ‖conv_f_delta_lp i‖) (f := fun i => ⟪f, conv_f_delta_lp i⟫) (s := S) (by intro s hs have foo := norm_inner_le_norm (x := f) (y := conv_f_delta_lp s) (𝕜 := ℝ) @@ -635,7 +576,6 @@ lemma laplace_positive_semidefinite (f: (MeasureTheory.Lp ℝ 2 (μ := volume ( rw [f_conv_delta] simp - calc _ ≥ ‖f‖ ^ 2 - 1 / ↑(#S) * ∑ i ∈ S, ‖f‖ * ‖conv_f_delta_lp i‖ := by @@ -656,11 +596,11 @@ lemma laplace_positive_semidefinite (f: (MeasureTheory.Lp ℝ 2 (μ := volume ( simp rw [← Function.comp_def] rw [MeasureTheory.eLpNorm_comp_measurePreserving (ν := volume)] - . simp [norm] - . apply MeasureTheory.AEStronglyMeasurable.of_discrete - . exact measurePreserving_mul_left volume x + · simp [norm] + · apply MeasureTheory.AEStronglyMeasurable.of_discrete + · exact measurePreserving_mul_left volume x simp - have s_card_ne_zero: (#S : ℝ) ≠ 0 := by + have s_card_ne_zero : (#S : ℝ) ≠ 0 := by simp have foo := hS simp at foo @@ -669,41 +609,36 @@ lemma laplace_positive_semidefinite (f: (MeasureTheory.Lp ℝ 2 (μ := volume ( rw [← mul_assoc] simp [s_card_ne_zero] rw [pow_two] - . - intro s hs + · intro s hs simp - have mem_lp_h_comp: MemLp (f ∘ (fun x => s * x)) 2 := by + have mem_lp_h_comp : MemLp (f ∘ (fun x => s * x)) 2 := by apply MeasureTheory.MemLp.comp_measurePreserving (ν := volume) - . apply MeasureTheory.Lp.memLp f - . exact measurePreserving_mul_left volume s + · apply MeasureTheory.Lp.memLp f + · exact measurePreserving_mul_left volume s - have prod_lp1 := MeasureTheory.MemLp.smul (p := 2) (q := 2) (r := 1) (μ := volume) (MeasureTheory.Lp.memLp f) mem_lp_h_comp + have prod_lp1 := MeasureTheory.MemLp.smul (p := 2) (q := 2) (r := 1) (μ := volume) mem_lp_h_comp (MeasureTheory.Lp.memLp f) rw [MeasureTheory.memLp_one_iff_integrable] at prod_lp1 - exact prod_lp1 - + simpa only [Pi.smul_apply, smul_eq_mul, Pi.mul_def, Function.comp_apply] using prod_lp1 @[expose] noncomputable def Δ := Laplace_linear.mkContinuous _ (laplace_bounded') -lemma Δ_symmetric: Δ.IsSymmetric := by +lemma Δ_symmetric : Δ.IsSymmetric := by unfold LinearMap.IsSymmetric intro x hx unfold Δ - -- TODO - why doesn't this fire automatically? simp [LinearMap.mkContinuous] simp [Laplace_linear] rw [laplace_self_adjoint] -lemma Δ_spectrum_subset: spectrum ℝ Δ ⊆ Set.Icc 0 2 := by +lemma Δ_spectrum_subset : spectrum ℝ Δ ⊆ Set.Icc 0 2 := by intro a ha have restricts := ContinuousLinearMap.IsPositive.spectrumRestricts (f := Δ) (by rw [ContinuousLinearMap.isPositive_def] refine ⟨?_, ?_⟩ - . - apply Δ_symmetric - . - intro x + · apply Δ_symmetric + · intro x simp [ContinuousLinearMap.reApplyInnerSelf_apply] unfold Δ simp [LinearMap.mkContinuous] @@ -712,44 +647,39 @@ lemma Δ_spectrum_subset: spectrum ℝ Δ ⊆ Set.Icc 0 2 := by apply laplace_positive_semidefinite ) simp - have a_nonneg: 0 ≤ a := by - have zero_eq: (0: ℝ) = (0: NNReal) := by + have a_nonneg : 0 ≤ a := by + have zero_eq : (0 : ℝ) = (0 : NNReal) := by simp rw [zero_eq] apply (SpectrumRestricts.nnreal_le_iff restricts).mp - . simp - . exact ha - + · simp + · exact ha refine ⟨?_, ?_⟩ - . - exact a_nonneg - . - have norm_le: ‖a‖ ≤ ‖(2: ℝ)‖ := by + · exact a_nonneg + · have norm_le : ‖a‖ ≤ ‖(2 : ℝ)‖ := by have foo := spectrum.norm_le_norm_mul_of_mem ha simp at foo simp [Δ] at foo grw [← (ContinuousLinearMap.opNorm_le_iff (M := ‖2‖) (f := Δ) ?_).mpr] - . - have h := spectrum.norm_le_norm_mul_of_mem ha + · have h := spectrum.norm_le_norm_mul_of_mem ha rw [ContinuousLinearMap.one_def] at h grw [ContinuousLinearMap.norm_id_le] at h simpa using h - . intro x + · intro x simp [Δ, LinearMap.mkContinuous, Laplace_linear] have bound := laplace_bounded x simp [enorm] at bound norm_cast at bound - . simp + · simp simp at norm_le rw [abs_of_nonneg] at norm_le - . exact norm_le - . exact a_nonneg + · exact norm_le + · exact a_nonneg - -lemma laplace_spectrum_contains_zero (f_n_limit: f_n_conv_delta_tendsto): 0 ∈ spectrum ℝ Δ := by +lemma laplace_spectrum_contains_zero (f_n_limit : f_n_conv_delta_tendsto) : 0 ∈ spectrum ℝ Δ := by rw [spectrum.zero_mem_iff] by_contra this obtain ⟨f, hf⟩ := this @@ -761,8 +691,8 @@ lemma laplace_spectrum_contains_zero (f_n_limit: f_n_conv_delta_tendsto): 0 ∈ use 0 use MemLp.toLp (Pi.single 1 1) (by apply Continuous.memLp_of_hasCompactSupport - . apply continuous_of_discreteTopology - . simp [HasCompactSupport, tsupport] + · apply continuous_of_discreteTopology + · simp [HasCompactSupport, tsupport] ) simp rw [MeasureTheory.Lp.ext_iff] @@ -779,7 +709,7 @@ lemma laplace_spectrum_contains_zero (f_n_limit: f_n_conv_delta_tendsto): 0 ∈ have norm_mul_bound := ContinuousLinearEquiv.one_le_norm_mul_norm_symm (ContinuousLinearEquiv.ofUnit f) - have inv_norm_ge (n: ℕ) : (1 : ENNReal) / (eLpNorm (Laplace_b (F_n n)) 2 (μ := volume (α := G))) ≤ ENNReal.ofReal ‖f.inv‖ := by + have inv_norm_ge (n : ℕ) : (1 : ENNReal) / (eLpNorm (Laplace_b (F_n n)) 2 (μ := volume (α := G))) ≤ ENNReal.ofReal ‖f.inv‖ := by calc _ = (eLpNorm (F_n n) 2 (μ := volume (α := G))) / ((eLpNorm (Laplace_b (F_n n)) 2 (μ := volume (α := G)))) := by @@ -795,7 +725,6 @@ lemma laplace_spectrum_contains_zero (f_n_limit: f_n_conv_delta_tendsto): 0 ∈ lhs rw [Lp.norm_def] - conv => lhs arg 1 @@ -804,21 +733,20 @@ lemma laplace_spectrum_contains_zero (f_n_limit: f_n_conv_delta_tendsto): 0 ∈ rhs rhs simp [hf, Δ, Laplace, Laplace_linear] - simp [-AddSubgroupClass.coe_sub, -AddSubgroup.coe_sub, Laplace] + simp [-AddSubgroupClass.coe_sub, -AddSubgroup.coe_sub] apply_fun ENNReal.ofReal at other - -- TODO - consider removing @[simp] from 'AddSubgroupClass.coe_sub' simp only [map_sub, ofReal_norm] at other simp only [← Units.inv_eq_val_inv] - simp only [F_n_lp2, Laplace_b, ← hf, conv_mu_lp2] + simp only [F_n_lp2, Laplace_b, conv_mu_lp2] --simp_rw [ae_eq_everywhere.mp (MemLp.coeFn_toLp _)] - by_cases norm_f_eq_zero: ‖F_n_lp2 n - conv_mu_lp2 (F_n_lp2 n)‖ = 0 - . rw [norm_eq_zero] at norm_f_eq_zero + by_cases norm_f_eq_zero : ‖F_n_lp2 n - conv_mu_lp2 (F_n_lp2 n)‖ = 0 + · rw [norm_eq_zero] at norm_f_eq_zero have foo := laplace_zero_iff_zero (F_n_lp2 n) (by simp [Laplace] exact norm_f_eq_zero ) simp [F_n_lp2] at foo - apply_fun (fun f => (f: (G → ℝ))) at foo + apply_fun (fun f => (f : (G → ℝ))) at foo simp_rw [ae_eq_everywhere.mp (MemLp.coeFn_toLp _)] at foo conv at foo => rhs @@ -827,7 +755,7 @@ lemma laplace_spectrum_contains_zero (f_n_limit: f_n_conv_delta_tendsto): 0 ∈ simp [foo] unfold Conv simp - have const_zero: (fun (x: G) => (0 : ℝ)) = 0 := by rfl + have const_zero : (fun (x : G) => (0 : ℝ)) = 0 := by rfl conv => pattern MemLp.toLp _ _ equals 0 => @@ -839,32 +767,28 @@ lemma laplace_spectrum_contains_zero (f_n_limit: f_n_conv_delta_tendsto): 0 ∈ simp_rw [ae_eq_everywhere.mp (MeasureTheory.AEEqFun.coeFn_zero)] simp rw [ENNReal.ofReal_div_of_pos] at other - . - simp only [ofReal_norm, Lp.enorm_def] at other + · simp only [ofReal_norm, Lp.enorm_def] at other rw [ae_eq_everywhere.mp (Lp.coeFn_sub _ _)] at other simp only [F_n_lp2, conv_mu_lp2] at other simp_rw [ae_eq_everywhere.mp (MemLp.coeFn_toLp _)] at other rw [ENNReal.ofReal_toReal] at other - . - rw [ae_eq_everywhere.mp (Lp.coeFn_sub _ _)] + · rw [ae_eq_everywhere.mp (Lp.coeFn_sub _ _)] rw [ae_eq_everywhere.mp (Lp.coeFn_sub _ _)] at other simp_rw [ae_eq_everywhere.mp (MemLp.coeFn_toLp _)] at other simp at other simp simp_rw [ae_eq_everywhere.mp (MemLp.coeFn_toLp _)] exact other - . - rw [← ae_eq_everywhere.mp (Lp.coeFn_sub _ _)] + · rw [← ae_eq_everywhere.mp (Lp.coeFn_sub _ _)] apply MeasureTheory.Lp.eLpNorm_ne_top - . simpa using norm_f_eq_zero - . exact ENNReal.ofReal_mono - . - rw [isBoundedLinearMap_iff] at inv_bounded + · simpa using norm_f_eq_zero + · exact ENNReal.ofReal_mono + · rw [isBoundedLinearMap_iff] at inv_bounded obtain ⟨M, M_pos, le_M⟩ := inv_bounded.2 have foo := F_n_conv_mu_lim f_n_limit rw [ENNReal.tendsto_atTop_zero] at foo - obtain ⟨n, hn⟩ := foo ((1: ENNReal) /(2 * ‖f.inv‖ₑ)) (by + obtain ⟨n, hn⟩ := foo ((1 : ENNReal) /(2 * ‖f.inv‖ₑ)) (by simp rw [ENNReal.mul_eq_top] simp @@ -880,7 +804,7 @@ lemma laplace_spectrum_contains_zero (f_n_limit: f_n_conv_delta_tendsto): 0 ∈ grw [hn] at inv_norm_ge simp at inv_norm_ge - have norm_nonzero :‖f.inv‖ ≠ 0 := by + have norm_nonzero : ‖f.inv‖ ≠ 0 := by by_contra! simp at this diff --git a/Gromov/HarmonicR2.lean b/Gromov/HarmonicR2.lean index 44f0aa9..752d6fd 100644 --- a/Gromov/HarmonicR2.lean +++ b/Gromov/HarmonicR2.lean @@ -12,11 +12,6 @@ a ball of radius `2R`. public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false open scoped Finset open scoped Pointwise @@ -27,7 +22,200 @@ open Generates variable [hGS: Generates] include hGS -set_option maxHeartbeats 9000000 in +private noncomputable def harmonicCutoff (r : ℕ) (x : G) : ℝ := + if WordNorm x ≤ 2 * r + 1 then 1 + else if WordNorm x ≤ 4 * r then -(WordNorm x : ℝ) / (2 * (r : ℝ)) + 2 else 0 + +private lemma harmonic_cutoff_step (f : G → ℝ) (r : ℕ) (hr : r ≠ 0) + (x : G) (hx : x ∈ Metric.closedBall 1 (4 * r)) (s : G) (hs : s ∈ S) : + (f x)^2 * (harmonicCutoff r (s * x) - harmonicCutoff r x)^2 ≤ + (1 : ℝ) / r^2 * (f x)^2 := by + simp [harmonicCutoff] + have norm_s_x := word_dist_mul_eq (x := 1) (y := s) (z := x) hs + simp_rw [WordDist_comm] at norm_s_x + simp_rw [WordDist_one] at norm_s_x + rw [← or_assoc] at norm_s_x + cases norm_s_x + . + rename_i norm_s_x_eq + cases norm_s_x_eq + . + rename_i s_lt + simp [dist] at hx + norm_cast at hx + rw [WordDist_one] at hx + by_cases s_x_le: WordNorm (s * x) ≤ 2 *r + 1 + . + simp [s_x_le] + simp [s_lt] + split_ifs + . simp + positivity + . + have s_x_eq: WordNorm (s * x) = 2 *r + 1 := by grind + simp [s_x_eq] + field_simp + apply mul_le_mul + . simp + . + norm_num + ring_nf + norm_num + . positivity + . positivity + . + grind + . + have sub_eq: (WordNorm x) - 1 = WordNorm (s * x) := by omega + have s_x_le_four: WordNorm (s * x) ≤ 4 * r := by + simp [s_lt] at hx + grind + simp [s_x_le, s_x_le_four] + split_ifs + . + grind + . + simp [← sub_eq] + rw [← sub_div] + simp + field_simp + conv => + lhs + rhs + lhs + equals 1 => + rw [sub_eq] + rw [s_lt] + push_cast + ring + simp + norm_num + -- TODO - surely this can be simplified + by_cases f_x_zero: (f x) ^2 = 0 + . simp [f_x_zero] + + rw [le_mul_iff_one_le_right] + . norm_num + . positivity + . + rename_i s_lt + simp [dist] at hx + norm_cast at hx + rw [WordDist_one] at hx + by_cases s_x_le: WordNorm (s * x) ≤ 2*r + 1 + . + simp [s_x_le] + split_ifs + . simp + positivity + . + have s_x_eq: WordNorm (s * x) = 2 *r := by grind + simp + rw [mul_comm] + apply mul_le_mul + . + ring_nf + norm_num + field_simp + rw [mul_sub] + rw [← pow_two] + rw [sub_mul] + conv => + lhs + equals (2 * r) * (2 * r) - (WordNorm x) * 2 * r * 2 + (WordNorm x)^2 => + ring + rename_i x_gt + simp at x_gt + omega + . simp + . positivity + . norm_num + . + by_cases norm_x_eq: WordNorm x = 4 * r + . + have not_le: ¬(WordNorm (s * x) ≤ (2 *r) + 1) := by grind + have not_le_four: ¬(WordNorm (s * x) ≤ (4 *r)) := by grind + have x_le: (WordNorm (x) ≤ (4 *r)) := by grind + have not_x_le: ¬(WordNorm (x) ≤ (2 *r) + 1) := by grind + simp [not_le, not_le_four, x_le, not_x_le] + rw [mul_comm] + -- TODO - surely this can be simplified + by_cases f_x_zero: (f x) ^2 = 0 + . simp [f_x_zero] + rw [mul_le_mul_iff_left₀] + . + field_simp + grw [x_le] + grind + simp + norm_num + simp [norm_x_eq] + . positivity + + have sub_eq: (WordNorm x) = WordNorm (s * x) - 1 := by omega + have s_x_le_four: WordNorm (s * x) ≤ 4 * r := by + rw [← s_lt] + grind + simp [s_x_le, s_x_le_four] + split_ifs + . + field_simp + -- TODO - surely this can be simplified + by_cases f_x_zero: (f x) ^2 = 0 + . simp [f_x_zero] + + rw [mul_le_mul_iff_right₀] + . + norm_num + field_simp + conv => + lhs + lhs + ring_nf + conv => + rhs + equals (2^2) => + norm_num + + have norm_x_eq: WordNorm x = 2 *r + 1 := by grind + rw [← s_lt, norm_x_eq] + conv => + lhs + lhs + simp + field_simp + ring_nf + norm_num + + . positivity + . + simp + rw [← sub_div] + simp + field_simp + conv => + lhs + rhs + lhs + equals -1 => + rw [sub_eq] + rw [Nat.cast_sub (by grind)] + ring + simp + norm_num + -- TODO - surely this can be simplified + by_cases f_x_zero: (f x) ^2 = 0 + . simp [f_x_zero] + + rw [le_mul_iff_one_le_right] + . norm_num + . positivity + + . + rename_i norm_eq + simp [← norm_eq] + positivity + lemma harmonic_r2_inequality (f : G → ℝ) (hf : Laplace_b f = 0) (r: ℕ) (hr: r ≠ 0): ∑ x ∈ Metric.closedBall 1 (2 * r), deriv_sq f x ≤ ((1: ℝ) / r^2) * #(S) * ∑ x ∈ Metric.closedBall 1 (4 * r), f x ^ 2 := by -- `deriv_sq f x = ∑ s, (f (s*x) - f x)^2`; the proof below is written with the @@ -43,30 +231,24 @@ lemma harmonic_r2_inequality (f : G → ℝ) (hf : Laplace_b f = 0) (r: ℕ) (hr -- m * (2 *r) - * (4 * r * m) = 1 -- 2rm - 4rm = 1 -- m = -1/2 - let φ := fun (x: G) => if WordNorm x ≤ (2 * r) + 1 then 1 else if (WordNorm x ≤ 4 * r) then (-(WordNorm x)/(2 * (r: ℝ))) + 2 else 0 + let φ := harmonicCutoff r have phi_support : φ.support ⊆ Metric.ball 1 (4 * r) := by intro s hs - simp at hs - rw [ite_eq_iff] at hs - simp at hs - by_cases s_gt: 2 * r + 1 < (WordNorm s) - . - specialize hs s_gt - simp [dist] - rw [WordDist_one] - by_cases eq_four: WordNorm s = 4*r - . - simp [eq_four] at hs - field_simp [hr] at hs - norm_num at hs - . - norm_cast - grind - . - simp at s_gt - simp [dist, WordDist_one] - norm_cast - grind + have hsne : harmonicCutoff r s ≠ 0 := hs + have hslt : WordNorm s < 4 * r := by + by_contra h + have hge : 4 * r ≤ WordNorm s := by omega + have hshort : ¬ WordNorm s ≤ 2 * r + 1 := by omega + by_cases heq : WordNorm s = 4 * r + · apply hsne + rw [harmonicCutoff, ite_eq_right hshort, ite_eq_left heq.le, heq] + push_cast + field_simp [hr] + ring + · have hlong : ¬ WordNorm s ≤ 4 * r := by omega + exact hsne (by simp [harmonicCutoff, hshort, hlong]) + simp only [Metric.mem_ball, dist, WordDist_one] + exact_mod_cast hslt have foo := cutoff_inequality f φ hf ?_ . @@ -91,201 +273,13 @@ lemma harmonic_r2_inequality (f : G → ℝ) (hf : Laplace_b f = 0) (r: ℕ) (hr rw [Finset.mul_sum] apply Finset.sum_le_sum intro s hs - simp [φ] - have norm_s_x := word_dist_mul_eq (x := 1) (y := s) (z := x) hs - simp_rw [WordDist_comm] at norm_s_x - simp_rw [WordDist_one] at norm_s_x - rw [← or_assoc] at norm_s_x - cases norm_s_x - . - rename_i norm_s_x_eq - cases norm_s_x_eq - . - rename_i s_lt - simp [dist] at hx - norm_cast at hx - rw [WordDist_one] at hx - by_cases s_x_le: WordNorm (s * x) ≤ 2 *r + 1 - . - simp [s_x_le] - simp [s_lt] - split_ifs - . simp - positivity - . - have s_x_eq: WordNorm (s * x) = 2 *r + 1 := by grind - simp [s_x_eq] - field_simp - apply mul_le_mul - . simp - . - norm_num - ring - norm_num - . positivity - . positivity - . - grind - . - have sub_eq: (WordNorm x) - 1 = WordNorm (s * x) := by omega - have s_x_le_four: WordNorm (s * x) ≤ 4 * r := by - simp [s_lt] at hx - grind - simp [s_x_le, s_x_le_four] - split_ifs - . - grind - . - simp [← sub_eq] - rw [← sub_div] - simp - field_simp - push_cast - conv => - lhs - rhs - lhs - equals 1 => - rw [sub_eq] - rw [s_lt] - push_cast - ring - simp - norm_num - -- TODO - surely this can be simplified - by_cases f_x_zero: (f x) ^2 = 0 - . simp [f_x_zero] - - rw [le_mul_iff_one_le_right] - . norm_num - . positivity - . - rename_i s_lt - simp [dist] at hx - norm_cast at hx - rw [WordDist_one] at hx - by_cases s_x_le: WordNorm (s * x) ≤ 2*r + 1 - . - simp [s_x_le] - split_ifs - . simp - positivity - . - have s_x_eq: WordNorm (s * x) = 2 *r := by grind - simp [s_x_eq] - rw [mul_comm] - apply mul_le_mul - . - norm_num - ring - norm_num - field_simp - rw [mul_sub] - rw [← pow_two] - rw [sub_mul] - conv => - lhs - equals (2 * r) * (2 * r) - (WordNorm x) * 2 * r * 2 + (WordNorm x)^2 => - ring - rename_i x_gt - simp at x_gt - omega - . simp - . positivity - . norm_num - . - by_cases norm_x_eq: WordNorm x = 4 * r - . - have not_le: ¬(WordNorm (s * x) ≤ (2 *r) + 1) := by grind - have not_le_four: ¬(WordNorm (s * x) ≤ (4 *r)) := by grind - have x_le: (WordNorm (x) ≤ (4 *r)) := by grind - have not_x_le: ¬(WordNorm (x) ≤ (2 *r) + 1) := by grind - simp [not_le, not_le_four, x_le, not_x_le] - rw [mul_comm] - -- TODO - surely this can be simplified - by_cases f_x_zero: (f x) ^2 = 0 - . simp [f_x_zero] - rw [mul_le_mul_iff_left₀] - . - field_simp - grw [x_le] - grind - simp - norm_num - simp [norm_x_eq] - . positivity - - have sub_eq: (WordNorm x) = WordNorm (s * x) - 1 := by omega - have s_x_le_four: WordNorm (s * x) ≤ 4 * r := by - rw [← s_lt] - grind - simp [s_x_le, s_x_le_four] - split_ifs - . - field_simp - -- TODO - surely this can be simplified - by_cases f_x_zero: (f x) ^2 = 0 - . simp [f_x_zero] - - rw [mul_le_mul_iff_right₀] - . - norm_num - field_simp - conv => - lhs - lhs - ring - conv => - rhs - equals (2^2) => - norm_num - - have norm_x_eq: WordNorm x = 2 *r + 1 := by grind - rw [← s_lt, norm_x_eq] - conv => - lhs - lhs - simp - field_simp - ring - norm_num - - . positivity - . - simp [← sub_eq] - rw [← sub_div] - simp - field_simp - push_cast - conv => - lhs - rhs - lhs - equals -1 => - rw [sub_eq] - push_cast - rw [Nat.cast_sub (by grind)] - ring - simp - norm_num - -- TODO - surely this can be simplified - by_cases f_x_zero: (f x) ^2 = 0 - . simp [f_x_zero] - - rw [le_mul_iff_one_le_right] - . norm_num - . positivity - - . - rename_i norm_eq - simp [← norm_eq] - positivity + exact harmonic_cutoff_step f r hr x (by simpa using hx) s hs . rfl . intro x hx apply Finset.sum_congr . rfl . intro s hs - simp [φ] + simp [φ, harmonicCutoff] simp [dist, WordDist_one] at hx norm_cast at hx have hx_le : WordNorm x ≤ 2 * r + 1 := by grind @@ -367,6 +361,5 @@ lemma harmonic_r2_inequality (f : G → ℝ) (hf : Laplace_b f = 0) (r: ℕ) (hr apply finite_ball . exact phi_support -#print axioms harmonic_r2_inequality end GeneratesNS diff --git a/Gromov/Laplace.lean b/Gromov/Laplace.lean index 4f525b7..afd4e3b 100644 --- a/Gromov/Laplace.lean +++ b/Gromov/Laplace.lean @@ -23,7 +23,6 @@ set_option linter.style.longLine false set_option linter.style.cdot false -- TODO - vscode stops reporting underlines if there are too many total underlines / gutter messages -- I've disabled some failing lints for now so that error underlines still sho up -set_option linter.style.commandStart false open Subgroup open scoped Finset diff --git a/Gromov/Lemma326.lean b/Gromov/Lemma326.lean index 430b325..03cbd45 100644 --- a/Gromov/Lemma326.lean +++ b/Gromov/Lemma326.lean @@ -12,11 +12,6 @@ basis. public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false open scoped Finset open scoped Pointwise @@ -62,7 +57,6 @@ noncomputable def phi (data: GoodScalesData b): V →ₗ[ℝ] EuclideanSpace ℝ @[expose] def C: ℝ := 32 * (#S) -set_option maxHeartbeats 2500000 in lemma lemma_3_26_a (data: GoodScalesData b) (u: V): Q_R (R_2 data) u u ≤ 2 * (#(S^(R_1 data ))) * ‖(phi data u)‖^2 + C * (Real.exp ((2 * a data.d))) * (R_1 data + 1)^2 * (∑ x ∈ B_r (8 * R_2 data), deriv_sq u x) := by rw [Q_R] @@ -132,7 +126,7 @@ lemma lemma_3_26_a (data: GoodScalesData b) (u: V): Q_R (R_2 data) u u ≤ 2 * ( rw [add_comm] apply add_le_add . - ring + ring_nf simp . @@ -197,10 +191,10 @@ lemma lemma_3_26_a (data: GoodScalesData b) (u: V): Q_R (R_2 data) u u ≤ 2 * ( simp at foo grind grw [i_1_le] - ring + ring_nf . rw [← le_sub_iff_add_le] - ring + ring_nf have i_2_pos := (GoodScales data).i_2_pos have le_one: 1 ≤ (GoodScales data).i_2 := by grind grw [← le_one] @@ -229,7 +223,7 @@ lemma lemma_3_26_a (data: GoodScalesData b) (u: V): Q_R (R_2 data) u u ≤ 2 * ( equals (32 * ↑(#S) * (Real.exp (a data.d) * (↑(R_1 data) + 1) ^ 2)) * ((Real.exp (a data.d)) * ∑ x ∈ B_r (8 * ↑(R_2 data)), deriv_sq (⇑u.val) x) => ring apply mul_le_mul - . ring + . ring_nf simp . grw [Finset.sum_le_sum (g := fun x => Real.exp (a data.d) * (deriv_sq (u.val).toFun x))] @@ -241,10 +235,10 @@ lemma lemma_3_26_a (data: GoodScalesData b) (u: V): Q_R (R_2 data) u u ≤ 2 * ( norm_cast norm_cast at card_inter_le grw [card_inter_le] - simp [deriv_sq, ← pow_two] + simp [deriv_sq] positivity - . simp [deriv_sq, ← pow_two] + . simp [deriv_sq] apply Finset.sum_nonneg intro i hi norm_cast @@ -280,7 +274,6 @@ lemma lemma_3_26_a (data: GoodScalesData b) (u: V): Q_R (R_2 data) u u ≤ 2 * ( rw [← pow_two] positivity -#print axioms lemma_3_26_a -- Controlled grwoth diff --git a/Gromov/LipschitzNorm.lean b/Gromov/LipschitzNorm.lean index 8e23a57..64dd7bf 100644 --- a/Gromov/LipschitzNorm.lean +++ b/Gromov/LipschitzNorm.lean @@ -21,8 +21,6 @@ seminormed space. The quotient space `W := LipschitzH ⧸ ConstF` is an actual n public section -set_option linter.style.cdot false -set_option linter.style.whitespace false namespace GeneratesNS open Generates @@ -43,7 +41,6 @@ lemma lipschiz_norm_zero: LipschitzSemiNorm (0) = 0 := by exact nonpos_iff_eq_zero.mp sinf_le -#synth IsStrictOrderedRing NNReal -- TODO - upstream to mathlib lemma lipschitz_attains_norm (f: G → ℝ) (hf: IsLipschitz f): LipschitzWith (LipschitzSemiNorm f) f := by @@ -167,10 +164,9 @@ lemma lipschitzSemiNorm_neg (f : G → ℝ) : LipschitzSemiNorm (-f) = Lipschitz unfold LipschitzSemiNorm congr 1 ext k - simp only [Set.mem_setOf_eq, lipschitzWith_neg_iff] + simp only [Set.mem_ofPred_eq, lipschitzWith_neg_iff] -set_option maxHeartbeats 1000000 in noncomputable instance LipschitzH_seminorm: SeminormedAddCommGroup (LipschitzH) where norm := fun v => LipschitzSemiNorm v dist_self := by @@ -295,7 +291,7 @@ lemma iterated_lipschitz_bound (f: LipschitzH): ∀ g: G, ‖f g‖ ≤ (Lipschi norm_cast rw [Nat.add_sub_of_le (by grind)] simp [DFunLike.coe] - ring + ring_nf norm_cast conv => lhs diff --git a/Gromov/MatrixSubsum.lean b/Gromov/MatrixSubsum.lean index ec60107..88c0b4b 100644 --- a/Gromov/MatrixSubsum.lean +++ b/Gromov/MatrixSubsum.lean @@ -164,7 +164,7 @@ lemma eigen_nonzero {d: ℕ} (A: (Matrix (Fin d) (Fin d) ℤ)ˣ): ∀ (k : Modul intro k by_contra! have eigen_zero := LinearMap.hasEigenvalue_zero_tfae ((A.val.map (Int.castRingHom ℂ)).toLin') - have det_zero := (eigen_zero.out 0 3).mp + have det_zero := (eigen_zero.out 1 4).mp have has_k := k.prop conv at has_k => lhs @@ -195,8 +195,7 @@ lemma eigen_nonzero {d: ℕ} (A: (Matrix (Fin d) (Fin d) ℤ)ˣ): ∀ (k : Modul . simp exact Int.cast_injective -@[expose] -def KroneckerPow_exists {d: ℕ} (A: (Matrix (Fin d) (Fin d) ℤ)ˣ) (k: Module.End.Eigenvalues (A.val.map (Int.castRingHom ℂ)).toLin') (eigen_one_complex: ∀ k : Module.End.Eigenvalues ((A.val.map (Int.castRingHom ℂ ))).toLin', ‖k.val‖ = 1) := Polynomial.pow_eq_one_of_mahlerMeasure_eq_one (by +theorem KroneckerPow_exists {d: ℕ} (A: (Matrix (Fin d) (Fin d) ℤ)ˣ) (k: Module.End.Eigenvalues (A.val.map (Int.castRingHom ℂ)).toLin') (eigen_one_complex: ∀ k : Module.End.Eigenvalues ((A.val.map (Int.castRingHom ℂ ))).toLin', ‖k.val‖ = 1) : ∃ n : ℕ, 0 < n ∧ (k : ℂ) ^ n = 1 := Polynomial.pow_eq_one_of_mahlerMeasure_eq_one (by rw [Polynomial.mahlerMeasure_eq_leadingCoeff_mul_prod_roots] rw [Polynomial.Monic.leadingCoeff] . @@ -279,7 +278,7 @@ lemma int_matrix_unipotent {d: ℕ} (hd: 0 < d) (n: ℕ) (hn: 0 < n) (A: (Matrix intro k by_contra! have eigen_zero := LinearMap.hasEigenvalue_zero_tfae (A_C.toLin') - have det_zero := (eigen_zero.out 0 3).mp + have det_zero := (eigen_zero.out 1 4).mp have has_k := k.prop conv at has_k => lhs @@ -518,8 +517,6 @@ lemma int_matrix_unipotent {d: ℕ} (hd: 0 < d) (n: ℕ) (hn: 0 < n) (A: (Matrix . exact Int.cast_injective -#print axioms int_matrix_unipotent -#print axioms int_matrix_poly_growth_eigenvalue open scoped Pointwise Finset diff --git a/Gromov/MatrixSubsum/Subsums.lean b/Gromov/MatrixSubsum/Subsums.lean index 3f723a7..370ac6f 100644 --- a/Gromov/MatrixSubsum/Subsums.lean +++ b/Gromov/MatrixSubsum/Subsums.lean @@ -19,8 +19,7 @@ structure DerivedSets {R: Type*} [NormedCommRing R] {n: ℕ} (A: Matrix (Fin n) supp_disj: Disjoint (p \ q) (q \ p) -@[expose] -def poly_cancel {R: Type*} [NormedCommRing R] {n: ℕ} (A: Matrix (Fin n) (Fin n) R) (v: (Fin n) → R) (p q : Finset ℕ) (hpq: p.sum (fun k => A^k • v) = q.sum (fun k => A^k • v)) : DerivedSets A v p q := ({ +theorem poly_cancel {R: Type*} [NormedCommRing R] {n: ℕ} (A: Matrix (Fin n) (Fin n) R) (v: (Fin n) → R) (p q : Finset ℕ) (hpq: p.sum (fun k => A^k • v) = q.sum (fun k => A^k • v)) : DerivedSets A v p q := ({ h_prime := by have p_inter_subset : p ∩ q ⊆ q := by simp @@ -118,15 +117,12 @@ lemma interval_sum_le {R: Type*} {d: ℕ} [RCLike R] [ NormSMulClass R (Fin d simp rw [Matrix.dotProduct_mulVec] rw [mul_pow_exact A φ k hva] - norm_cast - rw [Matrix.dotProduct_mulVec] at ih rw [mul_pow_exact A φ k hva] at ih apply_fun (fun x => x + ‖k‖ ^ n * ‖v‖) at ih . simp only [] at ih - norm_cast at ih simp at ih grw [ih] simp @@ -144,7 +140,6 @@ lemma interval_sum_le {R: Type*} {d: ℕ} [RCLike R] [ NormSMulClass R (Fin d exact hab . linarith -#print axioms interval_sum_le theorem hasEigenvalue_of_isRoot_charpoly {R : Type*} {M : Type*} [CommRing R] [AddCommGroup M] [Module R M] {f : Module.End R M} {μ : R} [IsDomain R] [Module.Finite R M] [Module.Free R M] (h : (f.charpoly).IsRoot μ) : f.HasEigenvalue μ := by @@ -212,7 +207,7 @@ lemma int_matrix_eigenvalue {d: ℕ} (A: (Matrix (Fin d) (Fin d) ℤ)ˣ): equals ∏ i ∈ A_C.charpoly.roots.toEnumFinset, 1 => simp - apply Finset.prod_lt_prod + apply Finset.prod_lt_prod₀ . intro i hi simp at hi @@ -285,9 +280,7 @@ lemma int_matrix_eigenvalue {d: ℕ} (A: (Matrix (Fin d) (Fin d) ℤ)ˣ): norm_num at roots_prod_le -#print axioms int_matrix_eigenvalue -set_option maxHeartbeats 1200000 in lemma subsums_unique {d: ℕ} (A: Matrix (Fin d) (Fin d) ℂ) (φ v: (Fin d) → ℂ) (N₀ N: ℕ) (hv: ‖φ ⬝ᵥ v‖ ≠ 0) (k: ℂ) (hk: 3 ≤ ‖k‖) (hva: A.vecMul φ = k • φ) (hn: N₀ ≤ N) (p q: Finset ℕ) (hp: p ⊆ Finset.Ico N₀ N) (hq: q ⊆ Finset.Ico N₀ N) (hpq: p.sum (fun k => A^k • v) = q.sum (fun k => A^k • v)): p = q := by @@ -433,7 +426,6 @@ lemma subsums_unique {d: ℕ} (A: Matrix (Fin d) (Fin d) ℂ) (φ v: (Fin d) → intro a ha b hb grind -#print axioms subsums_unique lemma int_matrix_exponential_growth {d: ℕ} (A: (Matrix (Fin d) (Fin d) ℤ)) (φ : (Fin d) → ℂ) (v: Fin d → ℤ) (v_ne_zero: ‖φ ⬝ᵥ (Int.castRingHom ℂ) ∘ v‖ ≠ 0) (k: ℂ) (hv: (A.map (Int.castRingHom ℂ)).vecMul φ = (k • φ)) (k_gt: 1 < ‖k‖): @@ -505,4 +497,3 @@ lemma int_matrix_exponential_growth {d: ℕ} (A: (Matrix (Fin d) (Fin d) ℤ)) ( rw [Finset.sum_apply (a := v)] rw [Finset.sum_apply (a := v)] rw [hab] -#print axioms int_matrix_exponential_growth diff --git a/Gromov/NilpotentFinite.lean b/Gromov/NilpotentFinite.lean index ffe4196..541722a 100644 --- a/Gromov/NilpotentFinite.lean +++ b/Gromov/NilpotentFinite.lean @@ -1,26 +1,20 @@ -/- -This file was edited by Aristotle. +module -Lean version: leanprover/lean4:v4.24.0 -Mathlib version: f897ebcf72cd16f89ab4577d0c826cd14afaafc7 -This project request had uuid: c7b9eaaf-b542-48c8-afcd-8a008aa813c3 +public import Mathlib -The following was proved by Aristotle: +/-! # Finiteness of finitely generated nilpotent torsion groups -- lemma finite_of_nilpotent_fg_order {G: Type*} [Group G] [Group.FG G] [Group.IsNilpotent G] (m: ℕ) (hm: 0 < m) (hg: ∀ g : G, g^m = 1): Finite G +The proof is by induction on the nilpotency class, using the central quotient +and finite generation of finite-index subgroups. Formalized by Aristotle. -/ -module - -public import Mathlib - public section open scoped IsMulCommutative -lemma finite_of_nilpotent_fg_order {G: Type*} [Group G] [Group.FG G] [Group.IsNilpotent G] (hG: Monoid.IsTorsion G): Finite G := by +lemma finite_of_nilpotent_fg_order {G: Type*} [Group G] [Group.FG G] [Group.IsNilpotent G] (hG: IsMulTorsion G): Finite G := by induction' n : Group.nilpotencyClass G with n ih generalizing G <;> simp_all +decide [ Group.nilpotencyClass ]; - · rw [ eq_top_iff ] at n ; aesop; + · rw [ eq_top_iff ] at n; -- Since the top subgroup is equal to the bottom subgroup, G must be trivial. have h_trivial : ∀ g : G, g = 1 := by simp_all +decide [ Subgroup.eq_bot_iff_forall ]; @@ -40,7 +34,7 @@ lemma finite_of_nilpotent_fg_order {G: Type*} [Group G] [Group.FG G] [Group.IsNi rw [← QuotientGroup.out_eq' (a := g)] erw [ QuotientGroup.eq_one_iff ] simp [hn.2] - · have e := nilpotencyClass_quotient_center (G := G) + · have e := Group.nilpotencyClass_quotient_center (G := G) have hq : Group.IsNilpotent (G ⧸ Subgroup.center G) := inferInstance simp_all +decide [Group.nilpotencyClass] -- Since $Z(G)$ is finitely generated and torsion, it is finite. @@ -50,7 +44,7 @@ lemma finite_of_nilpotent_fg_order {G: Type*} [Group G] [Group.FG G] [Group.IsNi convert Subgroup.fg_of_index_ne_zero ?_; · infer_instance; · exact Subgroup.finiteIndex_iff_finite_quotient.mpr h_quot_finite; - have h_center_torsion : Monoid.IsTorsion (↥(Subgroup.center G)) := by + have h_center_torsion : IsMulTorsion (↥(Subgroup.center G)) := by intro x; rw [isOfFinOrder_iff_pow_eq_one] specialize hG x @@ -61,5 +55,5 @@ lemma finite_of_nilpotent_fg_order {G: Type*} [Group G] [Group.FG G] [Group.IsNi rw [Subtype.ext_iff] simp exact hn.2 - exact CommGroup.finite_of_fg_torsion (↥(Subgroup.center G)) h_center_torsion; + exact CommGroup.finite_of_fg_isMulTorsion (↥(Subgroup.center G)) h_center_torsion; convert Finite.of_subgroup_quotient ( H := Subgroup.center G ) diff --git a/Gromov/Packing.lean b/Gromov/Packing.lean index 14de782..7d49b7c 100644 --- a/Gromov/Packing.lean +++ b/Gromov/Packing.lean @@ -12,11 +12,6 @@ the intersection-multiplicity bound `card_B_le_exp_wa`. public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false open scoped Finset open scoped Pointwise @@ -55,8 +50,6 @@ noncomputable def GoodScales (data: GoodScalesData b) := Classical.choice (lemma @[expose] noncomputable def R_1 (data: GoodScalesData b) := 2 * 16^(GoodScales data).i_1 @[expose] noncomputable def R_2 (data: GoodScalesData b) := 16^(GoodScales data).i_2 - --- TODO - does it matter than 'Metric.maximalSeparatedSet' uses 'R_1 < dist' instead of 'R_1 <= dist' ? @[expose] def X_j (data: GoodScalesData b) := Metric.maximalSeparatedSet (R_1 data) ((Metric.closedBall (1: G) (R_2 data))) -- A collection of disjoint balls that cover the ball R_2 @[expose] def B (data: GoodScalesData b) := (fun a => Metric.closedBall a (R_1 data)) '' (X_j data) @@ -87,10 +80,8 @@ lemma B_ball_injective_on (data: GoodScalesData b) (R: ℝ) (R_pos: 0 ≤ R) (hR simp [edist, PseudoMetricSpace.edist] at sep rw [dist_comm] at b_mem simp [dist] at b_mem - norm_cast at b_mem rify at sep grw [b_mem] at sep - norm_cast at sep grind lemma B_covers_R2 (data: GoodScalesData b): Metric.closedBall 1 (R_2 data) ⊆ ⋃₀ (B data) := by @@ -100,44 +91,44 @@ lemma B_covers_R2 (data: GoodScalesData b): Metric.closedBall 1 (R_2 data) ⊆ -- Metric.maximalSeparatedSet_subset have card_le := Metric.encard_le_of_isSeparated (C := (X_j data) ∪ {x}) (ε := (R_1 data)) (A := ( (Metric.closedBall 1 (R_2 data)))) ?_ ?_ ?_ - . + · simp [X_j] at card_le rw [Set.encard_insert_of_notMem] at card_le rw [Set.Finite.encard_eq_coe_toFinset_card] at card_le - . norm_cast at card_le + · norm_cast at card_le grind - . + · apply Set.Finite.subset (s := Metric.closedBall 1 (R_2 data)) - . apply finite_closed_ball - . apply Metric.maximalSeparatedSet_subset - . + · apply finite_closed_ball + · apply Metric.maximalSeparatedSet_subset + · simp at x_not_mem simp only [B, Set.mem_image, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, - not_lt, X_j] at x_not_mem + X_j] at x_not_mem by_contra! specialize x_not_mem x this simp [R_1] at x_not_mem - . + · apply Set.union_subset - . simp [X_j] + · simp [X_j] grw [Metric.maximalSeparatedSet_subset] - . + · simp at x_mem simpa using x_mem - . + · simp apply Metric.IsSeparated.insert - . simp [X_j] + · simp [X_j] apply Metric.isSeparated_maximalSeparatedSet - . intro y hy hxy + · intro y hy hxy simp [B] at x_not_mem specialize x_not_mem y hy simp [edist, PseudoMetricSpace.edist] simp [dist] at x_not_mem exact x_not_mem - . + · rw [← lt_top_iff_ne_top] grw [Metric.packingNumber_le_encard_self] simp @@ -152,7 +143,7 @@ lemma B_half_disjoint (data: GoodScalesData b): (B_half data).PairwiseDisjoint i obtain ⟨y, y_mem, hy⟩ := hY by_cases x_eq_y : x = y - . + · rw [x_eq_y] at hx rw [← hx, ← hy] @@ -171,7 +162,6 @@ lemma B_half_disjoint (data: GoodScalesData b): (B_half data).PairwiseDisjoint i rw [dist_comm x a] at x_y_dist_bad grw [a_dist_x, a_dist_y] at x_y_dist_bad simp at x_y_dist_bad - -- TODO - we need a lemma that edist = ↑dist simp [edist, PseudoMetricSpace.edist] at x_sep simp [dist] at x_y_dist_bad grind @@ -201,6 +191,7 @@ lemma ball_subset_smul_origin (a: G) (r: ℝ): Metric.closedBall a r ⊆ (MulOpp simp at hx simpa using hx +omit v_wrapper_inst in lemma ball_smul_eq_origin (a: G) (r: ℝ): Metric.closedBall a r = (MulOpposite.op a) • Metric.closedBall 1 r := by ext x have foo := smul_origin_ball_subset a r @@ -222,8 +213,6 @@ lemma B_half_finite (data: GoodScalesData b): (B_half data).Finite := by apply finite_closed_ball @[expose] noncomputable def B_finsets (data: GoodScalesData b): Finset (Finset G) := Finset.image ((fun a => (finite_closed_ball a (R_1 data )).toFinset)) (X_j_finite data).toFinset - --- TODO - combine this with 'B_half' @[expose] noncomputable def B_half_finsets (data: GoodScalesData b): Finset (Finset G) := Finset.image ((fun a => (finite_closed_ball a (R_1 data / 2)).toFinset)) (X_j_finite data).toFinset @@ -240,10 +229,10 @@ lemma inter_mult_helper (data: GoodScalesData b): InterMult (B_3 data) * #(S ^ ( apply Nat.mul_le_of_le_div unfold InterMult by_cases h_s: InterMult_f (B_3 data) = ∅ - . simp [h_s] - . + · simp [h_s] + · rw [csSup_le_iff] - . + · intro n hn simp [InterMult_f] at hn obtain ⟨X, ⟨X_subset, X_inter⟩, X_card⟩ := hn @@ -252,7 +241,7 @@ lemma inter_mult_helper (data: GoodScalesData b): InterMult (B_3 data) * #(S ^ ( rw [Set.Finite.encard_eq_coe_toFinset_card X_finite] simp rw [Nat.le_div_iff_mul_le] - . + · have X_inner_nonempty: ∀ t ∈ X, ∃ a, a ∈ (X_j data) ∧ Metric.closedBall a (3 * (R_1 data + 1)) = t := by intro t ht specialize X_subset ht @@ -264,11 +253,11 @@ lemma inter_mult_helper (data: GoodScalesData b): InterMult (B_3 data) * #(S ^ ( rw [← Finset.sum_const] grw [Finset.sum_le_sum (g := fun a => if ha: a ∈ X then #(finite_closed_ball (X_inner_nonempty a ha).choose ((R_1 data) / 2)).toFinset else 0)] - . + · rw [← closed_ball_eq_S_pow] rw [Finset.sum_dite] rw [← Finset.card_biUnion] - . + · rw [← ne_eq, ← Set.nonempty_iff_ne_empty] at X_inter obtain ⟨base, h_base⟩ := X_inter @@ -287,7 +276,7 @@ lemma inter_mult_helper (data: GoodScalesData b): InterMult (B_3 data) * #(S ^ ( simp at ha simp obtain ⟨c, hc, a_dist⟩ := ha - . + · let q := (X_inner_nonempty c hc).choose grw [dist_triangle _ q] conv at a_dist => @@ -307,7 +296,7 @@ lemma inter_mult_helper (data: GoodScalesData b): InterMult (B_3 data) * #(S ^ ( simp [q] grw [h_base] grind - . + · rw [Finset.pairwiseDisjoint_iff] intro a _ b _ hab rw [Subtype.ext_iff] @@ -328,23 +317,23 @@ lemma inter_mult_helper (data: GoodScalesData b): InterMult (B_3 data) * #(S ^ ( simp only [Set.mem_image, id_eq, forall_exists_index, and_imp] at from_b simp at hab have inter_eq := from_b a_center a_center_mem (i := (Metric.closedBall a_center (↑(R_1 data) / 2) )) (?_) b_center b_center_mem (j := (Metric.closedBall b_center (↑(R_1 data) / 2) )) (?_) ?_ - . + · rw [← a_eq, ← b_eq] simp [a_center, b_center] at inter_eq apply B_ball_injective_on data (R_1 data / 2) (by grind) (by simp [R_1]) at inter_eq - . + · simp [inter_eq] - . grind - . grind - . rfl - . rfl - . simp [a_center, b_center] + · grind + · grind + · rfl + · rfl + · simp [a_center, b_center] rw [← Finset.coe_nonempty] at hab simp at hab exact hab - . intro y hy + · intro y hy simp at hy simp only [hy, ↓reduceDIte] nth_rw 1 [← Finset.card_smul_finset (MulOpposite.op (X_inner_nonempty y hy).choose)] @@ -365,10 +354,10 @@ lemma inter_mult_helper (data: GoodScalesData b): InterMult (B_3 data) * #(S ^ ( grw [Nat.cast_div_le] simp - . simp + · simp apply Finset.Nonempty.pow simp [S_nonempty] - . + · unfold BddAbove use (B_3 data).encard.toNat rw [mem_upperBounds] @@ -377,12 +366,12 @@ lemma inter_mult_helper (data: GoodScalesData b): InterMult (B_3 data) * #(S ^ ( obtain ⟨a, b, x_eq⟩ := hx rw [← x_eq] apply ENat.toNat_le_toNat - . + · apply Set.encard_le_encard grind - . simp + · simp apply B_3_finite - . rw [Set.nonempty_iff_ne_empty] + · rw [Set.nonempty_iff_ne_empty] grind @[expose] noncomputable def B_r (r: ℝ) := (finite_closed_ball 1 r).toFinset @@ -401,9 +390,9 @@ lemma pack_center_helper (data: GoodScalesData b) (x: G): #{ c ∈ (X_j_finite d rw [← closed_ball_eq_S_pow] grw [Finset.sum_le_sum (g := fun a => #(B_c_r a ↑((R_1 data : ℝ) / 2)))] - . + · rw [← Finset.card_biUnion] - . + · nth_rw 2 [← Finset.card_smul_finset (MulOpposite.op x)] apply Finset.card_le_card rw [← Finset.coe_subset] @@ -424,9 +413,9 @@ lemma pack_center_helper (data: GoodScalesData b) (x: G): #{ c ∈ (X_j_finite d rw [dist_comm] at x_mem grw [x_mem] rw [mul_add] - ring + ring_nf grind - . + · rw [Finset.pairwiseDisjoint_iff] intro a ha b hb hab @@ -437,27 +426,28 @@ lemma pack_center_helper (data: GoodScalesData b) (x: G): #{ c ∈ (X_j_finite d rw [Set.pairwiseDisjoint_iff] at from_b simp only [Set.mem_image, id_eq, forall_exists_index, and_imp] at from_b have inter_eq := from_b a ha.1 (i := (Metric.closedBall a ((↑(R_1 data) : ℝ) / 2) )) (?_) b hb.1 (j := (Metric.closedBall b (↑(R_1 data : ℝ) / 2) )) (?_) ?_ - . + · apply B_ball_injective_on data (R_1 data / 2) (by grind) (by simp [R_1]) at inter_eq - . + · simp [inter_eq] - . grind - . grind - . rfl - . rfl - . + · grind + · grind + · rfl + · rfl + · rw [← Finset.coe_nonempty] at hab simp [B_c_r] at hab simpa using hab - . + · intro a ha simp at ha simp [B_c_r_eq_smul, B_r] rw [Nat.cast_div] - . simp - . simp [R_1] - . simp + · simp + · simp [R_1] + · simp +omit [Nonempty ι] in /-- Common step for Lemma 3.25 (a) and (b). `h i = log (#(S ^ 16 ^ i) * det (Q_{16 ^ i}) ^ (dim V)⁻¹)` splits into a log-cardinality term @@ -483,8 +473,8 @@ lemma log_card_pow_sub_le {j k m n : ℕ} (hj : i₀ ≤ j) (hjk : j ≤ k) (hm0 -- `h k - h j` is non-negative and may be discarded. have det_le : (Q_R_matrix b ((16 ^ j : ℕ) : ℝ)).det ≤ (Q_R_matrix b ((16 ^ k : ℕ) : ℝ)).det := by apply matrix_det_montone - . exact pd_j - . unfold Q_R_matrix + · exact pd_j + · unfold Q_R_matrix rw [← map_sub] rw [← LinearMap.isPosSemidef_iff_posSemidef_toMatrix] apply Q_R_lin_sub_pos_semi_def @@ -501,150 +491,147 @@ lemma log_card_pow_sub_le {j k m n : ℕ} (hj : i₀ ≤ j) (hjk : j ≤ k) (hm0 Real.log ((#(S ^ m) : ℝ)) - Real.log ((#(S ^ n) : ℝ)) ≤ Real.log ((#(S ^ 16 ^ k) : ℝ)) - Real.log ((#(S ^ 16 ^ j) : ℝ)) := by apply sub_le_sub - . apply Real.log_le_log (card_pos m) + · apply Real.log_le_log (card_pos m) norm_cast exact Finset.card_pow_mono hm0 hm - . apply Real.log_le_log (card_pos (16 ^ j)) + · apply Real.log_le_log (card_pos (16 ^ j)) norm_cast exact Finset.card_pow_mono (by positivity) hn simp only [h, f] rw [Real.log_mul, Real.log_mul] - . linarith - . exact ne_of_gt (card_pos (16 ^ j)) - . exact ne_of_gt (Real.rpow_pos_of_pos pd_j.det_pos _) - . exact ne_of_gt (card_pos (16 ^ k)) - . exact ne_of_gt (Real.rpow_pos_of_pos + · linarith + · exact ne_of_gt (card_pos (16 ^ j)) + · exact ne_of_gt (Real.rpow_pos_of_pos pd_j.det_pos _) + · exact ne_of_gt (card_pos (16 ^ k)) + · exact ne_of_gt (Real.rpow_pos_of_pos (Q_R_matrix_pos_def_i₀ b _ i₀_le_k).det_pos _) -- Lemma 3.25 (a) lemma log_inter_mult_b3 (data: GoodScalesData b): InterMult (B_3 data) ≤ Real.exp (a data.d) := by by_cases mult_zero: InterMult (B_3 data) = 0 - . simp [mult_zero] + · simp [mult_zero] positivity rw [← Real.log_le_iff_le_exp] have foo := inter_mult_helper data rw [← Nat.le_div_iff_mul_le] at foo grw [foo] - . + · grw [Nat.cast_div_le] - . + · rw [Real.log_div] - . + · have bound := (GoodScales data).first_h_i grw [← bound] apply log_card_pow_sub_le (GoodScales data).i_1_ge (Nat.le_succ _) - . simp [R_1] - . rw [pow_succ] + · simp [R_1] + · rw [pow_succ] simp [R_1] - ring + ring_nf rw [← le_tsub_iff_right] - . + · rw [← Nat.mul_sub] norm_num grw [← Nat.one_le_pow] - . simp - . simp - . simp - . simp [R_1] - . norm_cast + · simp + · simp + · simp + · simp [R_1] + · norm_cast rw [Finset.card_eq_zero] rw [← ne_eq, ← Finset.nonempty_iff_ne_empty] apply Finset.Nonempty.pow simp [S_nonempty] - . norm_cast + · norm_cast rw [Finset.card_eq_zero] rw [← ne_eq, ← Finset.nonempty_iff_ne_empty] apply Finset.Nonempty.pow simp [S_nonempty] - . simp + · simp refine ⟨?_, ?_⟩ - . apply Finset.Nonempty.pow + · apply Finset.Nonempty.pow simp [S_nonempty] - . + · apply Finset.card_pow_mono - . simp [R_1] - . grind - . + · simp [R_1] + · grind + · simp apply Finset.Nonempty.pow simp [S_nonempty] - . simp + · simp grind lemma log_pack_center_helper (data: GoodScalesData b) (x: G): #{ c ∈ (X_j_finite data).toFinset | x ∈ B_c_r c (3 * (R_1 data + 1)) } ≤ Real.exp (a data.d) := by by_cases inter_empty: { c ∈ (X_j_finite data).toFinset | x ∈ B_c_r c (3 * (R_1 data + 1)) } = ∅ - . simp [inter_empty] + · simp [inter_empty] apply Real.exp_nonneg rw [← Real.log_le_iff_le_exp] have foo := pack_center_helper data x rw [← Nat.le_div_iff_mul_le] at foo grw [foo] - . + · grw [Nat.cast_div_le] - . + · rw [Real.log_div] - . + · have bound := (GoodScales data).first_h_i grw [← bound] apply log_card_pow_sub_le (GoodScales data).i_1_ge (Nat.le_succ _) - . simp [R_1] - . rw [pow_succ] + · simp [R_1] + · rw [pow_succ] simp [R_1] - ring + ring_nf rw [← le_tsub_iff_right] - . + · rw [← Nat.mul_sub] norm_num grw [← Nat.one_le_pow] - . simp - . simp - . simp - . simp [R_1] - . norm_cast + · simp + · simp + · simp + · simp [R_1] + · norm_cast rw [Finset.card_eq_zero] rw [← ne_eq, ← Finset.nonempty_iff_ne_empty] apply Finset.Nonempty.pow simp [S_nonempty] - . norm_cast + · norm_cast rw [Finset.card_eq_zero] rw [← ne_eq, ← Finset.nonempty_iff_ne_empty] apply Finset.Nonempty.pow simp [S_nonempty] - . simp + · simp refine ⟨?_, ?_⟩ - . apply Finset.Nonempty.pow + · apply Finset.Nonempty.pow simp [S_nonempty] - . + · apply Finset.card_pow_mono - . simp [R_1] - . grind - . + · simp [R_1] + · grind + · simp rw [Finset.nonempty_iff_ne_empty] simpa using inter_empty - . simp + · simp apply Finset.Nonempty.pow simp [S_nonempty] - . simp + · simp rw [Finset.nonempty_iff_ne_empty] simpa using inter_empty -#print axioms inter_mult_helper -#print axioms log_inter_mult_b3 -#print axioms log_pack_center_helper -- Lemma 3.25 (b) lemma card_B_le_exp_wa (data: GoodScalesData b): #(B_finite data).toFinset < Real.exp (data.w * (a data.d)) := by have B_union := Finset.card_biUnion (s := (B_half_finsets data)) (t := id) ?_ - . + · simp at B_union have sum_le := Finset.sum_eq_card_nsmul (f := fun (u: Finset G) => #u) (s := B_half_finsets data) (b := #(S ^ (R_1 data / 2))) ?_ - . + · rw [← Nat.card_eq_card_finite_toFinset] simp [B] grw [Set.ncard_image_le (hs := by apply X_j_finite)] @@ -676,33 +663,33 @@ lemma card_B_le_exp_wa (data: GoodScalesData b): #(B_finite data).toFinset < Rea grw [sum_le] rw [← B_union] grw [Finset.card_le_card (t := (finite_closed_ball (1: G) ↑(2 * (R_2 data))).toFinset)] - . + · grw [Nat.cast_div_le] rw [card_closed_ball_eq] - . + · rw [← Real.log_lt_iff_lt_exp] - . + · apply lt_of_le_of_lt ?_ ((GoodScales data).h_diff_lt_w) rw [Real.log_div (by simp; grind [S_nonempty]) (by simp; grind [S_nonempty])] apply log_card_pow_sub_le (GoodScales data).i_1_ge - . -- `i_2 - i_1 > w ≥ 0` forces `i_1 < i_2` + · -- `i_2 - i_1 > w ≥ 0` forces `i_1 < i_2` have hdiff := (GoodScales data).i_diff_mem simp [Set.mem_Ioo] at hdiff omega - . simp [R_2] - . rw [pow_succ] + · simp [R_2] + · rw [pow_succ] simp [R_2] omega - . simp [R_1] - . + · simp [R_1] + · apply div_pos - . simp + · simp apply Finset.Nonempty.pow simp [S_nonempty] - . simp + · simp apply Finset.Nonempty.pow simp [S_nonempty] - . + · intro a ha simp at ha obtain ⟨x, x_mem, hx⟩ := ha @@ -723,10 +710,10 @@ lemma card_B_le_exp_wa (data: GoodScalesData b): #(B_finite data).toFinset < Rea simp at foo grind grw [i_1_le] - . + · grind - . simp - . + · simp + · intro b hb simp [B_half_finsets] at hb obtain ⟨c, c_mem, b_eq⟩ := hb @@ -734,8 +721,6 @@ lemma card_B_le_exp_wa (data: GoodScalesData b): #(B_finite data).toFinset < Rea rw [← Set.toFinite_toFinset] rw [← Nat.card_eq_card_finite_toFinset] rw [ball_smul_eq_origin] - - -- TODO - make the various finite/fintype/card conversion less awful conv => lhs equals (MulOpposite.op c • (Metric.closedBall (1: G) (↑(R_1 data) / 2))).ncard => @@ -750,8 +735,7 @@ lemma card_B_le_exp_wa (data: GoodScalesData b): #(B_finite data).toFinset < Rea simp [R_1] rw [card_closed_ball_eq] - . - -- TODO - there must be a less horrendous way of dealing with Finset here + · simp [B_half_finsets] have foo := B_half_disjoint data simp [B_half] at foo diff --git a/Gromov/Poincare.lean b/Gromov/Poincare.lean index 81268ad..1b399d6 100644 --- a/Gromov/Poincare.lean +++ b/Gromov/Poincare.lean @@ -11,11 +11,6 @@ public import Gromov.Packing public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false open scoped Finset open scoped Pointwise @@ -55,7 +50,7 @@ lemma deriv_sq_R_inv_comp (f: G → ℝ) (x: G): apply Finset.sum_nbij' (i := fun s => s⁻¹) (j := fun s => s⁻¹) <;> simp +contextual [hGS.has_inv, mul_inv_rev] -omit v_wrapper_inst in +omit hGS v_wrapper_inst in lemma three_term_cs (a b: ℝ) (n: Type*) {s: Finset n} (f: n → ℝ): a + (∑ x ∈ s, f x) + b ≤ √(a^2 + (∑ x ∈ s, (f x)^2) + b^2) * √(2 + #(s)) := by conv => lhs @@ -77,7 +72,7 @@ lemma ball_x_one_subset (x: G): (Metric.closedBall x 1) ⊆ ((x) • S) ∪ ((Mu obtain ⟨l, l_prod, l_len⟩ := word_norm_prod_self (x * a⁻¹) simp [ProdS] at l_prod by_cases l_len_eq: l.length = 0 - . + · have l_eq: l = [] := by grind simp [l_eq] at l_prod rw [eq_comm, mul_inv_eq_one] at l_prod @@ -85,7 +80,7 @@ lemma ball_x_one_subset (x: G): (Metric.closedBall x 1) ⊆ ((x) • S) ∪ ((Mu use 1 simp [one_mem] grind - . + · rw [← l_len] at ha have l_len_one: l.length = 1 := by grind rw [List.length_eq_one_iff] at l_len_one @@ -98,21 +93,22 @@ lemma ball_x_one_subset (x: G): (Metric.closedBall x 1) ⊆ ((x) • S) ∪ ((Mu rw [l_prod] refine ⟨?_, ?_⟩ - . + · rw [← Finset.mem_inv'] rw [← S_eq_Sinv] simp - . - simp [l_prod] -omit v_wrapper_inst in + · + simp +omit hGS v_wrapper_inst in lemma le_of_sub_eq (a b c: ℝ) (ha: a = b - c) (hc: 0 ≤ c): a ≤ b := by grind +omit v_wrapper_inst in lemma double_ball_sum (R: ℕ) (hR: 0 < R) (f: G → ℝ) (hf: ∀ g, 0 ≤ f g): ∑ x ∈ B_r (↑(R - 1)), ∑ y ∈ (Metric.closedBall x 1), f y ≤ 2 * #S * ∑ x ∈ B_r R, f x := by classical grw [Finset.sum_le_sum (g := fun x => ∑ y ∈ ((x) • S) ∪ ((MulOpposite.op x • S)), f y)] - . + · have union_sub (x: G) := Finset.sum_union_inter (f := f) (s₁ := x • S) (s₂ := (MulOpposite.op x • S)) simp_rw [← eq_sub_iff_add_eq] at union_sub have foo (x) := le_of_sub_eq _ _ _ (union_sub x) (by @@ -131,12 +127,12 @@ lemma double_ball_sum (R: ℕ) (hR: 0 < R) (f: G → ℝ) (hf: ∀ g, 0 ≤ f g) have card_le (i: G) : #({a ∈ B_r ↑(R - 1) ×ˢ S | a.1 • a.2 = i}) ≤ #S := by apply Finset.card_le_card_of_injOn (f := fun p => p.1⁻¹ * i) - . intro a ha + · intro a ha simp at ha simp simp [← ha.2] grind - . intro a ha b hb hab + · intro a ha b hb hab simp at hab simp at ha simp at hb @@ -149,12 +145,12 @@ lemma double_ball_sum (R: ℕ) (hR: 0 < R) (f: G → ℝ) (hf: ∀ g, 0 ≤ f g) have card_le_rev (i: G) : #({a ∈ B_r ↑(R - 1) ×ˢ S | a.2 * a.1 = i}) ≤ #S := by apply Finset.card_le_card_of_injOn (f := fun p => i * p.1⁻¹) - . intro a ha + · intro a ha simp at ha simp simp [← ha.2] grind - . intro a ha b hb hab + · intro a ha b hb hab simp at hab simp at ha simp at hb @@ -170,31 +166,30 @@ lemma double_ball_sum (R: ℕ) (hR: 0 < R) (f: G → ℝ) (hf: ∀ g, 0 ≤ f g) rw [← Finset.sum_product'] simp_rw [Finset.sum_comp] grw [Finset.sum_le_sum_of_subset_of_nonneg (t := B_r R)] - . + · grw [Finset.sum_le_sum (g := fun i => #S • f i)] - . + · simp rw [← Finset.mul_sum] rw [add_comm] grw [Finset.sum_le_sum_of_subset_of_nonneg (t := B_r R)] - . + · grw [Finset.sum_le_sum (g := fun i => #S • f i)] - . + · simp rw [← Finset.mul_sum] rw [← mul_add] grind - . + · intro i hi simp - -- TODO - why doesn't grw work here apply mul_le_mul - . simp + · simp apply card_le_rev - . simp - . apply hf - . simp - . + · simp + · apply hf + · simp + · rw [Finset.image_subset_iff] intro x hx simp at hx @@ -204,17 +199,17 @@ lemma double_ball_sum (R: ℕ) (hR: 0 < R) (f: G → ℝ) (hf: ∀ g, 0 ≤ f g) grw [hx.1] have norm_s := word_norm_le x.2 [⟨x.2, hx.2⟩] (by simp [ProdS]) grw [norm_s] - simp [hR] + simp grind - . intros + · intros apply mul_nonneg - . simp - . apply hf - . intro i hi + · simp + · apply hf + · intro i hi grw [card_le] apply hf - . rw [Finset.image_subset_iff] + · rw [Finset.image_subset_iff] intro x hx simp at hx simp [B_r, dist, WordDist_one] @@ -224,79 +219,168 @@ lemma double_ball_sum (R: ℕ) (hR: 0 < R) (f: G → ℝ) (hf: ∀ g, 0 ≤ f g) have norm_s := word_norm_le x.2 [⟨x.2, hx.2⟩] (by simp [ProdS]) grw [norm_s] simp [hR] - . intros + · intros simp apply mul_nonneg - . simp - . apply hf - . intro i hi + · simp + · apply hf + · intro i hi grw [Finset.sum_le_sum_of_subset_of_nonneg] - . + · simp apply ball_x_one_subset - . intros + · intros apply hf --- TODO - get rid of some lemmas, since mathlib already has Metric.smul_closedBall defined - --- Theorem 3.20 -set_option maxHeartbeats 3500000 in -lemma poincare_inequality (R: ℕ) (f: G → ℝ): ∑ x ∈ (B_r (R - 1)), |f x - (f_avg (R - 1) f)|^2 ≤ - 16 * R^2 * #S * (#(B_r (2 * R - 2))) / #(B_r (R - 1)) * ∑ x ∈ (B_r (3 * R)), deriv_sq_R f x := by +omit v_wrapper_inst in +private lemma poincare_average_bound (R : ℕ) (f : G → ℝ) (R_nonpos : R ≠ 0) (x : G) : |f x - f_avg (R - 1) f| ≤ √((#((B_r (R - 1))) : ℝ)⁻¹ * (∑ y ∈ (B_r (R - 1)), (f x - f y)^2)) := by + rw [f_avg] + conv => + lhs + arg 1 + arg 1 + equals (#((B_r (↑R - 1))) : ℝ)⁻¹ * ∑ y ∈ (B_r (↑R - 1)), f x => + simp + rw [inv_mul_cancel_left₀] + simp [B_r] + exact Set.ncard_ne_zero_of_mem (a := 1) (by simp; grind) (finite_closed_ball 1 _) - by_cases R_nonpos: R = 0 - . - simp [R_nonpos, f_avg, B_r] + rw [B_r] + rw [← mul_sub] + rw [abs_mul] + rw [← Finset.sum_sub_distrib] + grw [Finset.abs_sum_le_sum_abs] + conv => + lhs + rhs + arg 2 + intro i + equals |f x - f i| * 1 => simp + grw [Real.sum_mul_le_sqrt_mul_sqrt] + simp [Real.sqrt_eq_rpow] + rw [← Real.rpow_neg_one] + rw [mul_comm] + rw [mul_assoc] + rw [← Real.rpow_add] + · + norm_num + simp + rw [Real.mul_rpow] + · + field_simp + rw [← Real.rpow_mul] + · + simp + · positivity + · positivity + · positivity - let δ_f (x: G) := ∑ x ∈ (finite_closed_ball x 1).toFinset, deriv_sq_R f x + · simp + rw [Set.ncard_pos (finite_closed_ball 1 _)] + exact ⟨1, by simp; grind⟩ - have f_sub_le (x: G): |f x - f_avg (R - 1) f| ≤ √((#((B_r (R - 1))) : ℝ)⁻¹ * (∑ y ∈ (B_r (R - 1)), (f x - f y)^2)) := by - rw [f_avg] +omit v_wrapper_inst in +private lemma poincare_path_sum (R : ℕ) (f : G → ℝ) (R_nonpos : R ≠ 0) : + let δ_f (x : G) := ∑ x ∈ (finite_closed_ball x 1).toFinset, deriv_sq_R f x + let γ (z : G) (i : ℕ) := ((word_norm_prod_self z).choose.take i).unattach.prod + ∀ (z: G) (_hz: z ∈ B_r (2*R - 2)), ∑ x ∈ B_r (R - 1), ∑ i ∈ Finset.range (WordNorm z), δ_f (x * (γ z i)) ≤ 2 * R * ∑ x ∈ B_r (3*R - 1), δ_f x := by + dsimp only + let δ_f (x : G) := ∑ x ∈ (finite_closed_ball x 1).toFinset, deriv_sq_R f x + let γ (z : G) (i : ℕ) := ((word_norm_prod_self z).choose.take i).unattach.prod + have gamma_zero (z: G): γ z 0 = 1 := by simp [γ] + have gamma_norm (z: G): γ z (WordNorm z) = z := by + simp [γ] + obtain ⟨prod, len_eq⟩ := (word_norm_prod_self z).choose_spec + simp [ProdS] at prod conv => - lhs - arg 1 arg 1 - equals (#((B_r (↑R - 1))) : ℝ)⁻¹ * ∑ y ∈ (B_r (↑R - 1)), f x => - simp - rw [inv_mul_cancel_left₀] - simp [B_r] - exact Set.ncard_ne_zero_of_mem (a := 1) (by simp; grind) (finite_closed_ball 1 _) + pattern (WordNorm z) + rw [← len_eq] - rw [B_r] - rw [← mul_sub] - rw [abs_mul] - rw [← Finset.sum_sub_distrib] - grw [Finset.abs_sum_le_sum_abs] - conv => - lhs - rhs - arg 2 - intro i - equals |f x - f i| * 1 => simp - grw [Real.sum_mul_le_sqrt_mul_sqrt] - simp [Real.sqrt_eq_rpow] - rw [← Real.rpow_neg_one] - rw [mul_comm] - rw [mul_assoc] - rw [← Real.rpow_add] - . - norm_num + simp + exact prod + + have gamma_i_norm_le (z: G) (i: ℕ): WordNorm (γ z i) ≤ i := by + simp [γ] + + have i_le := word_norm_le ((word_norm_prod_self z).choose.take i).unattach.prod ((word_norm_prod_self z).choose.take i) (by simp [ProdS]) + grw [List.length_take_le] at i_le + exact i_le + + intro z hz + change ∑ x ∈ B_r (R - 1), ∑ i ∈ Finset.range (WordNorm z), δ_f (x * (γ z i)) ≤ 2 * R * ∑ x ∈ B_r (3*R - 1), δ_f x + + rw [← Finset.sum_product'] + rw [Finset.sum_comp] + simp + grw [Finset.sum_le_sum (g := fun a => (((2 * R) : ℝ) * (δ_f a)))] + · + rw [← Finset.mul_sum] + grw [Finset.sum_le_sum_of_subset_of_nonneg (t := B_r (3*R - 1))] + · + intro p hp + simp at hp + obtain ⟨a, b, ⟨a_mem, b_lt⟩, p_eq⟩ := hp + rw [← p_eq] + simp [B_r, dist, WordDist_one] + grw [word_norm_mul_le] + simp [B_r, dist, WordDist_one] at a_mem + simp [B_r, dist, WordDist_one] at hz simp - rw [Real.mul_rpow] - . - field_simp - rw [← Real.rpow_mul] - . - simp - . positivity - . positivity - . positivity + grw [a_mem] + grw [gamma_i_norm_le] + grw [b_lt] + grw [hz] + grind + · intro p hp _ + simp [δ_f, deriv_sq_R] + positivity + · + intro b hb + simp at hb + obtain ⟨x, n, ⟨x_mem, n_lt⟩, b_eq⟩ := hb + grw [Finset.card_le_card (t := (Finset.range (2 * R)).image (fun n => (b * ((γ z n)⁻¹), n)))] + · + grw [Finset.card_image_le] + · simp + · simp [δ_f, deriv_sq_R] + positivity + · + simp [δ_f, deriv_sq_R] + positivity + · + intro p hp + simp at hp + simp + use p.2 + refine ⟨?_, ?_⟩ + · - . simp - rw [Set.ncard_pos (finite_closed_ball 1 _)] - exact ⟨1, by simp; grind⟩ + by_contra! + grw [hp.1.2] at this + simp [B_r, dist, WordDist_one] at hz + conv at hz => + rhs + equals ↑(2*R - 2) => + rw [Nat.cast_sub] + simp + grind - let γ (z: G) (i: ℕ) := ((word_norm_prod_self z).choose.take i).unattach.prod + norm_cast at hz + grind + · + ext + · simp [← hp.2] + · simp + +omit v_wrapper_inst in +private lemma poincare_difference_bound (R : ℕ) (f : G → ℝ) (R_nonpos : R ≠ 0) : + let δ_f (x : G) := ∑ x ∈ (finite_closed_ball x 1).toFinset, deriv_sq_R f x + let γ (z : G) (i : ℕ) := ((word_norm_prod_self z).choose.take i).unattach.prod + ∀ (x y: G) (_hx: x ∈ B_r (R - 1)) (_hy: y ∈ B_r (R - 1)), |f y - f x| ≤ √((2 * R) * (∑ i ∈ Finset.range (WordNorm (x⁻¹ * y)), δ_f (x * γ (x⁻¹ * y) i))) := by + dsimp only + let δ_f (x : G) := ∑ x ∈ (finite_closed_ball x 1).toFinset, deriv_sq_R f x + let γ (z : G) (i : ℕ) := ((word_norm_prod_self z).choose.take i).unattach.prod have gamma_zero (z: G): γ z 0 = 1 := by simp [γ] have gamma_norm (z: G): γ z (WordNorm z) = z := by simp [γ] @@ -317,163 +401,118 @@ lemma poincare_inequality (R: ℕ) (f: G → ℝ): ∑ x ∈ (B_r (R - 1)), |f x grw [List.length_take_le] at i_le exact i_le - have gamma_sum (z: G) (hz: z ∈ B_r (2*R - 2)): ∑ x ∈ B_r (R - 1), ∑ i ∈ Finset.range (WordNorm z), δ_f (x * (γ z i)) ≤ 2 * R * ∑ x ∈ B_r (3*R - 1), δ_f x := by + intro x y hx hy + change |f y - f x| ≤ √((2 * R) * (∑ i ∈ Finset.range (WordNorm (x⁻¹ * y)), δ_f (x * γ (x⁻¹ * y) i))) - rw [← Finset.sum_product'] - rw [Finset.sum_comp] - simp - grw [Finset.sum_le_sum (g := fun a => (((2 * R) : ℝ) * (δ_f a)))] - . - rw [← Finset.mul_sum] - grw [Finset.sum_le_sum_of_subset_of_nonneg (t := B_r (3*R - 1))] - . - intro p hp - simp at hp - obtain ⟨a, b, ⟨a_mem, b_lt⟩, p_eq⟩ := hp - rw [← p_eq] - simp [B_r, dist, WordDist_one] - grw [word_norm_mul_le] - simp [B_r, dist, WordDist_one] at a_mem - simp [B_r, dist, WordDist_one] at hz + have inv_prod_le: WordNorm (x⁻¹ * y) ≤ 2*R - 2 := by + grw [word_norm_mul_le] + rw [← word_norm_inv] + simp [B_r, dist, WordDist_one] at hx hy + conv at hx => + rhs + equals ↑(R - 1) => + rw [Nat.cast_sub] simp - grw [a_mem] - grw [gamma_i_norm_le] - grw [b_lt] - grw [hz] grind - . intro p hp _ - simp [δ_f, deriv_sq_R] - positivity - . - intro b hb - simp at hb - obtain ⟨x, n, ⟨x_mem, n_lt⟩, b_eq⟩ := hb - grw [Finset.card_le_card (t := (Finset.range (2 * R)).image (fun n => (b * ((γ z n)⁻¹), n)))] - . - grw [Finset.card_image_le] - . simp - . simp [δ_f, deriv_sq_R] - positivity - . - simp [δ_f, deriv_sq_R] - positivity - . - intro p hp - simp at hp + conv at hy => + rhs + equals ↑(R - 1) => + rw [Nat.cast_sub] simp - use p.2 - refine ⟨?_, ?_⟩ - . - - by_contra! - grw [hp.1.2] at this - simp [B_r, dist, WordDist_one] at hz - conv at hz => - rhs - equals ↑(2*R - 2) => - rw [Nat.cast_sub] - simp - grind + grind + norm_cast at hx hy + grw [hx, hy] + grind - norm_cast at hz - grind - . - ext - . simp [← hp.2] - . simp + have root_le_R: √(WordNorm (x⁻¹ * y)) ≤ √(2*R) := by + rw [Real.sqrt_le_sqrt_iff] + · norm_cast + grw [inv_prod_le] + simp + · simp - have diff_le_delta_sum (x y: G) (hx: x ∈ B_r (R - 1)) (hy: y ∈ B_r (R - 1)): |f y - f x| ≤ √((2 * R) * (∑ i ∈ Finset.range (WordNorm (x⁻¹ * y)), δ_f (x * γ (x⁻¹ * y) i))) := by + conv => + lhs + equals |(f (x * γ (x⁻¹ * y) (WordNorm (x⁻¹ * y)))) - f (x * γ (x⁻¹ * y) 0)| => + simp [gamma_zero, gamma_norm] - have inv_prod_le: WordNorm (x⁻¹ * y) ≤ 2*R - 2 := by - grw [word_norm_mul_le] - rw [← word_norm_inv] - simp [B_r, dist, WordDist_one] at hx hy - conv at hx => - rhs - equals ↑(R - 1) => - rw [Nat.cast_sub] - simp - grind - conv at hy => - rhs - equals ↑(R - 1) => - rw [Nat.cast_sub] - simp - grind - norm_cast at hx hy - grw [hx, hy] - grind + rw [← Finset.sum_range_sub (n := WordNorm (x⁻¹ * y)) (f := fun i => f (x * γ (x⁻¹ * y) i))] + grw [Finset.abs_sum_le_sum_abs] + conv => + lhs + arg 2 + intro i + rw [← mul_one (a := |_|)] - have root_le_R: √(WordNorm (x⁻¹ * y)) ≤ √(2*R) := by - rw [Real.sqrt_le_sqrt_iff] - . norm_cast - grw [inv_prod_le] - simp - . simp + grw [Real.sum_mul_le_sqrt_mul_sqrt] + simp + grw [root_le_R] + + have sum_le_delta: ∑ x_1 ∈ Finset.range (WordNorm (x⁻¹ * y)), (f (x * γ (x⁻¹ * y) x_1) - f (x * γ (x⁻¹ * y) (x_1 + 1))) ^ 2 ≤ ∑ n ∈ Finset.range (WordNorm (x⁻¹ * y)), δ_f (x * (γ (x⁻¹ * y) n)) := by + apply Finset.sum_le_sum + intro n hn + simp [δ_f, deriv_sq_R] + rw [← Finset.add_sum_erase (a := (x * γ (x⁻¹ * y) n))] + · + apply le_add_of_le_of_nonneg + · + let s := (word_norm_prod_self (x⁻¹ * y)).choose[n]?.getD ⟨1, one_mem⟩ + rw [← Finset.add_sum_erase (a := s.val) (h := by simp)] + apply le_add_of_le_of_nonneg + · + rw [sub_sq_comm] + conv => + rhs + lhs + arg 1 + arg 1 + equals x * γ (x⁻¹ * y) (n + 1) => + + rw [mul_assoc, mul_left_cancel_iff] + simp [γ, s] + by_cases n_add_lt: (n) < (word_norm_prod_self (x⁻¹ * y)).choose.length + · + simp [n_add_lt] + rw [List.take_add_one] + simp + rw [getElem?_pos] + · simp + · grind + · + simp [n_add_lt] + rw [List.take_add_one] + simp + rw [getElem?_neg] + · simp + · grind + · positivity + · positivity + · simp [dist, WordDist, word_norm_one] + + simp_rw [sub_sq_comm] + grw [sum_le_delta] + rw [mul_comm] + simp - conv => - lhs - equals |(f (x * γ (x⁻¹ * y) (WordNorm (x⁻¹ * y)))) - f (x * γ (x⁻¹ * y) 0)| => - simp [gamma_zero, gamma_norm] +-- Theorem 3.20 +omit v_wrapper_inst in +lemma poincare_inequality (R: ℕ) (f: G → ℝ): ∑ x ∈ (B_r (R - 1)), |f x - (f_avg (R - 1) f)|^2 ≤ + 16 * R^2 * #S * (#(B_r (2 * R - 2))) / #(B_r (R - 1)) * ∑ x ∈ (B_r (3 * R)), deriv_sq_R f x := by - rw [← Finset.sum_range_sub (n := WordNorm (x⁻¹ * y)) (f := fun i => f (x * γ (x⁻¹ * y) i))] - grw [Finset.abs_sum_le_sum_abs] - conv => - lhs - arg 2 - intro i - rw [← mul_one (a := |_|)] + by_cases R_nonpos: R = 0 + · + simp [R_nonpos, f_avg, B_r] - grw [Real.sum_mul_le_sqrt_mul_sqrt] - simp - grw [root_le_R] + let δ_f (x: G) := ∑ x ∈ (finite_closed_ball x 1).toFinset, deriv_sq_R f x - have sum_le_delta: ∑ x_1 ∈ Finset.range (WordNorm (x⁻¹ * y)), (f (x * γ (x⁻¹ * y) x_1) - f (x * γ (x⁻¹ * y) (x_1 + 1))) ^ 2 ≤ ∑ n ∈ Finset.range (WordNorm (x⁻¹ * y)), δ_f (x * (γ (x⁻¹ * y) n)) := by - apply Finset.sum_le_sum - intro n hn - simp [δ_f, deriv_sq_R] - rw [← Finset.add_sum_erase (a := (x * γ (x⁻¹ * y) n))] - . - apply le_add_of_le_of_nonneg - . - let s := (word_norm_prod_self (x⁻¹ * y)).choose[n]?.getD ⟨1, one_mem⟩ - rw [← Finset.add_sum_erase (a := s.val) (h := by simp)] - apply le_add_of_le_of_nonneg - . - rw [sub_sq_comm] - conv => - rhs - lhs - arg 1 - arg 1 - equals x * γ (x⁻¹ * y) (n + 1) => - - rw [mul_assoc, mul_left_cancel_iff] - simp [γ, s] - -- TODO - we can probably use hn instead of this case split - by_cases n_add_lt: (n) < (word_norm_prod_self (x⁻¹ * y)).choose.length - . - simp [n_add_lt] - rw [List.take_add_one] - simp - rw [getElem?_pos] - . simp - . grind - . - simp [n_add_lt] - rw [List.take_add_one] - simp - rw [getElem?_neg] - . simp - . grind - . positivity - . positivity - . simp [dist, WordDist, word_norm_one] - - simp_rw [sub_sq_comm] - grw [sum_le_delta] - rw [mul_comm] - simp + have f_sub_le := poincare_average_bound R f R_nonpos + + let γ (z: G) (i: ℕ) := ((word_norm_prod_self z).choose.take i).unattach.prod + have gamma_sum (z : G) (hz : z ∈ B_r (2*R - 2)) : ∑ x ∈ B_r (R - 1), ∑ i ∈ Finset.range (WordNorm z), δ_f (x * (γ z i)) ≤ 2 * R * ∑ x ∈ B_r (3*R - 1), δ_f x := + poincare_path_sum R f R_nonpos z hz + + have diff_le_delta_sum (x y : G) (hx : x ∈ B_r (R - 1)) (hy : y ∈ B_r (R - 1)) : |f y - f x| ≤ √((2 * R) * (∑ i ∈ Finset.range (WordNorm (x⁻¹ * y)), δ_f (x * γ (x⁻¹ * y) i))) := + poincare_difference_bound R f R_nonpos x y hx hy conv at f_sub_le => intro x @@ -510,9 +549,8 @@ lemma poincare_inequality (R: ℕ) (f: G → ℝ): ∑ x ∈ (B_r (R - 1)), |f x rw [Finset.sum_product] simp only [] rw [Finset.sum_comm] - -- TODO - use gcongr here grw [Finset.sum_le_sum (g := fun z => ∑ x ∈ B_r (2*R - 2), ∑ i ∈ Finset.range (WordNorm x), δ_f (z * γ x i))] - . + · rw [Finset.sum_comm] grw [Finset.sum_le_sum (h := gamma_sum)] simp [δ_f] @@ -534,37 +572,37 @@ lemma poincare_inequality (R: ℕ) (f: G → ℝ): ∑ x ∈ (B_r (R - 1)), |f x simp grind grw [double_ball_sum] - . + · norm_cast have four_le: (4: ℝ) ≤ 8 := by grind grw [four_le] simp [deriv_sq_R] - ring + ring_nf simp simp [deriv_sq_R] positivity - . simp + · simp grind - . intro g + · intro g simp [deriv_sq_R] positivity - . intro a ha + · intro a ha rw [Finset.sum_comp (g := fun y => a⁻¹ * y) (f := fun x => ∑ x_1 ∈ Finset.range (WordNorm (x)), δ_f (a * γ (x) x_1))] grw [Finset.sum_le_sum_of_subset_of_nonneg (t := B_r (2*R - 2))] - . + · simp_rw [inv_mul_eq_iff_eq_mul] simp_rw [Finset.card_filter] simp apply Finset.sum_le_sum intro x hx split_ifs - . simp - . simp [δ_f, deriv_sq_R] + · simp + · simp [δ_f, deriv_sq_R] positivity - . + · rw [Finset.image_subset_iff] intro x hx simp [B_r, dist, WordDist_one] @@ -574,22 +612,23 @@ lemma poincare_inequality (R: ℕ) (f: G → ℝ): ∑ x ∈ (B_r (R - 1)), |f x simp grw [ha, hx] grind - . + · intros simp [δ_f, deriv_sq_R] positivity -#print axioms poincare_inequality -- `B_r` is centred at `1`, so it is closed under inversion (`word_norm_inv`). omit v_wrapper_inst in lemma mem_B_r_inv (r: ℝ) (x: G): x⁻¹ ∈ B_r r ↔ x ∈ B_r r := by simp [B_r, dist, WordDist_one, ← word_norm_inv] +omit v_wrapper_inst in lemma sum_B_r_inv (r: ℝ) (g: G → ℝ): ∑ x ∈ B_r r, g x⁻¹ = ∑ x ∈ B_r r, g x := by apply Finset.sum_nbij' (i := fun x => x⁻¹) (j := fun x => x⁻¹) <;> simp +contextual [mem_B_r_inv] +omit v_wrapper_inst in lemma f_avg_inv (r: ℝ) (f: G → ℝ): f_avg r (fun y => f y⁻¹) = f_avg r f := by unfold f_avg rw [show (finite_closed_ball (1: G) r).toFinset = B_r r from rfl, sum_B_r_inv] @@ -597,6 +636,7 @@ lemma f_avg_inv (r: ℝ) (f: G → ℝ): f_avg r (fun y => f y⁻¹) = f_avg r f -- Theorem 3.20, restated for the *left* Cayley graph. Rather than mirroring the (long) proof of -- `poincare_inequality`, we conjugate it by the inversion `x ↦ x⁻¹`: this is a bijection of every -- `B_r r` (`mem_B_r_inv`) and carries `deriv_sq_R` to `deriv_sq` (`deriv_sq_R_inv_comp`). +omit v_wrapper_inst in lemma poincare_inequality_left (R: ℕ) (f: G → ℝ): ∑ x ∈ (B_r (R - 1)), |f x - (f_avg (R - 1) f)|^2 ≤ 16 * R^2 * #S * (#(B_r (2 * R - 2))) / #(B_r (R - 1)) * ∑ x ∈ (B_r (3 * R)), deriv_sq f x := by have poincare := poincare_inequality R (fun y => f y⁻¹) @@ -610,7 +650,6 @@ lemma poincare_inequality_left (R: ℕ) (f: G → ℝ): ∑ x ∈ (B_r (R - 1)), exact Finset.sum_congr rfl (fun x _ => deriv_sq_R_inv_comp f x)] at poincare exact poincare -#print axioms poincare_inequality_left omit v_wrapper_inst in lemma card_B_r_eq (R: ℕ): #(B_r R) = #(S ^ R) := by @@ -648,11 +687,11 @@ lemma lemma_3_25_poincare (data: GoodScalesData b) (j: (X_j data)) (f: G → ℝ rw [B_c_r_eq_smul] rw [← Finset.image_smul] rw [Finset.sum_image] - . + · simp left simp [B_r] - . simp + · simp simp_rw [sq_abs] grw [poincare] @@ -662,8 +701,8 @@ lemma lemma_3_25_poincare (data: GoodScalesData b) (j: (X_j data)) (f: G → ℝ rw [← Real.log_le_iff_le_exp] - . rw [Real.log_div] - . + · rw [Real.log_div] + · rw [card_B_r_eq] @@ -678,42 +717,41 @@ lemma lemma_3_25_poincare (data: GoodScalesData b) (j: (X_j data)) (f: G → ℝ simp rw [card_B_r_eq] grw [log_card_pow_sub_le (b := b) (k := (GoodScales data).i_1 + 1) (j := (GoodScales data).i_1)] - . + · grw [(GoodScales data).first_h_i] - . + · apply (GoodScales data).i_1_ge - . simp - . simp + · simp + · simp grind - . simp + · simp have h_i_1 := (GoodScales data).i_1_ge simp [i₀, R'] at h_i_1 simp [R_1] - ring + ring_nf grind - . + · simp [R_1] - . simp only [B_r, Set.toFinite_toFinset, ne_eq, Nat.cast_eq_zero] + · simp only [B_r, Set.toFinite_toFinset, ne_eq, Nat.cast_eq_zero] apply Finset.card_ne_zero_of_mem (a := 1) simp [R_1] - . simp only [B_r, Set.toFinite_toFinset, ne_eq, Nat.cast_eq_zero] + · simp only [B_r, Set.toFinite_toFinset, ne_eq, Nat.cast_eq_zero] apply Finset.card_ne_zero_of_mem (a := 1) simp [R_1] - . apply mul_pos - . simp only [B_r, Set.toFinite_toFinset] + · apply mul_pos + · simp only [B_r, Set.toFinite_toFinset] norm_cast rw [Finset.card_pos] use 1 simp [R_1] - . + · simp [-Set.toFinset_card] use 1 simp [B_r, R_1] - . + · rw [mul_div_assoc] - norm_num grw [vol_frac_le] - . + · conv => lhs @@ -729,7 +767,7 @@ lemma lemma_3_25_poincare (data: GoodScalesData b) (j: (X_j data)) (f: G → ℝ simp [deriv_sq] group simp - . simp [deriv_sq] + · simp [deriv_sq] positivity -- Estimating functions relative to cover diff --git a/Gromov/PolynomialGrowth.lean b/Gromov/PolynomialGrowth.lean new file mode 100644 index 0000000..43f2bfe --- /dev/null +++ b/Gromov/PolynomialGrowth.lean @@ -0,0 +1,37 @@ +module + +public import Mathlib + +/-! # Polynomial growth of Cayley balls + +Cayley balls consist of products of at most a given number of generators or +inverse generators. Their cardinalities define the growth function. +-/ + +public section +namespace FormalConjecturesCheck +variable {G : Type*} [Group G] + +/-! The growth conventions follow the `formal-conjectures` library. -/ + +/-- The `CayleyBall` is the ball of radius `n` in the Cayley graph of a group `G` with generating +set `S`. -/ +@[expose] +def CayleyBall (S : Set G) (n : ℕ) : Set G := + {g : G | ∃ (l : List G), l.length ≤ n ∧ (∀ s ∈ l, s ∈ S ∨ s⁻¹ ∈ S) ∧ l.prod = g} + +/-- The `GrowthFunction` of a group `G` with respect to a set `S` counts the number of group +elements that can be reached by words of length at most `n` in `S`. -/ +@[expose] +noncomputable def GrowthFunction (S : Set G) (n : ℕ) : ℕ := + (CayleyBall S n).ncard + +/-- A group has polynomial growth if there exists a finite generating set whose growth function is +bounded above by a polynomial. -/ +@[expose] +def HasPolynomialGrowth (G : Type*) [Group G] : Prop := + ∃ (S : Set G), Set.Finite S ∧ Subgroup.closure S = ⊤ ∧ + ∃ (C : ℝ) (d : ℕ), C > 0 ∧ + ∀ n > 0, (GrowthFunction S n : ℝ) ≤ C * (n : ℝ) ^ d + +end FormalConjecturesCheck diff --git a/Gromov/QuadraticForm.lean b/Gromov/QuadraticForm.lean index eda1274..8ebe2ff 100644 --- a/Gromov/QuadraticForm.lean +++ b/Gromov/QuadraticForm.lean @@ -12,11 +12,6 @@ the determinant bound `det_bound` for a fixed finite-dimensional subspace `V`. public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false open scoped Finset open scoped Pointwise @@ -120,14 +115,14 @@ lemma Q_R_lin_hermetian {ι : Type*} [Fintype ι] [DecidableEq ι] {V: Submodule lemma Q_R_lin_sub_pos_semi_def (V : Submodule ℝ LipschitzH) (R_1 R_2: ℝ) (hr: R_1 ≤ R_2): ((Q_R_lin V R_2) - Q_R_lin V R_1).IsPosSemidef := by rw [LinearMap.isPosSemidef_def] refine ⟨?_, ?_⟩ - . + · -- `Q_R_lin` lands in a nested linear-map type `V →ₗ⋆[ℝ] V →ₗ[ℝ] ℝ`; giving -- `sub_eq_add_neg` its arguments explicitly avoids a metavariable whose `Sub` -- instance would need a deeper `synthPending` than the default depth allows. rw [sub_eq_add_neg (Q_R_lin V R_2) (Q_R_lin V R_1)] apply LinearMap.IsSymm.add - . apply Q_R_lin_symm - . + · apply Q_R_lin_symm + · -- TODO - add smul/neg lemmas so that we don't need to inline the proof here exact { eq := by @@ -135,15 +130,15 @@ lemma Q_R_lin_sub_pos_semi_def (V : Submodule ℝ LipschitzH) (R_1 R_2: ℝ) (hr simp [Q_R_lin, Q_R] simp_rw [mul_comm] } - . + · rw [LinearMap.isNonneg_def] intro x simp [Q_R_lin, Q_R] apply Finset.sum_le_sum_of_subset_of_nonneg - . + · simp [Metric.closedBall] grind - . intro a ha a_not + · intro a ha a_not rw [← pow_two] positivity @@ -185,7 +180,7 @@ lemma v_r_all_nonzero (V: Submodule ℝ LipschitzH) [FiniteDimensional ℝ V]: ext a simp only [Submodule.mem_iInf, Submodule.zero_eq_bot, Submodule.mem_bot] refine ⟨?_, ?_⟩ - . + · intro hi ext g specialize hi (WordNorm g) @@ -193,11 +188,11 @@ lemma v_r_all_nonzero (V: Submodule ℝ LipschitzH) [FiniteDimensional ℝ V]: specialize hi g simp [dist, WordDist_one] at hi simp [hi] - . intro hi + · intro hi simp [hi] rw [← Antitone.iInf_nat_add (k := n)] at inter_zero - . + · conv at inter_zero => lhs arg 1 @@ -221,13 +216,12 @@ lemma v_r_all_nonzero (V: Submodule ℝ LipschitzH) [FiniteDimensional ℝ V]: obtain ⟨x, h_x_1, h_x_2⟩ := inter_zero use x refine ⟨?_, ?_⟩ - . right + · right exact h_x_1 - . exact h_x_2 - . intro a b hab + · exact h_x_2 + · intro a b hab simp [zero_ball] - intro u hu hg - intro g g_dist + intro u hu hg g g_dist specialize hg g grw [hab] at g_dist specialize hg g_dist @@ -242,23 +236,23 @@ lemma R'_pos (V: Submodule ℝ LipschitzH) [FiniteDimensional ℝ V]: 1 < R'_ V lemma Q_R_pos_on_R' {V: Submodule ℝ LipschitzH} (v: V) (hv: v ≠ 0) [FiniteDimensional ℝ V] (R: ℝ) (hR: (R'_ V) ≤ R): 0 < Q_R R v v := by simp [Q_R] rw [Finset.sum_pos_iff_of_nonneg] - . + · by_contra! simp_rw [← pow_two] at this simp only [sq_nonpos_iff] at this have foo := (v_r_all_nonzero V).choose_spec.2 (v) (by apply Submodule.coe_mem) ?_ - . + · obtain ⟨g, g_mem, x_g_nonzero⟩ := foo specialize this g ?_ - . + · simp unfold R'_ at hR grw [hR] at g_mem simpa using g_mem - . + · simp at x_g_nonzero contradiction - . + · conv => rhs equals (0: V) => @@ -267,7 +261,7 @@ lemma Q_R_pos_on_R' {V: Submodule ℝ LipschitzH} (v: V) (hv: v ≠ 0) [FiniteDi rw [ne_eq, ← Subtype.ext_iff] rw [← ne_eq] exact hv - . intro y hy + · intro y hy rw [← pow_two] positivity @@ -282,13 +276,11 @@ lemma Q_R_matrix_pos_def {ι : Type*} [Fintype ι] [DecidableEq ι] {V: Submodul equals (star x) => simp rw [star_dotProduct_toMatrix₂_mulVec] apply Q_R_pos_on_R' - . rw [LinearEquiv.map_ne_zero_iff] + · rw [LinearEquiv.map_ne_zero_iff] exact hx - . exact hR + · exact hR -#print sorries Q_R_matrix_pos_def --- TODO - generalize and upstream section V_variable @@ -297,21 +289,20 @@ variable {V: Submodule ℝ LipschitzH} [V_finite: FiniteDimensional ℝ V] [Nont @[expose] instance nonempty_basis: Nonempty ↑(Module.Basis.ofVectorSpaceIndex ℝ ↥V) := Module.Basis.index_nonempty (Module.Basis.ofVectorSpace _ _) --- TODO - generalize and upstream omit hGS in lemma euclidean_of_lp_le {ι : Type*} [Fintype ι] (x: EuclideanSpace ℝ ι) (i: ι): |x.ofLp i| ≤ ‖x‖ := by rw [EuclideanSpace.norm_eq] rw [Real.le_sqrt] - . + · simp apply Finset.single_le_sum (a := i) - . intro i _ + · intro i _ positivity - . simp - . simp - . positivity + · simp + · simp + · positivity /-- The Lipschitz constant `‖(b i).val‖` of the `i`-th vector of the basis `b` of `V`. -/ @[expose] @@ -382,13 +373,13 @@ lemma det_bound {ι : Type*} [Fintype ι] [DecidableEq ι] [Nonempty ι] (b : Mo + (Module.finrank ℝ ↥V) * max_origin) * (1 + R)) ^ 2 from by simp only [max_lipschitz, max_origin, det_bound_const]; ring] rw [(Q_R_lin_hermetian b R).det_eq_prod_eigenvalues] - grw [Finset.prod_le_prod (g := fun _ => m)] - . + grw [Finset.prod_le_prod₀ (g := fun _ => m)] + · simp rw [← Module.finrank_eq_card_basis b] rw [← Real.rpow_natCast] rw [← Real.rpow_mul] - . + · have finrank_pos := Module.finrank_pos (R := ℝ) (M := V) field_simp [finrank_pos] simp @@ -412,18 +403,17 @@ lemma det_bound {ι : Type*} [Fintype ι] [DecidableEq ι] [Nonempty ι] (b : Mo ext a simp rw [foo] - simp only [Q_R_lin, Q_R, LipschitzH_apply, map_sum, - map_smul, LinearMap.coe_mk, AddHom.coe_mk, LinearMap.coe_sum, LinearMap.coe_smul, - Finset.sum_apply, Pi.smul_apply, smul_eq_mul, ge_iff_le] + simp only [Q_R_lin, Q_R, LipschitzH_apply, LinearMap.coe_mk, AddHom.coe_mk, + ge_iff_le] simp_rw [← pow_two] grw [Finset.sum_le_card_nsmul (n := (((((Module.finrank ℝ ↥V)) * max_lipschitz + ((Module.finrank ℝ ↥V) * max_origin)) * (1 + R)) ^ 2))] - . + · rw [← card_closed_ball_eq] simp rw [mul_comm] field_simp simp - . + · intro x hx specialize hB x simp @@ -431,7 +421,7 @@ lemma det_bound {ι : Type*} [Fintype ι] [DecidableEq ι] [Nonempty ι] (b : Mo rw [← Real.sqrt_sq_eq_abs] at hB rw [Real.sqrt_le_iff] at hB have foo := hB.2 - . + · simp [dist, WordDist_one] at hx grw [hx] at foo conv => @@ -451,10 +441,10 @@ lemma det_bound {ι : Type*} [Fintype ι] [DecidableEq ι] [Nonempty ι] (b : Mo grw [foo] rw [mul_pow, mul_pow] rw [mul_le_mul_iff_left₀] - . + · rw [pow_le_pow_iff_left₀] - . apply add_le_add - . + · apply add_le_add + · simp [max_lipschitz] have foo := (m_vec_V).val.lipschitz.choose_spec conv at foo => @@ -469,53 +459,52 @@ lemma det_bound {ι : Type*} [Fintype ι] [DecidableEq ι] [Nonempty ι] (b : Mo --grw [norm_sum_l] grw [norm_sum_le] grw [Finset.sum_le_card_nsmul (n := ↑max_lipschitz)] - . + · simp rw [← Module.finrank_eq_card_basis b] - . + · intro i _ simp [norm_smul] grw [euclidean_of_lp_le] simp [m_vec] apply h_max_lipschitz - . + · simp [m_vec_V, m_vec] rw [← LipschitzH_apply] rw [LipschitzH.finset_sum_apply] grw [Finset.abs_sum_le_sum_abs] grw [Finset.sum_le_card_nsmul (n := max_origin)] - . simp + · simp rw [← Module.finrank_eq_card_basis b] - . + · intro i hi simp grw [euclidean_of_lp_le] simp apply h_max_origin - . positivity - . exact add_nonneg (mul_nonneg (by positivity) (max_lipschitz_nonneg b)) + · positivity + · exact add_nonneg (mul_nonneg (by positivity) (max_lipschitz_nonneg b)) (mul_nonneg (by positivity) (max_origin_nonneg b)) - . simp - . positivity + · simp + · positivity - . unfold m + · unfold m apply Matrix.PosSemidef.eigenvalues_nonneg apply (Q_R_matrix_pos_def b R hR).posSemidef - . + · apply Finset.prod_nonneg intro i _ apply Matrix.PosSemidef.eigenvalues_nonneg apply (Q_R_matrix_pos_def b R hR).posSemidef - . + · intro i _ apply Matrix.PosSemidef.eigenvalues_nonneg apply (Q_R_matrix_pos_def b R hR).posSemidef - . intro i _ + · intro i _ unfold m have foo := (Finite.exists_max (Q_R_lin_hermetian b R).eigenvalues).choose_spec apply foo i -#print axioms det_bound end V_variable end GeneratesNS diff --git a/Gromov/Representation.lean b/Gromov/Representation.lean index d856c0c..f91e742 100644 --- a/Gromov/Representation.lean +++ b/Gromov/Representation.lean @@ -23,12 +23,6 @@ fact that it preserves the quotient norm. public section -set_option linter.style.longLine false -set_option linter.style.cdot false --- TODO - vscode stops reporting underlines if there are too many total underlines / gutter messages --- I've disabled some failing lints for now so that error underlines still sho up -set_option linter.style.commandStart false - open Subgroup open scoped Finset open scoped Pointwise @@ -42,8 +36,6 @@ include hGS open scoped RealInnerProductSpace --- `LipschitzH_seminorm` and `LipschitzH_normed` are public instances in --- `Gromov.LipschitzNorm`, so they are already available here. -- The lift of LipschitzSemiNorm to W, using a proof that LipschitzSemiNorm doesn't depend on the choice representative -- (adding a constant to a Lipschitz function doesn't change its Lipschitz constant) @@ -63,13 +55,13 @@ lemma constf_eq_null: (ConstF : Set (LipschitzH)) = nullAddSubgroup (LipschitzH) ext f simp refine ⟨?_, ?_⟩ - . + · intro hf obtain ⟨z, hz⟩ := hf rw [← hz] simp [norm] apply lipschitz_norm_const - . + · intro hf simp [norm, LipschitzSemiNorm] at hf have lipschitz_zero := lipschitz_attains_norm f (f.lipschitz) @@ -88,14 +80,6 @@ instance const_isClosed: IsClosed (ConstF : Set (LipschitzH)) := by exact isClosed_nullAddSubgroup -#synth NormedSpace ℝ (W ) -#synth NormedAddCommGroup (W ) - -#synth TopologicalSpace (W) - - -set_option synthInstance.maxHeartbeats 400000 -set_option maxHeartbeats 9000000 -- The space 'GL(W)' of invertible continuous linear functions from W to W abbrev GL_W := (W →L[ℝ] W)ˣ @@ -103,26 +87,10 @@ abbrev GL_W := (W →L[ℝ] W)ˣ -- The space 'GL(W)' of invertible continuous linear functions from W to W -#synth NormedRing (((W →L[ℝ] W))) - -#synth NormedAddCommGroup (((W →L[ℝ] W))) - - -#synth FiniteDimensional ℝ (((W →L[ℝ] W))) - --- Homeomorph.isCompact_preimage - @[expose] instance proper_linear_w: ProperSpace (((W →L[ℝ] W))) := FiniteDimensional.proper_rclike ℝ (((W →L[ℝ] W))) -#synth FiniteDimensional ℝ (LipschitzH) -#synth TopologicalSpace (LipschitzH) -#synth BorelSpace (((W →L[ℝ] W))) - -#synth ProperSpace (((W →L[ℝ] W))) - - @[expose] def GRep: Representation ℝ G (LipschitzH) := { toFun := fun g => { @@ -151,8 +119,7 @@ def GRep: Representation ℝ G (LipschitzH) := { -- We start with a map from G into the space of (not necessarily invertible) linear maps from W to W @[expose] def GRepW_non_invertible: Representation ℝ G (W) := Representation.quotient (GRep) ConstF (by - intro g - intro f hf + intro g f hf simp simp [ConstF] simp [ConstF] at hf @@ -186,9 +153,9 @@ lemma GRep_preserves_norm (g: G) (f: LipschitzH): ‖(GRep g) f‖ = ‖f‖ := have comp := LipschitzWith.comp (f := f.toFun) (g := fun y => (y * g)) (Kf := (LipschitzSemiNorm ⇑f)) (Kg := 1) ?_ ?_ rotate_left 1 - . apply lipschitz_attains_norm + · apply lipschitz_attains_norm exact f.lipschitz - . + · simp [LipschitzWith] have norm_mem: (LipschitzSemiNorm f) ∈ { k: NNReal | LipschitzWith k (f.toFun ∘ (fun y => (y * g))) } := by @@ -198,27 +165,27 @@ lemma GRep_preserves_norm (g: G) (f: LipschitzH): ‖(GRep g) f‖ = ‖f‖ := apply le_antisymm - . + · apply csInf_le (by simp [BddBelow] apply Set.nonempty_of_mem (x := 0) rw [mem_lowerBounds] simp ) norm_mem - . + · apply le_csInf - . + · apply Set.nonempty_of_mem (x := (LipschitzSemiNorm ⇑f)) norm_mem - . intro b hb + · intro b hb simp at hb simp [LipschitzSemiNorm] apply csInf_le - . + · simp [BddBelow] apply Set.nonempty_of_mem (x := 0) rw [mem_lowerBounds] simp - . simp + · simp simp [LipschitzWith] at hb simp [LipschitzWith] intro x y @@ -229,7 +196,9 @@ lemma GRep_preserves_norm (g: G) (f: LipschitzH): ‖(GRep g) f‖ = ‖f‖ := -- Takes in an invertible linear map from W to W, and produces a *continuous* linear map from W to W @[expose] -noncomputable def GRepW: (W →ₗ[ℝ] W)ˣ →* (W →L[ℝ] W)ˣ := { +noncomputable def linearUnitsToContinuous + (E : Type*) [NormedAddCommGroup E] [NormedSpace ℝ E] [FiniteDimensional ℝ E] : + (E →ₗ[ℝ] E)ˣ →* (E →L[ℝ] E)ˣ := { toFun := fun f => { val := LinearMap.toContinuousLinearMap f.val inv := LinearMap.toContinuousLinearMap f.inv @@ -257,8 +226,9 @@ noncomputable def GRepW: (W →ₗ[ℝ] W)ˣ →* (W →L[ℝ] W)ˣ := { simp } - -#synth Group (GL_W) +@[expose] +noncomputable def GRepW : (W →ₗ[ℝ] W)ˣ →* (W →L[ℝ] W)ˣ := + linearUnitsToContinuous W lemma quotient_norm_eq_norm (f: LipschitzH): ‖(Submodule.Quotient.mk f : W)‖ = ‖f‖ := by conv => @@ -289,15 +259,12 @@ lemma quotient_norm_eq_norm (f: LipschitzH): ‖(Submodule.Quotient.mk f : W)‖ rw [hinf] simp -#synth NormedRing (W →L[ℝ] W) -#synth TopologicalSpace (W →L[ℝ] W)ˣ - lemma GLW_preseves_norm (g: G) (w: W): ‖(GRepW (GRepW_base g)).val w‖ = ‖w‖ := by have exists_v: ∃ v, Submodule.Quotient.mk v = w := by apply Quotient.exists_rep obtain ⟨v, hv⟩ := exists_v - simp [GRepW, GRepW_base, GRepW_non_invertible] + simp [GRepW, linearUnitsToContinuous, GRepW_base, GRepW_non_invertible] nth_rw 1 [← hv] rw [Representation.asGroupHom_apply] simp only [Representation.quotient_apply, Submodule.mapQ_apply] @@ -309,31 +276,30 @@ lemma GLW_preseves_norm (g: G) (w: W): ‖(GRepW (GRepW_base g)).val w‖ = ‖w lemma GRepW_norm_le (g: G): ‖(GRepW (GRepW_base g)).val‖ ≤ 1 := by rw [ContinuousLinearMap.opNorm_le_iff] - . simp [GLW_preseves_norm] - . simp + · simp [GLW_preseves_norm] + · simp -set_option synthInstance.maxHeartbeats 500000 @[expose] noncomputable def rho_g := (GRepW_base).range -@[expose] -def isembedding_units_val := Units.isEmbedding_val_mk' (M := (W →L[ℝ] W)) (f := ContinuousLinearMap.inverse) (by +theorem isembedding_units_val : + Topology.IsEmbedding (Units.val : (W →L[ℝ] W)ˣ → (W →L[ℝ] W)) := Units.isEmbedding_val_mk' (M := (W →L[ℝ] W)) (f := ContinuousLinearMap.inverse) (by intro x hx have foo := ContDiffAt.continuousAt (ContinuousLinearMap.IsInvertible.contDiffAt_map_inverse (e := x) (n := 0) (by simp at hx obtain ⟨u, hu⟩ := hx apply ContinuousLinearMap.IsInvertible.of_inverse (g := u.inv) - . + · simp have mul_inv := u.val_inv dsimp [HMul.hMul, Mul.mul] at mul_inv rw [hu] at mul_inv exact mul_inv - . simp + · simp have inv_val := u.inv_val dsimp [HMul.hMul, Mul.mul] at inv_val rw [hu] at inv_val @@ -341,19 +307,15 @@ def isembedding_units_val := Units.isEmbedding_val_mk' (M := (W →L[ℝ] W)) (f )) apply ContinuousAt.continuousWithinAt exact foo - -- ContinuousLinearMap.IsInvertible.contDiffAt_map_inverse ) (by intro u have mul_inv := u.val_inv dsimp [HMul.hMul, Mul.mul] at mul_inv apply ContinuousLinearMap.inverse_eq - . exact u.val_inv - . exact u.inv_val + · exact u.val_inv + · exact u.inv_val ) -#synth NormedSpace ℝ (W →L[ℝ] W) -#synth MetricSpace (W →L[ℝ] W) - -- All norms are equivalent on finite-dimensional spaces: -- https://leanprover-community.github.io/mathlib4_docs/Mathlib/Analysis/Normed/Module/FiniteDimension.html @@ -363,22 +325,9 @@ def isembedding_units_val := Units.isEmbedding_val_mk' (M := (W →L[ℝ] W)) (f -- ρ(G) contains an abelian subgroup of finite index ---borelize (W →L[ℝ] W)ˣ - - --- (dropped a `#synth ContinuousMul (W →L[ℝ] W)` diagnostic here: it only resolves at a --- raised `maxSynthPendingDepth`. The instance itself *is* needed -- see --- `rho_g_contains_abelian`, which raises the depth for exactly this reason -- but a bare --- `#synth` is not worth carrying a build-wide option for.) - - -#synth NormedAddCommGroup (W) -#synth FiniteDimensional ℝ (W) -#synth TopologicalSpace (W) - @[expose] def FreshTopology (V: Type*) := V @@ -388,20 +337,9 @@ instance (V: Type*) [AddCommGroup V] [base_module: Module ℝ V]: Module ℝ (Fr @[expose] instance (V: Type*) [AddCommGroup V] [Module ℝ V] [base_finite: FiniteDimensional ℝ V]: FiniteDimensional ℝ (FreshTopology V) := base_finite - -#synth CStarAlgebra ((ℂ →L[ℂ] ℂ)) - -#synth AddCommMonoid (W) - @[expose] instance T2_W: T2Space (W) := TopologicalSpace.t2Space_of_metrizableSpace -#synth T2Space (W) - - -#synth TopologicalSpace (W →L[ℝ] W) -#synth FiniteDimensional ℝ (W →L[ℝ] W) - @[expose] noncomputable def G_SPolyData {d: ℕ} (h_poly: HasPolynomialGrowthD hGS.S d): SPolyData (T := G) ⊤ := { S := Subgroup.topEquiv.symm.toMonoidHom '' hGS.S @@ -438,10 +376,10 @@ noncomputable def G_SPolyData {d: ℕ} (h_poly: HasPolynomialGrowthD hGS.S d): S rw [Set.Finite.toFinset_image] rw [← Finset.image_pow] grw [Finset.card_image_le] - . + · specialize foo r hr simpa using foo - . simp + · simp } diff --git a/Gromov/RhoAbelian.lean b/Gromov/RhoAbelian.lean index 480ffb6..24e4bba 100644 --- a/Gromov/RhoAbelian.lean +++ b/Gromov/RhoAbelian.lean @@ -11,9 +11,6 @@ public import Gromov.Theorem38 public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false open Subgroup open scoped Finset @@ -28,23 +25,157 @@ include hGS open scoped RealInnerProductSpace -set_option synthInstance.maxHeartbeats 500000 -set_option maxHeartbeats 9000000 + +private lemma rho_continuous_range_compact + [IsTopologicalGroup (W →L[ℝ] W)ˣ] : + CompactSpace ((GRepW.comp GRepW_base).range.topologicalClosure) := by + let my_new_range := (GRepW.comp GRepW_base).range + have continuous_mul : ContinuousMul (W →L[ℝ] W) := + (NonUnitalSeminormedRing.toIsTopologicalRing (α := W →L[ℝ] W)).toContinuousMul + have is_topological : IsTopologicalGroup (W →L[ℝ] W)ˣ := by infer_instance + let plain_units_metric : MetricSpace (W →L[ℝ] W)ˣ := + isembedding_units_val.comapMetricSpace Units.val + change CompactSpace my_new_range.topologicalClosure + + refine { isCompact_univ := ?_ } + rw [Subtype.isCompact_iff] + rw [Topology.IsEmbedding.isCompact_iff (f := Units.val) ?_] + · rw [Metric.isCompact_iff_isClosed_bounded (α := (W) →L[ℝ] (W))] + refine ⟨?_, ?_⟩ + · apply IsSeqClosed.isClosed + by_contra! + simp [IsSeqClosed] at this + obtain ⟨seq, seq_in, ⟨lim_seq, seq_tendsto_lim_seq, lim_seq_not_mem⟩⟩ := this + + by_cases lim_seq_invertible: IsUnit lim_seq.toLinearMap + · + -- If the limit (in the space of linear maps) is invertible, then the limit will also exist in the space + -- of units, which will then imply that the limit exists in the space of linear maps. + obtain ⟨u, hu⟩ := lim_seq_invertible + have closure_closed := Subgroup.isClosed_topologicalClosure my_new_range + apply IsClosed.isSeqClosed at closure_closed + dsimp [IsSeqClosed] at closure_closed + + have seq_units: ∀ n: ℕ, IsUnit (seq n) := by + intro n + obtain ⟨x, x_mem, seq_eq_x⟩ := (seq_in n) + rw [← seq_eq_x] + apply Units.isUnit + + have lim_units := closure_closed (x := fun n => (seq_units n).unit) (p := GRepW u) ?_ ?_ + · + specialize lim_seq_not_mem (GRepW u) lim_units + conv at lim_seq_not_mem => + arg 1 + lhs + equals u.val.toContinuousLinearMap => + rfl + rw [hu] at lim_seq_not_mem + conv at lim_seq_not_mem => + arg 1 + lhs + equals lim_seq => + rfl + simp at lim_seq_not_mem + · intro n + have seq_n := seq_in n + obtain ⟨x, x_mem, seq_eq_x⟩ := seq_n + simp_rw [← seq_eq_x] + simpa using x_mem + · + rw [Topology.IsEmbedding.tendsto_nhds_iff (g := Units.val)] + · + conv => + arg 1 + equals seq => + rfl + + have to_clm_u: GRepW u = u.val.toContinuousLinearMap := by + rfl + + have u_val_eq_lim: u.val.toContinuousLinearMap = lim_seq := by + rw [hu] + rfl + + rw [to_clm_u, u_val_eq_lim] + exact seq_tendsto_lim_seq + · + exact isembedding_units_val + + + -- If the limit (in the space of linear maps) is not invertible, then it has a non-trivial kernel. + rw [LinearMap.isUnit_iff_ker_eq_bot] at lim_seq_invertible + apply Submodule.exists_mem_ne_zero_of_ne_bot at lim_seq_invertible + obtain ⟨v, v_in_ker, v_ne_zero⟩ := lim_seq_invertible + simp at v_in_ker + + + have eval_at := Filter.Tendsto.eval_const seq_tendsto_lim_seq v + have norm_tendsto := Continuous.tendsto (f := fun (x: W) => ‖x‖) (by fun_prop) (lim_seq v) + have norm_seq_lim := Filter.Tendsto.comp norm_tendsto eval_at + rw [v_in_ker] at norm_seq_lim + rw [norm_zero] at norm_seq_lim + conv at norm_seq_lim => + arg 1 + -- Use the fact that the action preserves the euclidian norm (maybe just up to a constant), + -- so the sequence is actually constant + equals fun x => ‖v‖ => + funext n + simp + have seq_mem := seq_in n + obtain ⟨x, x_mem, seq_eq_x⟩ := seq_mem + rw [← seq_eq_x] + apply ContinuousWithinAt.eq_const_of_mem_closure (f := fun (x: ((W) →L[ℝ] (W))ˣ) => ‖x.val v‖) (c := ‖v‖) (x := x) (s := my_new_range) + · apply Continuous.continuousWithinAt + fun_prop + · exact x_mem + · intro y hy + simp [my_new_range] at hy + obtain ⟨g, rep_g_eq_y⟩ := hy + rw [← rep_g_eq_y] + apply GLW_preseves_norm + have r_t2: T2Space ℝ := TopologicalSpace.t2Space_of_metrizableSpace + + have tendsto_norm_v := tendsto_const_nhds (α := ℕ) (f := Filter.atTop) (x := ‖v‖) + have norm_v_zero := tendsto_nhds_unique tendsto_norm_v norm_seq_lim + simp at norm_v_zero + contradiction + · + simp + apply LipschitzWith.isBounded_image (f := Units.val) (K := 1) + · rw [lipschitzWith_iff_dist_le_mul] + intro a b + simp + rfl + · + apply Bornology.IsBounded.closure + rw [Metric.isBounded_iff_subset_ball 1] + use 3 + intro a ha + simp [my_new_range] at ha + obtain ⟨g, rep_g_eq_a⟩ := ha + simp + conv => + lhs + equals dist (a.val) (ContinuousLinearMap.id _ _) => + rfl + grw [dist_le_norm_add_norm (a.val) (ContinuousLinearMap.id ℝ W)] + grw [ContinuousLinearMap.norm_id_le] + rw [← rep_g_eq_a] + grw [GRepW_norm_le] + norm_num + -- Bornology.isBounded_image_subtype_val + · exact isembedding_units_val open scoped RealInnerProductSpace in attribute [-simp] Subgroup.map_toSubmonoid in -set_option maxHeartbeats 2000000 in -set_option synthInstance.maxHeartbeats 600000 in ---set_option trace.Meta.synthInstance true in lemma rho_g_contains_abelian {d: ℕ} (hd: HasPolynomialGrowthD S d) : ∃ M: Subgroup ((rho_g)), IsMulCommutative M ∧ M.FiniteIndex := by classical let my_map := Subgroup.subtype (rho_g) have W_equiv: (W) ≃ₗ[ℝ] EuclideanSpace ℝ (Fin <| Module.finrank ℝ W) := LinearEquiv.ofFinrankEq _ _ finrank_euclideanSpace_fin.symm - unfold GL_W at my_map - -- TODO - is there a simpler way to get an arbitrary inner product space? let inner_prod_core: InnerProductSpace.Core ℝ (FreshTopology (W)) := { inner := fun v w => ⟪W_equiv v, W_equiv w⟫, conj_inner_symm := by intro x y; simp [real_inner_comm], @@ -75,118 +206,6 @@ lemma rho_g_contains_abelian {d: ℕ} (hd: HasPolynomialGrowthD S d) : ∃ M: Su have fresh_t2: T2Space (FreshTopology (W)) := TopologicalSpace.t2Space_of_metrizableSpace - let plain_linear_to_clm: (((W)) →ₗ[ℝ] ((W)))ˣ →* (((W)) →L[ℝ] ((W)))ˣ := { - toFun := fun f => { - val := LinearMap.toContinuousLinearMap f.val - inv := LinearMap.toContinuousLinearMap f.inv - val_inv := by - have old_inv := f.val_inv - ext a - apply_fun (fun f => f a) at old_inv - simp only [Units.inv_eq_val_inv, Module.End.one_apply] at old_inv - apply old_inv - inv_val := by - have old_inv := f.inv_val - ext a - apply_fun (fun f => f a) at old_inv - simp only [Units.inv_eq_val_inv, Module.End.one_apply] at old_inv - apply old_inv - } - -- TODO - why is a normal `simp` so slow here? - map_one' := by - ext a - simp only [] - rfl - map_mul' := by - intro f g - ext a - simp only [] - rfl - } - - let linear_to_clm: ((FreshTopology (W)) →ₗ[ℝ] (FreshTopology (W)))ˣ →* ((FreshTopology (W)) →L[ℝ] (FreshTopology (W)))ˣ := { - toFun := fun f => { - val := LinearMap.toContinuousLinearMap f.val - inv := LinearMap.toContinuousLinearMap f.inv - val_inv := by - have old_inv := f.val_inv - ext a - apply_fun (fun f => f a) at old_inv - simp only [Units.inv_eq_val_inv, Module.End.one_apply] at old_inv - apply old_inv - inv_val := by - have old_inv := f.inv_val - ext a - apply_fun (fun f => f a) at old_inv - simp only [Units.inv_eq_val_inv, Module.End.one_apply] at old_inv - apply old_inv - } - -- TODO - why is a normal `simp` so slow here? - map_one' := by - ext a - simp only [] - rfl - map_mul' := by - intro f g - ext a - simp only [] - rfl - } - - - have plain_linear_to_clm_preserves_norm (g: G) (w: (W)): ‖(plain_linear_to_clm (GRepW_base g)).val w‖ = ‖w‖ := by - simp [plain_linear_to_clm] - have exists_v: ∃ v, Submodule.Quotient.mk v = w := by - apply Quotient.exists_rep - obtain ⟨v, hv⟩ := exists_v - simp [GRepW, GRepW_base, GRepW_non_invertible] - nth_rw 1 [← hv] - rw [Representation.asGroupHom_apply] - simp only [Representation.quotient_apply, Submodule.mapQ_apply] - - rw [quotient_norm_eq_norm] - rw [GRep_preserves_norm] - rw [← hv] - rw [quotient_norm_eq_norm] - - - let my_range := (linear_to_clm.comp GRepW_base).range - - have fresh_complete: CompleteSpace (FreshTopology (W)) := by apply complete_of_proper (α := FreshTopology (W)) - - - - -- TODO - generalize to LinearMap/ContinuousLinearMap - have units_val_embedding: Topology.IsEmbedding (Units.val (α := ((FreshTopology (W)) →L[ℝ] (FreshTopology (W))))) := by - apply Units.isEmbedding_val_mk' (f := fun g => g.inverse) - . intro a ha - apply (ContinuousLinearMap.IsInvertible.contDiffAt_map_inverse (n := 1) ?_).continuousAt.continuousWithinAt - simp at ha - obtain ⟨b, hb⟩ := ha - use ContinuousLinearEquiv.ofUnit b - rw [← hb] - rfl - . intro u - apply ContinuousLinearMap.inverse_eq - . - have u_val_inv := u.val_inv - rw [ContinuousLinearMap.mul_def] at u_val_inv - -- TODO - avoid the unfold somehow - unfold Inv.inv - unfold Units.instInv - simp only [] - rw [u_val_inv] - rfl - . - unfold Inv.inv - unfold Units.instInv - simp only [] - have u_inv_val := u.inv_val - rw [ContinuousLinearMap.mul_def] at u_inv_val - rw [u_inv_val] - rfl - - let my_new_range := ((GRepW).comp GRepW_base).range unfold rho_g @@ -200,15 +219,6 @@ lemma rho_g_contains_abelian {d: ℕ} (hd: HasPolynomialGrowthD S d) : ∃ M: Su have is_topological: IsTopologicalGroup ((W) →L[ℝ] (W))ˣ := by infer_instance - let plain_units_metric: MetricSpace (((W)) →L[ℝ] ((W)))ˣ := by - apply Topology.IsEmbedding.comapMetricSpace (f := Units.val) - exact isembedding_units_val - - let units_metric: MetricSpace ((FreshTopology (W)) →L[ℝ] (FreshTopology (W)))ˣ := by - apply Topology.IsEmbedding.comapMetricSpace (f := Units.val) - apply units_val_embedding - - have fresh_equiv: W ≃L[ℝ] FreshTopology (W) := ContinuousLinearEquiv.ofFinrankEq (rfl) let to_fresh (f: (W) ≃ₗ[ℝ] (W)): (FreshTopology (W)) ≃ₗ[ℝ] (FreshTopology (W)) := f @@ -287,147 +297,16 @@ lemma rho_g_contains_abelian {d: ℕ} (hd: HasPolynomialGrowthD S d) : ∃ M: Su let mapped_group := Subgroup.map new_map_hom.toMonoidHom my_new_range.topologicalClosure - have my_new_range_compact: CompactSpace my_new_range.topologicalClosure := by - refine { isCompact_univ := ?_ } - rw [Subtype.isCompact_iff] - rw [Topology.IsEmbedding.isCompact_iff (f := Units.val) ?_] - . rw [Metric.isCompact_iff_isClosed_bounded (α := (W) →L[ℝ] (W))] - refine ⟨?_, ?_⟩ - . apply IsSeqClosed.isClosed - by_contra! - simp [IsSeqClosed] at this - obtain ⟨seq, seq_in, ⟨lim_seq, seq_tendsto_lim_seq, lim_seq_not_mem⟩⟩ := this - - by_cases lim_seq_invertible: IsUnit lim_seq.toLinearMap - . - -- If the limit (in the space of linear maps) is invertible, then the limit will also exist in the space - -- of units, which will then imply that the limit exists in the space of linear maps. - -- TODO - this probably can be a direct proof, rather than by contradiction - obtain ⟨u, hu⟩ := lim_seq_invertible - have closure_closed := Subgroup.isClosed_topologicalClosure my_new_range - apply IsClosed.isSeqClosed at closure_closed - dsimp [IsSeqClosed] at closure_closed - - have seq_units: ∀ n: ℕ, IsUnit (seq n) := by - intro n - obtain ⟨x, x_mem, seq_eq_x⟩ := (seq_in n) - rw [← seq_eq_x] - apply Units.isUnit - - have lim_units := closure_closed (x := fun n => (seq_units n).unit) (p := plain_linear_to_clm u) ?_ ?_ - . - specialize lim_seq_not_mem (plain_linear_to_clm u) lim_units - conv at lim_seq_not_mem => - arg 1 - lhs - equals u.val.toContinuousLinearMap => - rfl - rw [hu] at lim_seq_not_mem - conv at lim_seq_not_mem => - arg 1 - lhs - equals lim_seq => - rfl - simp at lim_seq_not_mem - . intro n - have seq_n := seq_in n - obtain ⟨x, x_mem, seq_eq_x⟩ := seq_n - simp_rw [← seq_eq_x] - simpa using x_mem - . - rw [Topology.IsEmbedding.tendsto_nhds_iff (g := Units.val)] - . - conv => - arg 1 - equals seq => - rfl - - have to_clm_u: plain_linear_to_clm u = u.val.toContinuousLinearMap := by - rfl - - have u_val_eq_lim: u.val.toContinuousLinearMap = lim_seq := by - rw [hu] - rfl - - rw [to_clm_u, u_val_eq_lim] - exact seq_tendsto_lim_seq - . - exact isembedding_units_val - - - -- If the limit (in the space of linear maps) is not invertible, then it has a non-trivial kernel. - rw [LinearMap.isUnit_iff_ker_eq_bot] at lim_seq_invertible - apply Submodule.exists_mem_ne_zero_of_ne_bot at lim_seq_invertible - obtain ⟨v, v_in_ker, v_ne_zero⟩ := lim_seq_invertible - simp at v_in_ker - - - have eval_at := Filter.Tendsto.eval_const seq_tendsto_lim_seq v - have norm_tendsto := Continuous.tendsto (f := fun (x: W) => ‖x‖) (by fun_prop) (lim_seq v) - have norm_seq_lim := Filter.Tendsto.comp norm_tendsto eval_at - rw [v_in_ker] at norm_seq_lim - rw [norm_zero] at norm_seq_lim - conv at norm_seq_lim => - arg 1 - -- Use the fact that the action preserves the euclidian norm (maybe just up to a constant), - -- so the sequence is actually constant - equals fun x => ‖v‖ => - funext n - simp - have seq_mem := seq_in n - obtain ⟨x, x_mem, seq_eq_x⟩ := seq_mem - rw [← seq_eq_x] - apply ContinuousWithinAt.eq_const_of_mem_closure (f := fun (x: ((W) →L[ℝ] (W))ˣ) => ‖x.val v‖) (c := ‖v‖) (x := x) (s := my_new_range) - . apply Continuous.continuousWithinAt - fun_prop - . exact x_mem - . intro y hy - simp [my_range] at hy - obtain ⟨g, rep_g_eq_y⟩ := hy - rw [← rep_g_eq_y] - apply plain_linear_to_clm_preserves_norm - - -- TODO - why do we need this? - have r_t2: T2Space ℝ := TopologicalSpace.t2Space_of_metrizableSpace - - have tendsto_norm_v := tendsto_const_nhds (α := ℕ) (f := Filter.atTop) (x := ‖v‖) - have norm_v_zero := tendsto_nhds_unique tendsto_norm_v norm_seq_lim - simp at norm_v_zero - contradiction - . - simp - apply LipschitzWith.isBounded_image (f := Units.val) (K := 1) - . rw [lipschitzWith_iff_dist_le_mul] - intro a b - simp - rfl - . - apply Bornology.IsBounded.closure - rw [Metric.isBounded_iff_subset_ball 1] - use 3 - intro a ha - simp [my_new_range] at ha - obtain ⟨g, rep_g_eq_a⟩ := ha - simp - conv => - lhs - equals dist (a.val) (ContinuousLinearMap.id _ _) => - rfl - grw [dist_le_norm_add_norm (a.val) (ContinuousLinearMap.id ℝ W)] - grw [ContinuousLinearMap.norm_id_le] - rw [← rep_g_eq_a] - grw [GRepW_norm_le] - norm_num - -- Bornology.isBounded_image_subtype_val - . exact isembedding_units_val + have my_new_range_compact : CompactSpace my_new_range.topologicalClosure := + rho_continuous_range_compact have continuous_new_map_entry: Continuous new_map_entry := by simp [new_map_entry] rw [Units.continuous_iff] refine ⟨?_, ?_⟩ - . fun_prop - . fun_prop + · fun_prop + · fun_prop have compact_mapped_group: CompactSpace mapped_group := by @@ -456,169 +335,42 @@ lemma rho_g_contains_abelian {d: ℕ} (hd: HasPolynomialGrowthD S d) : ∃ M: Su let data := theorem_3_8_real (H := mapped_group) compact_mapped_group ((Subgroup.map new_map_hom.toMonoidHom my_new_range).subgroupOf mapped_group) ?_ (final_data) obtain ⟨B, B_abelian, B_finite_index⟩ := data - let reverse_hom: ((map new_map_hom.toMonoidHom my_new_range).subgroupOf mapped_group) →* (GRepW_base).range := { - toFun := fun g => ( - ((⟨Units.map (ContinuousLinearMap.toLinearMapRingHom.toMonoidHom) (new_map_hom.symm g.val), by ( - simp - have g_prop := g.property - rw [Subgroup.mem_subgroupOf] at g_prop - rw [Subgroup.mem_map] at g_prop - obtain ⟨x, x_mem, g_eq⟩ := g_prop - simp [my_new_range] at x_mem - obtain ⟨a, ha⟩ := x_mem - use a - ext f - simp - apply_fun (fun h => Units.map (ContinuousLinearMap.toLinearMapRingHom.toMonoidHom) h) at ha - simp [GRepW] at ha - rw [ha] - simp [new_map_hom, new_map_entry_inv] - rw [← g_eq] - simp [new_map_hom, new_map_entry] - )⟩) : GRepW_base.range) - ), - map_one' := by - simp [map_one] - map_mul' := by - intro a b - apply Subtype.ext - show (Units.map _) (new_map_hom.symm ↑↑(a * b)) = - (Units.map _) (new_map_hom.symm ↑↑a) * (Units.map _) (new_map_hom.symm ↑↑b) - rw [← map_mul (Units.map _), ← map_mul new_map_hom.symm] - norm_cast - } - - have reverse_hom_ker_bot: reverse_hom.ker = ⊥ := by + have hinj : Function.Injective GRepW := by + intro x y h + apply Units.ext + apply LinearMap.ext + intro v + have hval := congrArg (fun u : (W →L[ℝ] W)ˣ => u.val v) h + simpa [GRepW, linearUnitsToContinuous] using hval + let e₁ := Subgroup.equivMapOfInjective GRepW_base.range GRepW hinj + let e₂ := MulEquiv.subgroupCongr (MonoidHom.map_range GRepW GRepW_base) + let e₃ := MulEquiv.subgroupMap new_map_hom my_new_range + let e := ((e₁.trans e₂).trans e₃).trans map_sub_equiv + let reverse_hom := e.symm.toMonoidHom + have reverse_hom_ker_bot : reverse_hom.ker = ⊥ := by rw [MonoidHom.ker_eq_bot_iff] - intro a b hab - simp only [reverse_hom, MonoidHom.coe_mk, OneHom.coe_mk, Subtype.mk.injEq] at hab - apply Units.map_injective at hab - . - replace hab := new_map_hom.symm.injective hab - exact Subtype.ext (Subtype.ext hab) - . - intro a b hab - simpa using hab - - have reverse_hom_range_top: reverse_hom.range = ⊤ := by - rw [Subgroup.eq_top_iff'] - intro x - have x_prop := x.property - rw [MonoidHom.mem_range] at x_prop - obtain ⟨g, hg⟩ := x_prop - have mem_range: plain_linear_to_clm ↑x ∈ my_new_range := by - refine MonoidHom.mem_range.mpr ⟨g, ?_⟩ - rw [← hg] - rfl - have mem_closure: plain_linear_to_clm ↑x ∈ my_new_range.topologicalClosure := - Subgroup.le_topologicalClosure my_new_range mem_range - refine MonoidHom.mem_range.mpr - ⟨⟨⟨new_map_entry (plain_linear_to_clm ↑x), - Subgroup.mem_map_of_mem new_map_hom.toMonoidHom mem_closure⟩, ?_⟩, ?_⟩ - . - rw [Subgroup.mem_subgroupOf] - exact Subgroup.mem_map_of_mem new_map_hom.toMonoidHom mem_range - . - have hrt : ∀ y, new_map_hom.symm (new_map_entry y) = y := new_map_hom.left_inv - refine Subtype.ext ?_ - change (Units.map (ContinuousLinearMap.toLinearMapRingHom (R₁ := ℝ) (M₁ := W)).toMonoidHom) - (new_map_hom.symm (new_map_entry (plain_linear_to_clm ↑x))) = x.val - rw [hrt] - ext f - rfl - + exact e.symm.injective + have reverse_hom_range_top : reverse_hom.range = ⊤ := + MonoidHom.range_eq_top.mpr e.symm.surjective let B' := Subgroup.map reverse_hom B use B' refine ⟨?_, ?_⟩ - . simp only [B'] + · simp only [B'] apply Subgroup.map_isMulCommutative - . simp only [B'] + · simp only [B'] rw [Subgroup.finiteIndex_iff] rw [Subgroup.index_map] rw [reverse_hom_ker_bot, reverse_hom_range_top, sup_bot_eq, Subgroup.index_top, mul_one] exact B_finite_index.index_ne_zero - . - have base_fg: (map new_map_hom.toMonoidHom my_new_range).FG := by - apply group_fg_map - simp [my_new_range] - have group_fg: Group.FG (GRepW.comp (GRepW_base)).range := by - apply Group.fg_range - exact (Group.fg_iff_subgroup_fg (GRepW.comp GRepW_base).range).mp group_fg - - have base_le: (map new_map_hom.toMonoidHom my_new_range) ≤ mapped_group := by - intro a ha - simp at ha - simp [mapped_group] - obtain ⟨g, g_mem, g_eq_a⟩ := ha - use g - refine ⟨?_, g_eq_a⟩ - apply Subgroup.le_topologicalClosure my_new_range g_mem - - - rw [Subgroup.fg_iff] - rw [Subgroup.fg_iff] at base_fg - obtain ⟨S, S_eq, S_finite⟩ := base_fg - - have S_in_map: ∀ s ∈ S, s ∈ (map new_map_hom.toMonoidHom my_new_range) := by - rw [Subgroup.ext_iff] at S_eq - intro s hs - apply (S_eq s).mp ?_ - exact Subgroup.mem_closure.mpr fun K a ↦ a hs - - let S' := Set.range (fun (s: S) => (⟨s.val, base_le (S_in_map s s.property)⟩ : mapped_group)) - use S' - -- TODO - this is a huge mess. This can be a general proof about the closure of Subgroup.subgroupOf - refine ⟨?_, ?_⟩ - . - simp only [S'] - rw [← S_eq] - ext a - refine ⟨?_, ?_⟩ - . intro ha - rw [Subgroup.mem_subgroupOf] - induction ha using Subgroup.closure_induction_left with - | one => simp - | mul_left y hy z hz h_other_z => - simp - apply Subgroup.mul_mem - . simp at hy - obtain ⟨p, p_mem, p_eq_y⟩ := hy - rw [← p_eq_y] - simp - apply Subgroup.mem_closure_of_mem p_mem - . exact h_other_z - | inv_mul_cancel y hy z hz h_other_z => - simp - apply Subgroup.mul_mem - . simp - simp at hy - obtain ⟨p, p_mem, p_eq_y⟩ := hy - rw [← p_eq_y] - simp - apply Subgroup.mem_closure_of_mem p_mem - . exact h_other_z - . intro ha - rw [Subgroup.mem_subgroupOf] at ha - rw [Subgroup.mem_closure] - intro K hK - rw [Subgroup.mem_closure] at ha - have a_mem := ha (Subgroup.map mapped_group.subtype K) ?_ - . simpa using a_mem - . simp - intro s hs - rw [Set.range_subset_iff] at hK - have s_mem := hK ⟨s, hs⟩ - simp - simp at s_mem - use ?_ - apply base_le (S_in_map s hs) - . - simp [S'] - rw [← Set.finite_coe_iff] at S_finite - apply Set.finite_range + · let : Group.FG my_new_range := Group.fg_range (GRepW.comp GRepW_base) + let : Group.FG (Subgroup.map new_map_hom.toMonoidHom my_new_range) := + Group.fg_of_surjective (f := (MulEquiv.subgroupMap new_map_hom my_new_range).toMonoidHom) + (MulEquiv.subgroupMap new_map_hom my_new_range).surjective + let : Group.FG ((Subgroup.map new_map_hom.toMonoidHom my_new_range).subgroupOf mapped_group) := + Group.fg_of_surjective (f := map_sub_equiv.toMonoidHom) map_sub_equiv.surjective + exact (Group.fg_iff_subgroup_fg _).mp inferInstance --- We need this to work with Finset structure Theorem3_1_Input (G: Type*) [Group G] where -- A finite index subgroup G' of G @@ -629,15 +381,7 @@ structure Theorem3_1_Input (G: Type*) [Group G] where hφ: Function.Surjective φ -#synth Group.FG (rho_g) - - lemma g_hom_abelian {T: Type*} [Group T] (A: Subgroup G) (A_finite_index: A.FiniteIndex) (hom: A →* T) (hom_surjective: Function.Surjective hom) (H: Subgroup T) (H_infinite: Infinite H) (H_abeliean: IsMulCommutative H) (H_finite_index: H.FiniteIndex) (H_FG: Group.FG H): Nonempty (Theorem3_1_Input G) := by - -- TODO - generalize this to a lemma: finite-index subgroup of an infinite group is infinite - -- and upstream to mathlib - - - -- TODO - figure out how to make instance inference work here obtain ⟨i, j, i_fin, j_fin, p, p_prime, e, exists_iso⟩ := @CommGroup.equiv_free_prod_prod_multiplicative_zmod H (haveI := H_abeliean; { (inferInstance : Group H) with mul_comm := mul_comm' }) (H_FG) have iso := Classical.choice exists_iso @@ -661,8 +405,6 @@ lemma g_hom_abelian {T: Type*} [Group T] (A: Subgroup G) (A_finite_index: A.Fini apply Finite.instProd have no_finite := H_infinite.not_finite contradiction - - -- TODO - can we get the comp '∘' syntax to give us a monoid hom, instead of a plain function? let h_to_z := (Pi.evalMonoidHom _ (Classical.choice (by exact j_nonempty ))).comp ((MonoidHom.fst _ _).comp iso.toMonoidHom) @@ -671,19 +413,17 @@ lemma g_hom_abelian {T: Type*} [Group T] (A: Subgroup G) (A_finite_index: A.Fini unfold h_to_z simp apply Function.Surjective.comp - . + · intro x simp use fun _ => x - . apply Function.Surjective.comp - . exact Prod.fst_surjective - . exact iso.surjective + · apply Function.Surjective.comp + · exact Prod.fst_surjective + · exact iso.surjective let G' := Subgroup.comap hom H - -- TODO - generalize this and PR to mathlib - have G'_finite_index: G'.FiniteIndex := by unfold G' @@ -691,15 +431,10 @@ lemma g_hom_abelian {T: Type*} [Group T] (A: Subgroup G) (A_finite_index: A.Fini index_ne_zero := by simp rw [Subgroup.index_comap] - -- apply somehow found this - how does it work??? exact Subgroup.FiniteIndex.index_ne_zero } - - - -- TODO - there must be an easier way to do this let g'_to_h: (map A.subtype G') →* H := { toFun := fun g => ⟨hom ⟨g.val, by ( - -- TODO - clean this up have foo := g.property rw [Subgroup.mem_map] at foo obtain ⟨x, hx, a_subtype⟩ := foo @@ -707,7 +442,7 @@ lemma g_hom_abelian {T: Type*} [Group T] (A: Subgroup G) (A_finite_index: A.Fini simp )⟩, by ( have g_prop := g.property - simp only [G', Subgroup.mem_comap] at g_prop + simp only [G'] at g_prop rw [Subgroup.mem_map] at g_prop obtain ⟨x, hx, a_subtype⟩ := g_prop simp_rw [← a_subtype] @@ -748,18 +483,18 @@ lemma g_hom_abelian {T: Type*} [Group T] (A: Subgroup G) (A_finite_index: A.Fini rw [Subgroup.finiteIndex_iff] simp [Subgroup.index_map_subtype] refine ⟨?_, ?_⟩ - . rw [← ne_eq] + · rw [← ne_eq] rw [← Subgroup.finiteIndex_iff] exact G'_finite_index - . exact A_finite_index.index_ne_zero + · exact A_finite_index.index_ne_zero -- G'_finite_index φ := g_to_z, hφ := by simp [g_to_z, g_to_additive_z] apply Function.Surjective.comp - . simp [additive_h_to_z] + · simp [additive_h_to_z] exact h_to_z_surjective - . + · simp [additive_g'_to_h, g'_to_h] intro h obtain ⟨a, hom_a⟩ := hom_surjective h @@ -769,7 +504,6 @@ lemma g_hom_abelian {T: Type*} [Group T] (A: Subgroup G) (A_finite_index: A.Fini simp [G', hom_a] } -#print axioms g_hom_abelian -- Case 1 in Section 3.3 of Vikman, where the representation ρ(G) is infinite lemma rho_g_case_infinite {d: ℕ} (hd: HasPolynomialGrowthD S d) (hr: Infinite (↥(rho_g))): Nonempty (Theorem3_1_Input G) := by @@ -785,11 +519,11 @@ lemma rho_g_case_infinite {d: ℕ} (hd: HasPolynomialGrowthD S d) (hr: Infinite have target := g_hom_abelian ⊤ (by infer_instance) (g_rho) ?_ (H) ?_ ?_ ?_ ?_ - . exact target - . + · exact target + · simp [g_rho] exact MonoidHom.rangeRestrict_surjective GRepW_base - . + · unfold rho_g at hr have card_mul := Subgroup.card_mul_index H unfold rho_g at card_mul @@ -798,10 +532,9 @@ lemma rho_g_case_infinite {d: ℕ} (hd: HasPolynomialGrowthD S d) (hr: Infinite replace card_mul := card_mul.resolve_right H_finite_index.index_ne_zero rw [Nat.card_eq_zero] at card_mul exact card_mul.resolve_left (fun h => h.false ⟨1, H.one_mem⟩) - . exact H_abelian - . exact H_finite_index - . exact h_fg + · exact H_abelian + · exact H_finite_index + · exact h_fg -#print axioms rho_g_case_infinite end GeneratesNS diff --git a/Gromov/Theorem31Input.lean b/Gromov/Theorem31Input.lean index 22f01cc..81b7985 100644 --- a/Gromov/Theorem31Input.lean +++ b/Gromov/Theorem31Input.lean @@ -11,9 +11,6 @@ The finite-image case `rho_g_case_finite` and `exists_theorem_3_1_input`. public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false open Subgroup open scoped Finset @@ -28,24 +25,12 @@ include hGS open scoped RealInnerProductSpace -set_option synthInstance.maxHeartbeats 500000 -set_option maxHeartbeats 9000000 open MeasureTheory open MeasureTheory --- TODO - figure out why we need these - - -#print axioms laplace_bounded -#print axioms laplace_self_adjoint -#print axioms laplace_positive_semidefinite - - -#synth Module ℝ (Lp ℝ 2 (μ := MeasureTheory.volume (α := G))) - omit hGS in lemma rangeRestrict_range {A B: Type*} [Group A] [Group B] (f: A →* B): f.rangeRestrict.range = ⊤ := by @@ -99,8 +84,6 @@ lemma rho_g_case_finite (hr: Finite (↥(rho_g))): Nonempty (Theorem3_1_Input G) simp [lambda_g] rw [mul_sub] } - - -- TODO - this could be much cleaner have act_eq_lambda (g: G) (hg: g ∈ (GRepW_base).ker) (f: LipschitzH ): (gAct g f) = f + ConstLipschitzH (lambda_g ⟨g, hg⟩ f) := by have act := act_v g hg f simp [GRep, gAct, ConstF] at act @@ -116,8 +99,8 @@ lemma rho_g_case_finite (hr: Finite (↥(rho_g))): Nonempty (Theorem3_1_Input G) apply eq_add_of_sub_eq at app_a rw [app_a] rw [add_comm] - simp [LipschitzH_apply] - simp [LipschitzH_apply] at hy + simp + simp at hy have other_app := congrFun hy 1 simp at other_app rw [← other_app] @@ -152,24 +135,23 @@ lemma rho_g_case_finite (hr: Finite (↥(rho_g))): Nonempty (Theorem3_1_Input G) } by_cases lambda_g_infinite: Infinite (lambda_g_hom.range) - . + · apply g_hom_abelian G' ?_ lambda_g_hom.rangeRestrict ?_ lambda_g_hom.rangeRestrict.range ?_ ?_ ?_ ?_ - . simp [G'] + · simp [G'] exact ker_finite_index - . exact MonoidHom.rangeRestrict_surjective lambda_g_hom - . rw [rangeRestrict_range] + · exact MonoidHom.rangeRestrict_surjective lambda_g_hom + · rw [rangeRestrict_range] simp - -- TODO: PR this to mathlib apply (Equiv.infinite_iff (α := lambda_g_hom.range) _).mp - . exact lambda_g_infinite - . exact { + · exact lambda_g_infinite + · exact { toFun := fun g => ⟨g, trivial⟩ invFun := fun g => g.val left_inv := by simp [Function.LeftInverse] right_inv := by simp [Function.RightInverse, Function.LeftInverse] } - . exact { + · exact { is_comm := { comm := by intro a b @@ -178,18 +160,16 @@ lemma rho_g_case_finite (hr: Finite (↥(rho_g))): Nonempty (Theorem3_1_Input G) rw [add_comm] } } - . rw [Subgroup.finiteIndex_iff] + · rw [Subgroup.finiteIndex_iff] rw [rangeRestrict_range] simp - . rw [rangeRestrict_range] + · rw [rangeRestrict_range] simp exact Group.FG.out - . + · simp only [not_infinite_iff_finite] at lambda_g_infinite let G'' := lambda_g_hom.ker have G''_finite_index := Subgroup.finiteIndex_ker lambda_g_hom - - -- TODO - this could be a lot cleaner have G''_act_v (g: lambda_g_hom.ker) (x: G) (f: LipschitzH ): f (x * g) = f x := by specialize act_v g simp at act_v @@ -224,8 +204,6 @@ lemma rho_g_case_finite (hr: Finite (↥(rho_g))): Nonempty (Theorem3_1_Input G) -- View G'' as a subgroup of G let G''_subgroup_G := (Subgroup.map G'.subtype lambda_g_hom.ker) - - -- TODO - clean up this proof have G''_subgroup_finite_index: G''_subgroup_G.FiniteIndex := by unfold G''_subgroup_G rw [Subgroup.finiteIndex_iff] @@ -244,7 +222,7 @@ lemma rho_g_case_finite (hr: Finite (↥(rho_g))): Nonempty (Theorem3_1_Input G) have f_range_eq (f: LipschitzH ): Set.range f = Set.range ((fun (x: G ⧸ G''_subgroup_G) => f (x.out))) := by ext a refine ⟨?_, ?_⟩ - . intro ha + · intro ha simp at ha obtain ⟨y, hy⟩ := ha have y_mem: y ∈ Set.univ := by simp @@ -270,7 +248,7 @@ lemma rho_g_case_finite (hr: Finite (↥(rho_g))): Nonempty (Theorem3_1_Input G) use i rw [← f_translate] exact hy - . intro ha + · intro ha simp only [Set.mem_range] at ha obtain ⟨y, hy⟩ := ha simp @@ -287,16 +265,16 @@ lemma rho_g_case_finite (hr: Finite (↥(rho_g))): Nonempty (Theorem3_1_Input G) simp at hp obtain ⟨y, hy⟩ := hp by_cases p_le_z: ‖p‖ ≤ ‖z‖ - . exact p_le_z - . simp at p_le_z + · exact p_le_z + · simp at p_le_z have f_le := hz (j := f.toFun y) ?_ ?_ - . + · simp at f_le rw [← hy] exact f_le - . simp - . simp + · simp + · simp rw [← hy] at p_le_z linarith @@ -326,22 +304,19 @@ lemma rho_g_case_finite (hr: Finite (↥(rho_g))): Nonempty (Theorem3_1_Input G) have app := congrFun f_const_fn a rw [app] simp [ConstLipschitzH] - . + · rw [f_range_eq] apply Set.finite_range - . apply Set.range_nonempty + · apply Set.range_nonempty obtain ⟨f, nontrivial_f⟩ := exists_nontrivial_harmonic obtain ⟨z, f_eq_const⟩ := all_f_const f specialize nontrivial_f z contradiction - - --- TODO - upstream to mathlib omit hGS in lemma exists_theorem_3_1_input [hGS: Generates ] {d: ℕ} (hd: HasPolynomialGrowthD S d): Nonempty (Theorem3_1_Input G) := by by_cases rho_g_infinite: Infinite (↥(rho_g)) - . exact rho_g_case_infinite hd rho_g_infinite - . exact rho_g_case_finite (by simpa using rho_g_infinite) + · exact rho_g_case_infinite hd rho_g_infinite + · exact rho_g_case_finite (by simpa using rho_g_infinite) end GeneratesNS diff --git a/Gromov/Theorem323.lean b/Gromov/Theorem323.lean index 0e1604a..8741f01 100644 --- a/Gromov/Theorem323.lean +++ b/Gromov/Theorem323.lean @@ -9,17 +9,10 @@ public import Gromov.BoundedDoubling `theorem_3_23` and the resulting finite-dimensionality of the space of Lipschitz harmonic functions. -Root of the Theorem 3.23 hierarchy: importing it pulls in the cutoff inequality, the quadratic -form, the packing argument and the Poincaré inequality. -/ public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false open scoped Finset open scoped Pointwise @@ -30,7 +23,186 @@ open Generates variable [hGS: Generates] include hGS -set_option maxHeartbeats 2500000 in +private lemma scale_contraction_bound (d w : ℕ) + (hw : w = ⌈Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a d))⌉₊) : + GeneratesNS.C * Real.exp (a d * 2) ^ 2 * (16 ^ (-↑w : ℝ)) ^ 2 * ↑(#S) + * 16 ≤ 2⁻¹ := by + have ha : (0:ℝ) ≤ a d := by simp only [a]; positivity + have hE1 : (1:ℝ) ≤ Real.exp (a d) := Real.one_le_exp ha + have hE4 : (1:ℝ) ≤ Real.exp (a d) ^ 4 := one_le_pow₀ hE1 + have hEpos : (0:ℝ) < Real.exp (a d) := Real.exp_pos _ + have he4 : Real.exp (4 * a d) = Real.exp (a d) ^ 4 := by + rw [← Real.exp_nat_mul]; norm_num + have he2 : Real.exp (a d * 2) = Real.exp (a d) ^ 2 := by + rw [show a d * 2 = 2 * a d from by ring, ← Real.exp_nat_mul]; norm_num + have he2sq : Real.exp (a d * 2) ^ 2 = Real.exp (a d) ^ 4 := by + rw [he2]; ring + have hS0 : (0:ℝ) < ↑(#S) := by exact_mod_cast Finset.card_pos.mpr S_nonempty + have hXpos : (0:ℝ) < 16 ^ 4 * ↑(#S) * Real.exp (a d) ^ 4 := by positivity + have h16w : (16:ℝ) ^ 4 * ↑(#S) * Real.exp (a d) ^ 4 ≤ (16:ℝ) ^ (↑w : ℝ) := by + rw [← he4] + have hlog : (16:ℝ) ^ Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a d)) + = 16 ^ 4 * ↑(#S) * Real.exp (4 * a d) := + Real.rpow_logb (by norm_num) (by norm_num) (by rw [he4]; exact hXpos) + have hle : Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a d)) ≤ (↑w : ℝ) := by + have hdef : w = ⌈Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a d))⌉₊ := hw + rw [hdef]; exact_mod_cast Nat.le_ceil _ + calc 16 ^ 4 * ↑(#S) * Real.exp (4 * a d) + = (16:ℝ) ^ Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a d)) := hlog.symm + _ ≤ (16:ℝ) ^ (↑w : ℝ) := Real.rpow_le_rpow_of_exponent_le (by norm_num) hle + have ht0 : (0:ℝ) ≤ (16:ℝ) ^ (-↑w : ℝ) := Real.rpow_nonneg (by norm_num) _ + have htX : (16:ℝ) ^ (-↑w : ℝ) * (16 ^ 4 * ↑(#S) * Real.exp (a d) ^ 4) ≤ 1 := by + calc (16:ℝ) ^ (-↑w : ℝ) * (16 ^ 4 * ↑(#S) * Real.exp (a d) ^ 4) + ≤ (16:ℝ) ^ (-↑w : ℝ) * (16:ℝ) ^ (↑w : ℝ) := + mul_le_mul_of_nonneg_left h16w ht0 + _ = 1 := by rw [← Real.rpow_add (by norm_num)]; simp + have hsq : ((16:ℝ) ^ (-↑w : ℝ) * (16 ^ 4 * ↑(#S) * Real.exp (a d) ^ 4)) ^ 2 ≤ 1 := by + nlinarith [htX, mul_nonneg ht0 (le_of_lt hXpos)] + have hM8 : (0:ℝ) ≤ ((16:ℝ) ^ (-↑w : ℝ)) ^ 2 * (↑(#S)) ^ 2 * Real.exp (a d) ^ 4 * 16 ^ 8 := by + positivity + have hP : ((16:ℝ) ^ (-↑w : ℝ)) ^ 2 * (↑(#S)) ^ 2 * Real.exp (a d) ^ 4 * 16 ^ 8 ≤ 1 := by + nlinarith [hsq, hE4, hM8] + have key : GeneratesNS.C * Real.exp (a d * 2) ^ 2 * (16 ^ (-↑w : ℝ)) ^ 2 * ↑(#S) + * 16 ≤ 2⁻¹ := by + rw [he2sq]; simp only [GeneratesNS.C] + nlinarith [hP, hM8] + exact key + +private lemma phi_restrict_injective [v_data : V_Wrapper] + (data : GoodScalesData (V_basis v_data.V)) + (hw : data.w = ⌈Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a data.d))⌉₊) + (U : Submodule ℝ LipschitzH) + (bounded_double : ∀ f ∈ U, Q_R (16 * R_2 data) f f ≤ + Real.exp (2 * a data.d) * Q_R (R_2 data) f f) : + Function.Injective ((phi data).domRestrict (U.submoduleOf v_data.V)) := by + -- Pinning the module types keeps this rewrite out of the instance diamond on + -- `↥(U.submoduleOf _)` (`Submodule…addCommMonoid` vs `AddCommGroup.toAddCommMonoid`), + -- which otherwise only reconciles at a raised `maxSynthPendingDepth`. + rw [← LinearMap.ker_eq_bot (M := ↥(U.submoduleOf v_data.V)) + (M₂ := EuclideanSpace ℝ ↥(B_finsets data))] + rw [LinearMap.ker_eq_bot' (M := ↥(U.submoduleOf v_data.V)) + (M₂ := EuclideanSpace ℝ ↥(B_finsets data))] + intro u hu + + have u_le := lemma_3_26_a data u + simp at hu + simp [hu] at u_le + + have u_bound := harmonic_r2_inequality u (by + have u_prop := u.val.val.harmonic + simp [Harmonic] at u_prop + simp [Laplace_b] + ext a + simp + nth_rw 1 [u_prop] + simp [f_conv_mu] + ) (4 * R_2 data) (by simp [R_2]) + simp [B_r] at u_le + conv at u_bound => + lhs + arg 1 + equals (Metric.closedBall 1 (8 * (R_2 data))).toFinset => + simp + ring_nf + + grw [u_bound] at u_le + · + have u_double := bounded_double u (by + exact u.prop + ) + conv at u_double => + lhs + simp [Q_R] + + simp_rw [← pow_two] at u_double + grw [Finset.sum_le_sum_of_subset_of_nonneg (t := (finite_closed_ball 1 (16 * (R_2 data))).toFinset)] at u_le + · + simp at u_le + grw [u_double] at u_le + · + by_cases u_zero: u = 0 + · exact u_zero + · + have r_pos := R'_pos v_data.V + have r_ratio_le: (R_1 data + 1) / (4 * R_2 data) ≤ 4 * ((16: ℝ) ^ (-(data.w : ℝ))) := by + simp [R_1, R_2] + field_simp + have i_diff := (GoodScales data).i_diff_mem + simp at i_diff + have one_le: (1: ℝ) ≤ 2*(16^((GoodScales data).i_1)) := by + apply one_le_mul_of_one_le_of_one_le + · simp + · rw [one_le_pow_iff_of_nonneg] + · simp + · simp + · simp + have h_i := (GoodScales data).i_1_pos + grind + grw [one_le] + rw [← mul_add] + rw [← two_mul] + ring_nf + rw [← pow_add] + apply mul_le_mul + · + rw [pow_le_pow_iff_right₀] + · grind + · simp + · norm_num + · simp + · simp + + conv at u_le => + rhs + equals GeneratesNS.C * Real.exp (2 * a data.d) * (((↑(R_1 data) + 1) / ((↑(4 * R_2 data : ℝ))))^2 * ↑(#S) * (Real.exp (2 * a data.d) * Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val)) => + ring + + grw [r_ratio_le] at u_le + ring_nf at u_le + · + have le_half: Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val ≤ (2: ℝ)⁻¹ * Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := by + have qr_nonneg : 0 ≤ Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := + Q_R_self_nonneg _ _ + have key := scale_contraction_bound data.d data.w hw + calc Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val + ≤ (GeneratesNS.C * Real.exp (a data.d * 2) ^ 2 * (16 ^ (-↑data.w : ℝ)) ^ 2 * ↑(#S) + * 16) * Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := by nlinarith [u_le] + _ ≤ 2⁻¹ * Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := by nlinarith [key, qr_nonneg] + + have Q_r_zero: Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val = 0 := by + by_contra! + rw [mul_comm] at le_half + have foo := one_le_of_le_mul_left₀ (by + have nonneg: 0 ≤ Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := + Q_R_self_nonneg _ _ + grind + ) le_half + norm_num at foo + + rw [← Submodule.coe_eq_zero] + by_contra hne + exact absurd Q_r_zero (ne_of_gt (Q_R_pos_on_R' (↑u) hne _ (R'_le_R_2 data))) + · apply mul_nonneg (by positivity) + exact Q_R_self_nonneg _ _ + · simp [GeneratesNS.C] + positivity + + · simp [GeneratesNS.C] + positivity + · + simp [GeneratesNS.C] + positivity + · intro a ha + simp + simp at ha + grind + · intro i hi _ + positivity + · + simp [GeneratesNS.C] + positivity + + lemma theorem_3_23 (d: ℕ) (hd: 0 < d): ∃ C: ℕ, ∀ v_data: V_Wrapper, growth_bound (V_basis v_data.V) d → (Module.finrank ℝ v_data.V) < C := by let w := ⌈Real.logb 16 ((16^4) * #(S) * Real.exp (4 * a (d)))⌉₊ let C: ℕ := 1 + (⌈2 * Real.exp (w * (a d))⌉₊) @@ -43,16 +215,16 @@ lemma theorem_3_23 (d: ℕ) (hd: 0 < d): ∃ C: ℕ, ∀ v_data: V_Wrapper, grow hw := by simp apply Real.logb_pos - . simp - . apply one_lt_mul - . + · simp + · apply one_lt_mul + · have card_s: 1 ≤ #(S) := by simp apply S_nonempty grw [← card_s] simp norm_num - . + · norm_num simp [a] positivity @@ -61,16 +233,16 @@ lemma theorem_3_23 (d: ℕ) (hd: 0 < d): ∃ C: ℕ, ∀ v_data: V_Wrapper, grow rw [Nat.lt_ceil] simp rw [Real.lt_logb_iff_rpow_lt] - . + · have mul_pos: 1 < ↑(#S) * Real.exp (4 * a d) := by apply one_lt_mul - . simp + · simp apply S_nonempty - . simp [a] + · simp [a] positivity linarith - . simp - . have S_ne: #(S) ≠ 0 := by + · simp + · have S_ne: #(S) ≠ 0 := by have foo := S_card_ne_zero_re simpa using foo positivity @@ -80,172 +252,7 @@ lemma theorem_3_23 (d: ℕ) (hd: 0 < d): ∃ C: ℕ, ∀ v_data: V_Wrapper, grow obtain ⟨U, U_sub_v, hU_dim, bounded_double⟩ := exists_bounded_doubling_subspace data let phi_u := (phi data).domRestrict (U.submoduleOf v_data.V) - have phi_u_inj: Function.Injective phi_u := by - -- Pinning the module types keeps this rewrite out of the instance diamond on - -- `↥(U.submoduleOf _)` (`Submodule…addCommMonoid` vs `AddCommGroup.toAddCommMonoid`), - -- which otherwise only reconciles at a raised `maxSynthPendingDepth`. - rw [← LinearMap.ker_eq_bot (M := ↥(U.submoduleOf v_data.V)) - (M₂ := EuclideanSpace ℝ ↥(B_finsets data))] - rw [LinearMap.ker_eq_bot' (M := ↥(U.submoduleOf v_data.V)) - (M₂ := EuclideanSpace ℝ ↥(B_finsets data))] - intro u hu - - have u_le := lemma_3_26_a data u - simp [phi_u] at hu - simp [hu] at u_le - - have u_bound := harmonic_r2_inequality u (by - have u_prop := u.val.val.harmonic - simp [Harmonic] at u_prop - simp [Laplace_b] - ext a - simp - nth_rw 1 [u_prop] - simp [f_conv_mu] - ) (4 * R_2 data) (by simp [R_2]) - simp [B_r] at u_le - conv at u_bound => - lhs - arg 1 - equals (Metric.closedBall 1 (8 * (R_2 data))).toFinset => - simp - ring - - grw [u_bound] at u_le - . - have u_double := bounded_double u (by - exact u.prop - ) - conv at u_double => - lhs - simp [Q_R] - - simp_rw [← pow_two] at u_double - grw [Finset.sum_le_sum_of_subset_of_nonneg (t := (finite_closed_ball 1 (16 * (R_2 data))).toFinset)] at u_le - . - simp [finite_closed_ball] at u_le - grw [u_double] at u_le - . - by_cases u_zero: u = 0 - . exact u_zero - . - have r_pos := R'_pos v_data.V - have r_ratio_le: (R_1 data + 1) / (4 * R_2 data) ≤ 4 * ((16: ℝ) ^ (-(data.w : ℝ))) := by - simp [R_1, R_2] - field_simp - have i_diff := (GoodScales data).i_diff_mem - simp at i_diff - have one_le: (1: ℝ) ≤ 2*(16^((GoodScales data).i_1)) := by - norm_num - apply one_le_mul_of_one_le_of_one_le - . simp - . rw [one_le_pow_iff_of_nonneg] - . simp - . simp - . simp - have h_i := (GoodScales data).i_1_pos - grind - grw [one_le] - rw [← mul_add] - rw [← two_mul] - ring - rw [← pow_add] - apply mul_le_mul - . - rw [pow_le_pow_iff_right₀] - . grind - . simp - . norm_num - . simp - . simp - - conv at u_le => - rhs - equals GeneratesNS.C * Real.exp (2 * a data.d) * (((↑(R_1 data) + 1) / ((↑(4 * R_2 data : ℝ))))^2 * ↑(#S) * (Real.exp (2 * a data.d) * Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val)) => - ring - - grw [r_ratio_le] at u_le - ring_nf at u_le - . - have le_half: Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val ≤ (2: ℝ)⁻¹ * Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := by - have qr_nonneg : 0 ≤ Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := - Q_R_self_nonneg _ _ - have ha : (0:ℝ) ≤ a data.d := by simp only [a]; positivity - have hE1 : (1:ℝ) ≤ Real.exp (a data.d) := Real.one_le_exp ha - have hE4 : (1:ℝ) ≤ Real.exp (a data.d) ^ 4 := one_le_pow₀ hE1 - have hEpos : (0:ℝ) < Real.exp (a data.d) := Real.exp_pos _ - have he4 : Real.exp (4 * a data.d) = Real.exp (a data.d) ^ 4 := by - rw [← Real.exp_nat_mul]; norm_num - have he2 : Real.exp (a data.d * 2) = Real.exp (a data.d) ^ 2 := by - rw [show a data.d * 2 = 2 * a data.d from by ring, ← Real.exp_nat_mul]; norm_num - have he2sq : Real.exp (a data.d * 2) ^ 2 = Real.exp (a data.d) ^ 4 := by - rw [he2]; ring - have hS0 : (0:ℝ) < ↑(#S) := by exact_mod_cast Finset.card_pos.mpr S_nonempty - have hXpos : (0:ℝ) < 16 ^ 4 * ↑(#S) * Real.exp (a data.d) ^ 4 := by positivity - have h16w : (16:ℝ) ^ 4 * ↑(#S) * Real.exp (a data.d) ^ 4 ≤ (16:ℝ) ^ (↑data.w : ℝ) := by - rw [← he4] - have hlog : (16:ℝ) ^ Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a data.d)) - = 16 ^ 4 * ↑(#S) * Real.exp (4 * a data.d) := - Real.rpow_logb (by norm_num) (by norm_num) (by rw [he4]; exact hXpos) - have hle : Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a data.d)) ≤ (↑data.w : ℝ) := by - have hdef : data.w = ⌈Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a data.d))⌉₊ := rfl - rw [hdef]; exact_mod_cast Nat.le_ceil _ - calc 16 ^ 4 * ↑(#S) * Real.exp (4 * a data.d) - = (16:ℝ) ^ Real.logb 16 (16 ^ 4 * ↑(#S) * Real.exp (4 * a data.d)) := hlog.symm - _ ≤ (16:ℝ) ^ (↑data.w : ℝ) := Real.rpow_le_rpow_of_exponent_le (by norm_num) hle - have ht0 : (0:ℝ) ≤ (16:ℝ) ^ (-↑data.w : ℝ) := Real.rpow_nonneg (by norm_num) _ - have htX : (16:ℝ) ^ (-↑data.w : ℝ) * (16 ^ 4 * ↑(#S) * Real.exp (a data.d) ^ 4) ≤ 1 := by - calc (16:ℝ) ^ (-↑data.w : ℝ) * (16 ^ 4 * ↑(#S) * Real.exp (a data.d) ^ 4) - ≤ (16:ℝ) ^ (-↑data.w : ℝ) * (16:ℝ) ^ (↑data.w : ℝ) := - mul_le_mul_of_nonneg_left h16w ht0 - _ = 1 := by rw [← Real.rpow_add (by norm_num)]; simp - have hsq : ((16:ℝ) ^ (-↑data.w : ℝ) * (16 ^ 4 * ↑(#S) * Real.exp (a data.d) ^ 4)) ^ 2 ≤ 1 := by - nlinarith [htX, mul_nonneg ht0 (le_of_lt hXpos)] - have hM8 : (0:ℝ) ≤ ((16:ℝ) ^ (-↑data.w : ℝ)) ^ 2 * (↑(#S)) ^ 2 * Real.exp (a data.d) ^ 4 * 16 ^ 8 := by - positivity - have hP : ((16:ℝ) ^ (-↑data.w : ℝ)) ^ 2 * (↑(#S)) ^ 2 * Real.exp (a data.d) ^ 4 * 16 ^ 8 ≤ 1 := by - nlinarith [hsq, hE4, hM8] - have key : GeneratesNS.C * Real.exp (a data.d * 2) ^ 2 * (16 ^ (-↑data.w : ℝ)) ^ 2 * ↑(#S) - * 16 ≤ 2⁻¹ := by - rw [he2sq]; simp only [GeneratesNS.C] - nlinarith [hP, hM8] - calc Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val - ≤ (GeneratesNS.C * Real.exp (a data.d * 2) ^ 2 * (16 ^ (-↑data.w : ℝ)) ^ 2 * ↑(#S) - * 16) * Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := by nlinarith [u_le] - _ ≤ 2⁻¹ * Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := by nlinarith [key, qr_nonneg] - - have Q_r_zero: Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val = 0 := by - by_contra! - rw [mul_comm] at le_half - have foo := one_le_of_le_mul_left₀ (by - have nonneg: 0 ≤ Q_R ↑(R_2 data) ⇑u.val.val ⇑u.val.val := - Q_R_self_nonneg _ _ - grind - ) le_half - norm_num at foo - - rw [← Submodule.coe_eq_zero] - by_contra hne - exact absurd Q_r_zero (ne_of_gt (Q_R_pos_on_R' (↑u) hne _ (R'_le_R_2 data))) - . apply mul_nonneg (by positivity) - exact Q_R_self_nonneg _ _ - . simp [GeneratesNS.C] - positivity - - . simp [GeneratesNS.C] - positivity - . - simp [GeneratesNS.C] - positivity - . intro a ha - simp - simp at ha - grind - . intro i hi _ - positivity - . - simp [GeneratesNS.C] - positivity + have phi_u_inj : Function.Injective phi_u := phi_restrict_injective data rfl U bounded_double apply LinearMap.finrank_le_finrank_of_injective at phi_u_inj simp at phi_u_inj @@ -270,7 +277,7 @@ lemma theorem_3_23 (d: ℕ) (hd: 0 < d): ∃ C: ℕ, ∀ v_data: V_Wrapper, grow have hB : (B_finite data).toFinset = Finset.image (fun a => Metric.closedBall a (↑(R_1 data):ℝ)) (X_j_finite data).toFinset := by ext s - simp only [Set.Finite.mem_toFinset, B, Set.mem_image, Finset.mem_image, Finset.mem_coe] + simp only [Set.Finite.mem_toFinset, B, Set.mem_image, Finset.mem_image] rw [hB, B_finsets, Finset.card_image_of_injOn (hinj1.mono hcoe.le), Finset.card_image_of_injOn (hinj2.mono hcoe.le)] rw [← card_eq] @@ -282,14 +289,11 @@ lemma theorem_3_23 (d: ℕ) (hd: 0 < d): ∃ C: ℕ, ∀ v_data: V_Wrapper, grow equals 0 + 2 * Real.exp (↑data.w * a data.d) => simp apply add_le_add - . simp - . apply Nat.le_ceil + · simp + · apply Nat.le_ceil open scoped Topology - --- TODO - do we really need the double by_contra here? -- Theorem 3.19 -set_option maxHeartbeats 2500000 in @[expose] instance Lipschitz_finite_dimensional: FiniteDimensional ℝ LipschitzH := by classical @@ -314,14 +318,14 @@ instance Lipschitz_finite_dimensional: FiniteDimensional ℝ LipschitzH := by V_finite := by infer_instance V_even := by rw [finrank_span_finset_eq_card] - . + · simp [fin_basis] rw [Finset.card_image_of_injective] - . grind - . + · grind + · exact Module.Basis.injective B - . + · simp [fin_basis] apply LinearIndepOn.id_image exact Module.Basis.linearIndepOn B ↑fin_basis_idx @@ -340,7 +344,7 @@ instance Lipschitz_finite_dimensional: FiniteDimensional ℝ LipschitzH := by -- `large_v.V` does not reduce on its own inside `rw`, so name the (definitional) equation. have large_v_V: large_v.V = Submodule.span ℝ fin_basis := rfl specialize V_bound large_v ?_ - . + · simp [growth_bound, my_expr] norm_cast @@ -363,7 +367,7 @@ instance Lipschitz_finite_dimensional: FiniteDimensional ℝ LipschitzH := by equals (𝓝[>] (0 * 0)) => simp apply Filter.TendstoNhdsWithinIoi.mul (by simp) (by simp) - . + · unfold HasPolynomialGrowthD at hd obtain ⟨a, s_growth⟩ := hd simp @@ -371,12 +375,11 @@ instance Lipschitz_finite_dimensional: FiniteDimensional ℝ LipschitzH := by rw [← Filter.tendsto_add_atTop_iff_nat R''] -- Filter.tendsto_add_atTop_iff_nat apply squeeze_zero_nhdsGT (g := (fun (R: ℕ) => (det_bound_const (V_basis large_v.V) * (1 + (R + R'')) ^ 2 * ((a * (R + R'')^d : ℝ))) / ((R + R'') ^ (↑d + 3) : ℝ))) - . + · rw [Filter.eventually_atTop] use 1 intro R R_pos have det_pos := (Q_R_matrix_pos_def (V_basis large_v.V) (R + R'') (by - -- TODO - why is this so messy? simp [R''] norm_cast have foo := Nat.le_ceil (a := R'_ large_v.V) @@ -386,7 +389,7 @@ instance Lipschitz_finite_dimensional: FiniteDimensional ℝ LipschitzH := by )).det_pos norm_cast at det_pos positivity - . + · apply Filter.Eventually.of_forall intro R have foo := det_bound (V_basis large_v.V) (R := R + R'') (by @@ -402,7 +405,7 @@ instance Lipschitz_finite_dimensional: FiniteDimensional ℝ LipschitzH := by push_cast at foo refine le_trans (mul_le_mul_of_nonneg_right foo (by positivity)) ?_ by_cases const_zero: det_bound_const (V_basis large_v.V) = 0 - . + · simp [const_zero] field_simp @@ -410,25 +413,25 @@ instance Lipschitz_finite_dimensional: FiniteDimensional ℝ LipschitzH := by rw [mul_div_assoc] rw [mul_assoc] rw [mul_le_mul_iff_right₀] - . + · by_cases r_zero: (R + R'') = 0 - . + · norm_cast simp [r_zero] - . + · grw [s_growth (R + R'') (by grind)] norm_cast simp rw [mul_div_assoc] - . + · have nonneg := det_bound_const_nonneg (V_basis large_v.V) grind - . poly_tendsto - . + · poly_tendsto + · unfold HasPolynomialGrowthD at hd obtain ⟨a, s_growth⟩ := hd apply squeeze_zero_nhdsGT (g := (fun (n: ℝ) => (a * n^d : ℝ) / (n ^ (↑d + 3))) ∘ (fun (n: ℕ) => (n: ℝ))) - . + · rw [Filter.eventually_atTop] use 1 intro n hn @@ -439,32 +442,30 @@ instance Lipschitz_finite_dimensional: FiniteDimensional ℝ LipschitzH := by norm_cast positivity - . + · apply Filter.Eventually.of_forall intro n by_cases hn: n = 0 - . + · simp [hn] - . + · grw [s_growth n (by grind)] norm_cast simp - . poly_tendsto - . + · poly_tendsto + · rw [large_v_V, finrank_span_finset_eq_card] at V_bound - . + · simp [fin_basis] at V_bound rw [Finset.card_image_of_injective] at V_bound - . + · simp [card_fin_basis_idx] at V_bound grind - . exact Module.Basis.injective B - . + · exact Module.Basis.injective B + · simp [fin_basis] apply LinearIndepOn.id_image exact Module.Basis.linearIndepOn B ↑fin_basis_idx -#synth FiniteDimensional ℝ LipschitzH -#print axioms Lipschitz_finite_dimensional end GeneratesNS diff --git a/Gromov/Theorem38.lean b/Gromov/Theorem38.lean index f00df84..c132e22 100644 --- a/Gromov/Theorem38.lean +++ b/Gromov/Theorem38.lean @@ -6,15 +6,12 @@ public import Gromov.Representation /-! # Theorem 3.8 -`theorem_3_8` and its real form: a group of polynomial growth admits a nontrivial -finite-dimensional representation. +A finitely generated polynomial-growth subgroup of a compact linear group is +virtually abelian, over either the real or the complex numbers. -/ public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false open Subgroup open scoped Finset @@ -29,12 +26,9 @@ include hGS open scoped RealInnerProductSpace -set_option synthInstance.maxHeartbeats 500000 -set_option maxHeartbeats 9000000 omit hGS in -set_option maxHeartbeats 500000 in lemma theorem_3_8 {V: Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] [FiniteDimensional ℂ V] (H: Subgroup (V →L[ℂ] V)ˣ) [DecidableEq H] (h_compact: CompactSpace H) (G: Subgroup H) (G_fg: G.FG) (S_data: SPolyData G): ∃ A: Subgroup G, IsMulCommutative A ∧ A.FiniteIndex := by obtain ⟨H', ⟨H_equiv_H'⟩⟩ := new_weyl_unitarian_trick (V := V) (H := H) let G' := Subgroup.map H'.subtype (Subgroup.map H_equiv_H'.symm.toMonoidHom G) @@ -105,18 +99,17 @@ lemma theorem_3_8 {V: Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] [F exact G_fg by_cases dim_le_one: Module.finrank ℂ (V) ≤ 1 - . + · use ⊤ refine ⟨?_, ?_⟩ - . + · have map_dim := Module.finrank_linearMap ℂ ℂ V V - -- TODO - is there an easier way to prove this? have map_dim_le_one: Module.finrank ℂ (V →ₗ[ℂ] V) ≤ 1 := by rw [map_dim] by_cases dim_eq_zero: Module.finrank ℂ (V) = 0 - . simp [dim_eq_zero] - . have dim_eq_one: Module.finrank ℂ (V) = 1 := by omega + · simp [dim_eq_zero] + · have dim_eq_one: Module.finrank ℂ (V) = 1 := by omega simp [dim_eq_one] rw [finrank_le_one_iff] at map_dim_le_one @@ -128,8 +121,6 @@ lemma theorem_3_8 {V: Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] [F simp obtain ⟨p, hx⟩ := v_span x.val.val.val obtain ⟨q, hy⟩ := v_span y.val.val.val - - -- TODO - upstream to mathlib have clm_apply (f: V →L[ℂ] V) (v: V): f v = f.toLinearMap v := rfl rw [clm_apply] rw [clm_apply] @@ -139,8 +130,8 @@ lemma theorem_3_8 {V: Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] [F rw [← hx, ← hy] simp rw [smul_comm] - . infer_instance - . + · infer_instance + · let new_S_data := map_S_data G (f := H'.subtype.comp (H_equiv_H'.symm.toMonoidHom)) S_data obtain ⟨N, N_comm, N_finite_index⟩ := compact_lie_virtually_abelian (Module.finrank ℂ V) (by omega) G' G'_fg (by @@ -158,17 +149,17 @@ lemma theorem_3_8 {V: Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] [F let new_N' := Subgroup.map G'_to_G N use new_N' refine ⟨?_, ?_⟩ - . + · simp [new_N'] apply Subgroup.map_isMulCommutative - . + · simp [new_N'] rw [Subgroup.finiteIndex_iff] rw [Subgroup.index_map_of_injective] - . simp + · simp refine ⟨?_, ?_⟩ - . exact N_finite_index.index_ne_zero - . conv => + · exact N_finite_index.index_ne_zero + · conv => arg 1 arg 1 arg 1 @@ -180,20 +171,20 @@ lemma theorem_3_8 {V: Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] [F use H'.subtype (H_equiv_H'.symm a) simp [my_hom] use ?_ - . have key : (MonoidHom.ofInjective (subtype_injective H')).symm + · have key : (MonoidHom.ofInjective (subtype_injective H')).symm ⟨↑(H_equiv_H'.symm (↑a : ↥H)), ⟨H_equiv_H'.symm (↑a : ↥H), rfl⟩⟩ = H_equiv_H'.symm (↑a : ↥H) := subtype_injective H' (MonoidHom.apply_ofInjective_symm _ _) exact Subtype.ext ((congrArg H_equiv_H' key).trans (H_equiv_H'.apply_symm_apply _)) - . simp [G'] + · simp [G'] use a.val use ?_ - . simp - . simp + · simp + · simp simp - . + · simp [G'_to_G] intro a b hab simpa using hab @@ -202,8 +193,6 @@ lemma theorem_3_8 {V: Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] [F instance rho_g_FG: Group.FG (rho_g) := by unfold rho_g apply Group.fg_range - --- TODO - deduplicate with 'map_S_Data' @[expose] def map_range_S_data {G H: Type*} [Group G] [Group H] [DecidableEq G] [DecidableEq H] {f: G →* H} (S_data: SPolyData (T := G) ⊤): SPolyData f.range := { S := (f.rangeRestrict.comp (Subgroup.topEquiv.toMonoidHom)) '' S_data.S @@ -232,9 +221,9 @@ def map_range_S_data {G H: Type*} [Group G] [Group H] [DecidableEq G] [Decidable rw [Set.Finite.toFinset_image] rw [← Finset.image_pow] grw [Finset.card_image_le] - . + · apply S_data.S_poly r hr - . exact S_data.S_finite + · exact S_data.S_finite } @[expose] @@ -265,12 +254,13 @@ def map_equiv_S_data {A B: Type*} [Group A] [Group B] [DecidableEq A] [Decidable rw [Set.Finite.toFinset_image] rw [← Finset.image_pow] grw [Finset.card_image_le] - . + · apply S_data.S_poly r hr - . exact S_data.S_finite + · exact S_data.S_finite } +omit hGS in /-- The real-inner-product-space version of `theorem_3_8`: a finitely generated, polynomial-growth subgroup of the units of a compact linear group over `ℝ` is virtually abelian. We reduce to the complex `theorem_3_8` by complexifying (`Cx.unitsMapHom`) just before the unitary machinery. -/ diff --git a/Gromov/ThreeTwoGenerates.lean b/Gromov/ThreeTwoGenerates.lean index 7187937..bb10b00 100644 --- a/Gromov/ThreeTwoGenerates.lean +++ b/Gromov/ThreeTwoGenerates.lean @@ -12,9 +12,6 @@ kernel of `φ`. public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false open Subgroup open scoped Finset @@ -29,9 +26,7 @@ include hGS open scoped RealInnerProductSpace -set_option synthInstance.maxHeartbeats 500000 -set_option maxHeartbeats 9000000 open MeasureTheory @@ -63,8 +58,8 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ have closure_enlarge: Subgroup.closure ({1, γ, γ⁻¹} ∪ (e_i '' Set.univ)) = Subgroup.closure (({1, γ, γ⁻¹} ∪ (e_i_regular '' Set.univ))^(max_phi + 1)) := by rw [Subgroup.closure_pow] - . simp - . unfold max_phi + · simp + · unfold max_phi simp conv => @@ -76,10 +71,10 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ rfl rw [closure_enlarge] apply Subgroup.closure_eq_of_le - . + · rw [hGS.generates] exact fun ⦃a⦄ a ↦ trivial - . + · simp intro s hs simp @@ -87,14 +82,13 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ rw [Subgroup.closure_toSubmonoid] dsimp [Membership.mem] rw [Submonoid.closure_eq_image_prod] - -- TODO - why do we need any of this? show s ∈ List.prod '' _ rw [Set.mem_image] have foo := Submonoid.exists_list_of_mem_closure (s := ((S ∪ S⁻¹) : Set G)) (x := s) rw [← Subgroup.closure_toSubmonoid _] at foo - simp only [mem_toSubmonoid, Finset.mem_coe] at foo + simp only [mem_toSubmonoid] at foo have generates := hGS.generates have x_in_top: s ∈ (⊤: Set G) := by simp @@ -114,7 +108,7 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ use new_list refine ⟨?_, ?_⟩ - . + · simp intro x hx unfold new_list list_with_mem l_attach at hx @@ -124,9 +118,9 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ have gamma_phi_in_minus_plus: γ^(φ a) ∈ ({1, γ, γ⁻¹} ∪ Set.range e_i_regular) ^ (max_phi - 1 +1) := by by_cases val_pos: 0 < φ a - . + · have eq_self: Int.natAbs (φ a) = φ a := by - simp [val_pos] + simp linarith conv => arg 2 @@ -134,8 +128,8 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ nth_rw 1 [← eq_self] norm_cast apply Set.pow_subset_pow_right (m := Int.natAbs (φ a)) (n := max_phi - 1 + 1) - . simp - . + · simp + · rw [cancel_add_minus] unfold max_phi simp @@ -147,10 +141,10 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ conv => pattern ofMul a equals a => rfl - . + · apply Set.pow_mem_pow simp - . + · have eq_neg_abs: (φ a) = -(φ a).natAbs := by rw [← Int.abs_eq_natAbs] simp at val_pos @@ -165,8 +159,8 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ norm_cast -- TOOD - deduplicate this with the positive case apply Set.pow_subset_pow_right (m := Int.natAbs (φ a)) (n := max_phi - 1 + 1) - . simp - . + · simp + · rw [cancel_add_minus] unfold max_phi simp @@ -178,7 +172,7 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ conv => pattern ofMul a equals a => rfl - . + · apply Set.pow_mem_pow simp have a_mem_s: a ∈ S := by exact l_mem_s a ha @@ -192,7 +186,7 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ simp have prod_eq_sum: e_i ⟨a, l_mem_s a ha⟩ + φ (ofMul a) • ofMul γ = (e_i_regular ⟨a, a_mem_s⟩) * (γ ^ φ (ofMul a)) := by - simp [e_i, e_i_regular, cancel_add_minus] + simp [e_i, e_i_regular] conv => @@ -202,7 +196,7 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ simp apply_fun (fun x => x * (γ ^ (- φ (ofMul a)))) - . + · simp only simp conv => @@ -222,7 +216,7 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ equals (a * γ ^ (-φ (ofMul a))) => rfl simp - . + · exact mul_left_injective (γ ^ (-φ (ofMul a))) @@ -253,10 +247,8 @@ lemma e_i_and_gamma_generates_G (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ exact List.map_id l -#print axioms e_i_and_gamma_generates_G -- The kernel of `φ` is generated by {γ_m_i} -set_option maxHeartbeats 1000000 lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ γ = 1) : Subgroup.closure (Set.range (Function.uncurry (gamma_m_helper (S := S) φ γ))) = AddSubgroup.toSubgroup φ.ker := by have phi_ofmul: φ (ofMul γ) = 1 := by exact hγ @@ -281,8 +273,8 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ have closure_enlarge: Subgroup.closure ({1, γ, γ⁻¹} ∪ (e_i '' Set.univ)) = Subgroup.closure (({1, γ, γ⁻¹} ∪ (e_i_regular '' Set.univ))^(max_phi + 1)) := by rw [Subgroup.closure_pow] - . simp - . unfold max_phi + · simp + · unfold max_phi simp @@ -291,7 +283,7 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ have gamma_m_ker_phi: (Subgroup.closure (Set.range (Function.uncurry gamma_m))) = φ.ker.toSubgroup := by ext z refine ⟨?_, ?_⟩ - . intro hz + · intro hz have foo := Submonoid.exists_list_of_mem_closure (s := Set.range (Function.uncurry gamma_m) ∪ (Set.range (Function.uncurry gamma_m))⁻¹) (x := z) rw [← Subgroup.closure_toSubmonoid _] at foo specialize foo hz @@ -325,7 +317,6 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ obtain ⟨n, val, val_in_s, prod_eq_a⟩ := a_eq_prod apply_fun Inv.inv at prod_eq_a simp at prod_eq_a - -- TODO - deduplicate this with the branch above rw [← prod_eq_a] simp have apply_mult := AddMonoidHom.toMultiplicative_apply_apply φ (toMul (e_i ⟨val, val_in_s⟩)) @@ -336,7 +327,7 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ equals e_i ⟨val, val_in_s⟩ => rfl rw [e_i_zero] at apply_mult exact apply_mult - . + · intro hz -- We need to write 'γ^a (f⁻¹ )' as an element of e_i @@ -351,7 +342,7 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ rw [← e_i_eq] at new_closure_e_i rw [new_closure_e_i] at foo rw [← Subgroup.closure_toSubmonoid _] at foo - simp only [mem_toSubmonoid, Finset.mem_coe] at foo + simp only [mem_toSubmonoid] at foo conv at foo => intro hz @@ -386,7 +377,7 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ have eq_split: list = list.takeWhile is_gamma ++ list.dropWhile is_gamma := by exact Eq.symm List.takeWhile_append_dropWhile by_cases header_eq_full: list.takeWhile is_gamma = list - . + · have list_eq_gamma_m: ∃ m: ℤ, list.unattach.prod = γ ^ m := by unfold is_gamma at header_eq_full clear eq_split is_gamma is_gamma_prop hlist @@ -400,21 +391,21 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ simp at header_eq_full exact header_eq_full.1 rw [List.takeWhile_cons_of_pos] at header_eq_full - . + · rw [List.cons_eq_cons] at header_eq_full specialize ih header_eq_full.2 obtain ⟨m, hm⟩ := ih by_cases h_eq_gamma: h = γ - . + · use (m + 1) simp [h_eq_gamma, hm] exact mul_self_zpow γ m - . use (-1 + m) + · use (-1 + m) simp [h_eq_gamma] at h_gamma simp [h_gamma, hm] rw [← zpow_neg_one] rw [zpow_add] - . simp [h_gamma] + · simp [h_gamma] have empty_prod_eq: list.unattach.prod = ([] : List E).unattach.prod := by @@ -427,7 +418,7 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ simp [hlist] exact ⟨[], empty_prod_eq⟩ - . + · have tail_nonempty: list.dropWhile is_gamma ≠ [] := by rw [not_iff_not.mpr List.takeWhile_eq_self_iff] at header_eq_full @@ -454,8 +445,6 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ rw [Set.mem_union] at drop_in_E have not_in_left: (List.dropWhile is_gamma list)[0].val ∉ ({γ, γ⁻¹} : Set G) := by simp [not_is_gamma_prop] - - -- TODO - why can't simp handle this? have in_right := Or.resolve_left drop_in_E not_in_left exact in_right @@ -507,13 +496,13 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ have gamma_copy_prod: gamma_copy.unattach.prod = γ^m := by simp [gamma_copy] by_cases m_ge: 0 ≤ m - . + · simp [m_ge] rw [← zpow_natCast] simp rw [← abs_eq_self] at m_ge rw [m_ge] - . + · simp [m_ge] rw [← zpow_natCast] simp @@ -525,13 +514,13 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ have gamma_copy_inv_prod: gamma_copy_inv.unattach.prod = γ^(-m) := by simp [gamma_copy_inv] by_cases m_ge: 0 ≤ m - . + · simp [m_ge] rw [← zpow_natCast] simp rw [← abs_eq_self] at m_ge rw [m_ge] - . + · simp [m_ge] rw [← zpow_natCast] simp @@ -546,9 +535,9 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ have header_prod: (List.takeWhile is_gamma list).unattach.prod = γ^m := by have my_lemma := take_count_sum_eq_exp (List.takeWhile is_gamma list) γ gamma_ne_inv ?_ - . + · rw [my_lemma] - . + · have foo (x: E) := List.mem_takeWhile_imp (p := fun (val: E) => (val = γ ∨ val = γ⁻¹)) (l := list) (x := x) conv at foo => intro x hx @@ -569,7 +558,7 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ have dropwhile_not_nul : (List.dropWhile is_gamma list) ≠ [] := by exact tail_nonempty apply_fun (fun x => x * (List.dropWhile is_gamma list).unattach.prod⁻¹) - . + · simp conv => pattern _[0] @@ -585,9 +574,7 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ have unattach_len_pos: 0 < (List.dropWhile is_gamma list).unattach.length := by rw [List.length_unattach] exact List.length_pos_iff.mpr dropwhile_not_nul - - -- TODO - this is gross, and should be removed - letI : Inhabited G := { + let : Inhabited G := { default := 1 } @@ -604,10 +591,10 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ rw [list_tail_unattach] rw [List.headI_mul_tail_prod_of_ne_nil] - . + · simp simp [header_prod] - . + · by_contra this rw [List.eq_nil_iff_length_eq_zero] at this rw [List.length_unattach] at this @@ -615,7 +602,7 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ contradiction - . exact mul_left_injective (List.dropWhile is_gamma list).unattach.prod⁻¹ + · exact mul_left_injective (List.dropWhile is_gamma list).unattach.prod⁻¹ have sublist_phi_zero: φ (gamma_copy ++ (List.dropWhile is_gamma list).tail).unattach.prod = 0 := by rw [← mega_list_prod] at hlist @@ -675,9 +662,9 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ | cons h t ih => simp split_ifs - . omega - . omega - . omega + · omega + · omega + · omega let rewritten_sub_list := (rewrite_list (gamma_copy ++ (list.dropWhile is_gamma).tail) sublist_phi_zero) let return_list := (⟨γ^m * (List.dropWhile is_gamma list)[0] * γ^(-m), in_range⟩) :: rewritten_sub_list.val @@ -712,24 +699,24 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ decreasing_by { simp split_ifs - . + · simp conv => rhs rw [← take_drop_len (p := fun (k: E) ↦ decide (↑k = γ) || decide (↑k = γ⁻¹))] apply add_lt_add_of_le_of_lt - . apply count_head_lt - . simp [is_gamma] at dropwhile_len_gt + · apply count_head_lt + · simp [is_gamma] at dropwhile_len_gt apply Nat.sub_one_lt apply Nat.pos_iff_ne_zero.mp dropwhile_len_gt - . + · simp-- [count_gamma_copy] conv => rhs rw [← take_drop_len (p := fun (k: E) ↦ decide (↑k = γ) || decide (↑k = γ⁻¹))] apply add_lt_add_of_le_of_lt - . apply count_head_lt - . simp [is_gamma] at dropwhile_len_gt + · apply count_head_lt + · simp [is_gamma] at dropwhile_len_gt apply Nat.sub_one_lt apply Nat.pos_iff_ne_zero.mp dropwhile_len_gt } @@ -771,7 +758,6 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ let my_res := rewrite_list ((z_list.filter (fun s ↦ !decide (s = 1))).attach.map (fun (g) => ⟨g.val, z_filter_mem_e g.val g.property⟩)) (by simp - -- TODO - there has to be a less awful way of doing this conv => arg 1 arg 2 @@ -783,8 +769,8 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ ext i q simp by_cases list_get: (List.filter (fun s ↦ !decide (s = 1)) z_list)[i]? = none - . simp [list_get] - . simp at list_get + · simp [list_get] + · simp at list_get simp [list_get] rw [← ofMul_list_prod] rw [h_z_list.2] @@ -800,12 +786,12 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ rw [Set.mem_image] use my_res.val.unattach refine ⟨?_, ?_⟩ - . simp only [Set.mem_setOf_eq] + · simp only [Set.mem_ofPred_eq] intro x hx rw [List.mem_unattach] at hx obtain ⟨x_prop, _⟩ := hx exact x_prop - . + · rw [← my_res_prop] conv => pattern List.unattach _ @@ -813,12 +799,13 @@ lemma three_two_gamma_m_generates (φ: (Additive G) →+ ℤ) (γ: G) (hγ: φ ext i q simp by_cases list_get: (List.filter (fun s ↦ !decide (s = 1)) z_list)[i]? = none - . simp [list_get] - . simp at list_get + · simp [list_get] + · simp at list_get simp [list_get] exact h_z_list.2 exact gamma_m_ker_phi +omit hGS in lemma three_two_S_n_subset_ker {G: Type*} [Group G] [DecidableEq G] (S: Finset G) (φ: (Additive G) →+ ℤ) (γ: G) (phi_gamma: φ γ = 1) (n: ℕ): ↑(three_two_S_n S φ γ n) ⊆ Additive.toMul '' φ.ker.carrier := by @@ -846,12 +833,12 @@ lemma three_two_S_n_subset_ker {G: Type*} [Group G] [DecidableEq G] (S: Finset G simp exact id (Eq.symm prod_eq_x) -lemma three_two_S_n_generates (d: ℕ) (hd: d >= 1) (hG: HasPolynomialGrowthD S d ) (φ: (Additive G) →+ ℤ) (γ : Additive G) (phi_gamma: φ γ = 1): ∃ n, AddSubgroup.closure (Additive.ofMul '' (three_two_S_n S φ γ (n))) = φ.ker := by +lemma three_two_S_n_generates (d: ℕ) (_hd: d >= 1) (hG: HasPolynomialGrowthD S d ) (φ: (Additive G) →+ ℤ) (γ : Additive G) (phi_gamma: φ γ = 1): ∃ n, AddSubgroup.closure (Additive.ofMul '' (three_two_S_n S φ γ (n))) = φ.ker := by obtain ⟨n, hn⟩ := three_poly_poly_growth_all_s_n d hG γ φ use n ext z refine ⟨?_, ?_⟩ - . intro hz + · intro hz induction hz using AddSubgroup.closure_induction with | mem x hx => have x_mem: x ∈ three_two_S_n S φ γ n := by @@ -867,7 +854,7 @@ lemma three_two_S_n_generates (d: ℕ) (hd: d >= 1) (hG: HasPolynomialGrowthD S exact (AddSubgroup.add_mem_cancel_right φ.ker hz).mpr hy | neg x x_mem hx => exact AddSubgroup.neg_mem φ.ker hx - . intro hz + · intro hz have generates_ker := three_two_gamma_m_generates φ γ phi_gamma have hz' : z ∈ Subgroup.closure (Set.range (Function.uncurry (gamma_m_helper (S := S) φ γ))) := by @@ -922,10 +909,10 @@ lemma three_two_ker_fg (d: ℕ) (hd: d >= 1) (hG: HasPolynomialGrowthD S d ) ( use ofMul '' ↑(three_two_S_n S φ γ n) refine ⟨hn, ?_⟩ rw [Set.finite_image_iff] - . + · simp - . intro a b hab - simpa using hab + · intro a _ b _ hab + exact Additive.ofMul.injective hab -- Extract a generatating set for the kernel of φ @@ -941,8 +928,7 @@ lemma finite_virtually_nilpotent {G: Type*} [Group G] [Finite G]: Group.IsVirtua rw [Group.IsVirtuallyNilpotent] use ⊥ refine ⟨?_, ?_⟩ - . exact Group.isNilpotent_of_subsingleton - -- TODO - prove that a finite group is nilpotent, and upstream to mathlib - . infer_instance + · exact Group.isNilpotent_of_subsingleton + · infer_instance end GeneratesNS diff --git a/Gromov/ThreeTwoGrowth.lean b/Gromov/ThreeTwoGrowth.lean index 1fc3a86..5fd825b 100644 --- a/Gromov/ThreeTwoGrowth.lean +++ b/Gromov/ThreeTwoGrowth.lean @@ -11,9 +11,6 @@ public import Gromov.Theorem31Input public section -set_option linter.style.longLine false -set_option linter.style.cdot false -set_option linter.style.commandStart false open Subgroup open scoped Finset @@ -28,9 +25,7 @@ include hGS open scoped RealInnerProductSpace -set_option synthInstance.maxHeartbeats 500000 -set_option maxHeartbeats 9000000 open MeasureTheory @@ -45,27 +40,27 @@ lemma take_count_sum_eq_exp {T: Type*} [ht: Group T] [heq: DecidableEq T] {E: Se | cons h t ih => simp [countElemOrInv] by_cases h_eq_g: h = g - . + · simp [h_eq_g] rw [ih] - . rw [← zpow_one_add] - . simp at hl + · rw [← zpow_one_add] + · simp at hl intro val hval have hl_right := hl.2 val (by simp) (by simp [hval]) exact hl_right - . + · have h_eq_inv: h = g⁻¹ := by specialize hl h simp at hl simp [h_eq_g] at hl exact hl - simp [h_eq_g, h_eq_inv] + simp [h_eq_inv] rw [ih] - . + · rw [← zpow_neg_one] rw [← zpow_add] simp [hg.symm] - . + · simp at hl intro val hval have hl_right := hl.2 val (by simp) (by simp [hval]) @@ -82,10 +77,10 @@ lemma list_filter_one {T: Type*} [DecidableEq T] [Group T] (l: List T): (l.filte | cons h t ih => simp by_cases h_eq_one: h = 1 - . + · simp [h_eq_one] exact ih - . + · rw [List.filter_cons] simp [h_eq_one] exact ih @@ -119,11 +114,7 @@ omit hGS in @[expose] noncomputable def three_two_B_n {G: Type*} [Group G] [DecidableEq G] (S: Finset G) (φ: (Additive G) →+ ℤ) (γ: G) (n: ℕ): Finset G := Finset.image (fun l => l.unattach.prod) (list_len_n S φ γ n ) - ---set_option maxHeartbeats 600000 - -- If G has polynomial growth, than we can find an N such that S_n ⊆ B_n * B_n⁻¹ -set_option maxHeartbeats 2000000 in lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) (φ: (Additive G) →+ ℤ) (s: G) (s_mem: s ∈ S): ∃ n, three_two_S_n (S := {s}) φ γ (n + 1) ⊆ ((three_two_B_n (S := {s}) φ γ n) * (three_two_B_n (S := {s}) φ γ n)⁻¹) := by by_contra! simp [HasPolynomialGrowthD] at hG @@ -163,7 +154,7 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) have disjoint_smul (M: ℕ) (hM: N ≤ M) (p: G) (p_mem: p ∈ three_two_S_n (S := {s}) φ γ (M + 1)) (p_not_prod: p ∉ three_two_B_n (S := {s}) φ γ M * (three_two_B_n (S := {s}) φ γ M)⁻¹): (p • three_two_B_n (S := {s}) φ γ M) ∩ (three_two_B_n (S := {s}) φ γ M) = ∅ := by rw [Finset.mem_mul.not] at p_not_prod - push_neg at p_not_prod + push Not at p_not_prod ext a simp only [Finset.mem_inter, Finset.notMem_empty, iff_false, not_and] @@ -225,12 +216,12 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) exact s_n_subset M hM s.property )⟩))) refine ⟨?_, ?_⟩ - . - simp [list_len_n, list_mem] + · + simp [list_len_n] simp [list_len_n] at list_mem exact list_mem - . + · simp conv => lhs @@ -255,7 +246,7 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) use (List.replicate m.natAbs m_list_choice).flatten ++ [⟨s, s_mem⟩] ++ (List.replicate (-(φ (ofMul s))).natAbs phi_list_choice).flatten ++ (List.replicate m.natAbs m_list_choice_inv).flatten refine ⟨?_, ?_⟩ - . + · simp [phi_list_choice] norm_cast rw [← s_m_eq] @@ -264,7 +255,6 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) rhs arg 1 arg 2 - -- TODO - is there a tactic that can normalize the 'ofMul' stuff for us? equals s * γ^(-(φ (ofMul s))) => rw [← ofMul_zpow] rw [← sub_eq_add_neg] @@ -278,7 +268,7 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) simp simp_rw [m_list_choice, m_list_choice_inv] by_cases m_pos: 0 < m - . + · simp_rw [m_pos] simp have m_eq_abs : |m| = m := by @@ -291,7 +281,7 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) rw [m_eq_abs] group by_cases phi_neg: (φ (ofMul s)) < 0 - . + · have phi_abs: |(φ (ofMul s))| = -φ (ofMul s) := by rw [Int.abs_eq_natAbs] omega @@ -301,7 +291,7 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) rw [gamma_list_prod] rw [m_eq_abs] group - . + · have phi_abs: |(φ (ofMul s))| = φ (ofMul s) := by rw [Int.abs_eq_natAbs] omega @@ -311,7 +301,7 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) rw [gamma_list_inv] rw [m_eq_abs] group - . + · simp_rw [m_pos] simp have neg_abs_m : |m| = - m := by @@ -324,9 +314,8 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) group rw [neg_abs_m] group - -- TODO - this can be deduplicated by_cases phi_neg: (φ (ofMul s)) < 0 - . + · have phi_abs: |(φ (ofMul s))| = -φ (ofMul s) := by rw [Int.abs_eq_natAbs] omega @@ -336,7 +325,7 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) rw [gamma_list_prod] rw [neg_abs_m] group - . + · have phi_abs: |(φ (ofMul s))| = φ (ofMul s) := by rw [Int.abs_eq_natAbs] omega @@ -346,7 +335,7 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) rw [gamma_list_inv] rw [neg_abs_m] group - . + · simp [m_list_choice, m_list_choice_inv] simp_rw [apply_ite] @@ -409,20 +398,19 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) simp [List.unattach, -List.map_subtype] have my_spec := Exists.choose_spec ((s_n_bound M hM h h.property)) have first_prop := my_spec.1 - -- wtf nth_rw 8 [← first_prop] simp have flat_list_len: nested_list.flatten.length ≤ nested_list.length • (4 * M^2) := by simp - have foo := List.sum_le_card_nsmul (l := (List.map List.length nested_list)) (4 * M^2) ?_ - . + have foo := List.sum_le_length_nsmul (l := (List.map List.length nested_list)) (4 * M^2) ?_ + · conv at foo => rhs simp exact foo - . + · intro q hq simp at hq obtain ⟨s_list, h_s_prod, s_len⟩ := hq @@ -443,8 +431,8 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) simp only [smul_eq_mul] at flat_list_len have nested_list_le_n_squared: nested_list.flatten.length ≤ M * (4 * M^2) := by apply le_mul_of_le_mul_right (b := l.length) - . omega - . omega + · omega + · omega let filled_list := nested_list.flatten ++ (List.replicate ((M * (4 * M^2)) - nested_list.flatten.length) ⟨1, hGS.one_mem⟩) @@ -484,8 +472,8 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) | base => simp [three_two_B_n, list_len_n] use [⟨(gamma_m_helper φ γ 0 ⟨s, s_mem⟩), ?_⟩] - . simp [N] - . + · simp [N] + · simp [three_two_S_n] use 0 refine ⟨by omega, ?_⟩ @@ -501,18 +489,18 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) have union_subset_n_succ: three_two_B_n (S := {s}) φ γ k ∪ (p • three_two_B_n (S := {s}) φ γ k) ⊆ three_two_B_n (S := {s}) φ γ (k + 1) := by apply Finset.union_subset - . exact b_n_subset_b_n_succ k hk - . exact smul_subset k hk p p_mem + · exact b_n_subset_b_n_succ k hk + · exact smul_subset k hk p p_mem have card_le := Finset.card_le_card (union_subset_n_succ) rw [Finset.card_union_of_disjoint ?_] at card_le - . + · simp at card_le ring_nf at card_le rw [add_comm] at card_le omega - . + · specialize disjoint_smul k hk p p_mem p_not_prod rw [Finset.inter_comm] at disjoint_smul rw [Finset.disjoint_iff_inter_eq_empty] @@ -577,13 +565,13 @@ lemma new_three_two_poly_growth (d: ℕ) (hG: HasPolynomialGrowthD S d ) (γ: G) have strict_lt: a * 4 ^ d * (↑M ^ 3) ^ d < (((2 : ℝ) ^ N)⁻¹ * 2 ^ M) := by apply helper_lemma (b := 2⁻¹) - . + · field_simp positivity - . simp - . simp - . exact m_pow_lt - . norm_num + · simp + · simp + · exact m_pow_lt + · norm_num conv at strict_lt => @@ -616,8 +604,7 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( exact S_nonempty ) use r - intro m - intro x hx + intro m x hx simp [gamma_m_helper] at hx simp [three_two_S_n, gamma_m_helper] obtain ⟨s, hs, x_eq_conj⟩ := hx @@ -640,10 +627,10 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( have my_iter := closure_iterate_mulact γ (e_i_regular_helper φ γ ⟨s, hs⟩) (n + 1) simp [three_two_S_n, gamma_m_helper] at s_n_subset have closure_eq := my_iter ?_ ?_ - . + · have x_mem_closure_range: x ∈ Subgroup.closure (Set.range fun (m : ℤ) ↦ γ ^ m * e_i_regular_helper φ γ ⟨s, hs⟩ * γ ^ (-m : ℤ)) := by by_cases m_pos: 0 < m - . + · have m_eq_natabs: m = m.natAbs := by omega apply Subgroup.subset_closure @@ -651,14 +638,14 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( use m.natAbs rw [m_eq_natabs] at x_eq_conj rw [← x_eq_conj] - . + · apply Subgroup.subset_closure simp use m rw [← closure_eq] at x_mem_closure_range apply Subgroup.closure_mono (h := ((fun (m : ℤ) ↦ γ ^ m * e_i_regular_helper φ γ ⟨s, hs⟩ * γ ^ (-m : ℤ)) '' (Set.Ioo (-(r + 1) : ℤ) (r + 1 : ℤ)))) - . + · intro p hp simp at hp simp @@ -669,7 +656,7 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( use hs rw [gamma_m_helper, zpow_neg] exact p_eq - . + · apply (Subgroup.closure_mono _) x_mem_closure_range intro z hz simp at hz @@ -677,13 +664,13 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( obtain ⟨a, ⟨a_gt, a_lt⟩, z_eq⟩ := hz use a refine ⟨⟨?_, ?_⟩, z_eq⟩ - . + · norm_cast at a_gt omega - . + · norm_cast at a_lt omega - . + · specialize s_n_subset (n + 1) (by omega) (by omega) s rfl simp [three_two_B_n] at s_n_subset rw [Finset.mem_mul] at s_n_subset @@ -694,7 +681,7 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( simp [e_i_regular_helper] rw [← prod_vals_eq] apply Subgroup.mul_mem - . + · simp at val_in_image obtain ⟨list, hlist, list_prod_eq⟩ := val_in_image rw [← list_prod_eq] @@ -713,7 +700,7 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( simp [gamma_m_helper] at e_i_eq obtain ⟨q, q_mem, e_i_eq'⟩ := e_i_eq simp [e_i_regular_helper] - . + · simp at other_val_in_image obtain ⟨list, hlist, list_prod_eq⟩ := other_val_in_image apply_fun Inv.inv at list_prod_eq @@ -735,8 +722,7 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( simp [gamma_m_helper] at e_i_eq obtain ⟨q, q_mem, e_i_eq'⟩ := e_i_eq simp [e_i_regular_helper] - . - -- TODO - 99% of this can be deduplicated + · specialize s_n_subset (-(n + 1)) (by omega) (by omega) s rfl -- Deduplicate verything after here simp [three_two_B_n] at s_n_subset @@ -749,7 +735,7 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( simp [e_i_regular_helper] rw [← prod_vals_eq] apply Subgroup.mul_mem - . + · simp at val_in_image obtain ⟨list, hlist, list_prod_eq⟩ := val_in_image rw [← list_prod_eq] @@ -768,7 +754,7 @@ lemma three_poly_poly_growth_all_s_n (d: ℕ) (hG: HasPolynomialGrowthD S d ) ( simp [gamma_m_helper] at e_i_eq obtain ⟨q, q_mem, e_i_eq'⟩ := e_i_eq simp [e_i_regular_helper] - . + · simp at other_val_in_image obtain ⟨list, hlist, list_prod_eq⟩ := other_val_in_image apply_fun Inv.inv at list_prod_eq diff --git a/Gromov/ToMathlib/Analysis/Matrix/StarNormalEigen.lean b/Gromov/ToMathlib/Analysis/Matrix/StarNormalEigen.lean index a6918d7..5dbc2a0 100644 --- a/Gromov/ToMathlib/Analysis/Matrix/StarNormalEigen.lean +++ b/Gromov/ToMathlib/Analysis/Matrix/StarNormalEigen.lean @@ -146,28 +146,33 @@ lemma star_normal_maxGenEigenspace_eq_eigenspace {A: Type*} [NormedAddCommGroup f.maxGenEigenspace k = f.eigenspace k := by apply le_antisymm; · intro x hx - aesop; + obtain ⟨w, hw⟩ := (Module.End.mem_maxGenEigenspace f k x).mp hx -- Since $f$ is star-normal, we have $\ker((f - kI)^2) = \ker(f - kI)$. have h_ker_sq_eq_ker : LinearMap.ker ((f - k • 1) ^ 2) = LinearMap.ker (f - k • 1) := by apply IsStarNormal.ker_sq_eq_ker; -- Since $f$ is star-normal, we have $f * star f = star f * f$. Therefore, $(f - k • 1) * star (f - k • 1) = star (f - k • 1) * (f - k • 1)$. have h_star_normal : (f - k • 1) * star (f - k • 1) = star (f - k • 1) * (f - k • 1) := by - simp_all +decide [ sub_mul, mul_sub, smul_sub, sub_smul ]; - simp_all +decide [ sub_eq_iff_eq_add, IsStarNormal, smul_smul ]; + simp_all +decide [ sub_mul, mul_sub, smul_sub ]; + simp_all +decide [ sub_eq_iff_eq_add, smul_smul ]; simp_all +decide [ mul_comm, sub_eq_add_neg, add_assoc, add_left_comm, add_comm ]; exact Eq.symm (star_comm_self' f); exact (isStarNormal_iff (f - k • 1)).mpr (id (Eq.symm h_star_normal)); -- By induction on $w$, we can show that $\ker((f - kI)^w) = \ker(f - kI)$ for all $w \geq 1$. have h_ker_pow_eq_ker : ∀ w ≥ 1, LinearMap.ker ((f - k • 1) ^ w) = LinearMap.ker (f - k • 1) := by intro w hw - induction' w, Nat.succ_le.mpr hw using Nat.le_induction with w hw ih; + induction' w, Nat.succ_le_iff.mpr hw using Nat.le_induction with w hw ih; · simp +decide; - · simp_all +decide [ pow_succ, LinearMap.ker_comp ]; + · simp_all +decide [ pow_succ ]; simp_all +decide [ SetLike.ext_iff, LinearMap.mem_ker ]; - intro x; specialize ih ( f x - k • x ) ; simp_all +decide [ sub_eq_iff_eq_add, pow_succ, mul_sub, sub_mul ] ; - by_cases hw : 1 ≤ w <;> aesop; - replace h_ker_pow_eq_ker := SetLike.ext_iff.mp ( h_ker_pow_eq_ker w hw ) x; aesop; - exact eq_of_sub_eq_zero h_ker_pow_eq_ker; + intro x; specialize ih ( f x - k • x ) ; simp_all +decide [ sub_eq_iff_eq_add ] ; + by_cases hw' : 1 ≤ w + · have hxker : x ∈ LinearMap.ker ((f - k • 1) ^ w) := hw + rw [h_ker_pow_eq_ker w hw'] at hxker + simpa only [Module.End.eigenspace_def] using hxker + · have hw0 : w = 0 := by omega + subst w + simp only [pow_zero, Module.End.one_apply] at hw + subst x + exact (f.eigenspace k).zero_mem · exact Module.End.eigenspace_le_maxGenEigenspace -#print axioms star_normal_maxGenEigenspace_eq_eigenspace diff --git a/Gromov/ToMathlib/Analysis/Matrix/Unitary.lean b/Gromov/ToMathlib/Analysis/Matrix/Unitary.lean index fad106a..4cbb9ee 100644 --- a/Gromov/ToMathlib/Analysis/Matrix/Unitary.lean +++ b/Gromov/ToMathlib/Analysis/Matrix/Unitary.lean @@ -12,14 +12,296 @@ direct sum of the eigenspaces of that element. public section +/-- A norm-preserving finite-dimensional endomorphism has a unitary matrix. -/ +private lemma matrix_unitary_of_norm_map {E : Type*} [NormedAddCommGroup E] + [InnerProductSpace ℂ E] [FiniteDimensional ℂ E] {ι : Type*} + [Fintype ι] [DecidableEq ι] (b : OrthonormalBasis ι ℂ E) + (f : E →ₗ[ℂ] E) (hf : ∀ x, ‖f x‖ = ‖x‖) : + LinearMap.toMatrixOrthonormal b f ∈ Matrix.unitaryGroup ι ℂ := by + let i : E →ₗᵢ[ℂ] E := { toLinearMap := f, norm_map' := hf } + let e := LinearIsometryEquiv.ofSurjective i + ((LinearMap.injective_iff_surjective).mp i.injective) + exact e.toMatrix_mem_unitaryGroup b b + +private lemma adjoint_comp_self_of_norm_map {E F : Type*} + [NormedAddCommGroup E] [InnerProductSpace ℂ E] [FiniteDimensional ℂ E] + [NormedAddCommGroup F] [InnerProductSpace ℂ F] [FiniteDimensional ℂ F] + (f : E →ₗ[ℂ] F) (hf : ∀ x, ‖f x‖ = ‖x‖) : + (LinearMap.adjoint f).comp f = 1 := by + apply LinearMap.ext + intro x + apply ext_inner_right ℂ + intro y + simp only [LinearMap.comp_apply, Module.End.one_apply, LinearMap.adjoint_inner_left] + exact (LinearMap.norm_map_iff_inner_map_map f).mp hf x y + +/-- Restriction to two orthogonal invariant summands splits the unitary centralizer. -/ +private lemma unitary_centralizer_blocks {n : ℕ} + (g : Matrix.unitaryGroup (Fin n) ℂ) + (p q : Submodule ℂ (EuclideanSpace ℂ (Fin n))) + (hcomp : IsCompl p q) (horth : p ⟂ q) + (hp : ∀ h : Subgroup.centralizer {g}, + Set.MapsTo h.val.val.toEuclideanLin p p) + (hq : ∀ h : Subgroup.centralizer {g}, + Set.MapsTo h.val.val.toEuclideanLin q q) + (hgp : Set.MapsTo g.val.toEuclideanLin p p) + (hqg : Set.MapsTo g.val.toEuclideanLin q q) : + ∃ (A : Subgroup (Matrix.unitaryGroup (Fin (Module.finrank ℂ p)) ℂ)) + (B : Subgroup (Matrix.unitaryGroup (Fin (Module.finrank ℂ q)) ℂ)), + Nonempty (Subgroup.centralizer {g} ≃* A × B) := by + have comm_g_h (h : Subgroup.centralizer {g}) : + Commute g.val.toEuclideanLin h.val.val.toEuclideanLin := by + have hh := h.property + rw [Subgroup.mem_centralizer_iff] at hh + have hg : g * h.val = h.val * g := hh g (by simp) + apply_fun (fun x => Matrix.toEuclideanLin x.val) at hg + rw [commute_iff_eq] + simpa only [Submonoid.coe_mul, Matrix.toEuclideanLin, Matrix.toLpLin_mul_same, + Module.End.mul_eq_comp] using hg + let map_first (h : Subgroup.centralizer {g}) := + h.val.val.toEuclideanLin.restrict (hp h) + + + let d := (Module.finrank ℂ ↥p) + let map_first_unitary (h: Subgroup.centralizer {g}): Matrix.unitaryGroup (Fin d) ℂ := { + val := LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥p) (map_first h) + property := by + apply matrix_unitary_of_norm_map + intro x + exact unitary_preserves_norm n h.val x.val + } + + + let map_first_hom: MonoidHom (Subgroup.centralizer {g}) _ := { + toFun := map_first_unitary + map_one' := by + have h_one : map_first 1 = 1 := by + apply LinearMap.ext + intro x + apply Subtype.ext + change Matrix.toEuclideanLin (1 : Matrix (Fin n) (Fin n) ℂ) x.val = x.val + simp [Matrix.toEuclideanLin_eq_toLin_orthonormal] + apply Subtype.ext + exact (congrArg (LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥p)) h_one).trans (map_one _) + map_mul' := by + intro x y + have h_mul : map_first (x * y) = map_first x * map_first y := by + apply LinearMap.ext + intro z + apply Subtype.ext + change Matrix.toEuclideanLin (x.val.val * y.val.val) z.val = + Matrix.toEuclideanLin x.val.val (Matrix.toEuclideanLin y.val.val z.val) + simp only [Matrix.toEuclideanLin, Matrix.toLpLin_mul_same, LinearMap.comp_apply] + apply Subtype.ext + exact (congrArg (LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥p)) h_mul).trans + (map_mul _ _ _) + } + + let first_range := map_first_hom.range + + + let map_second (h : Subgroup.centralizer {g}) := + h.val.val.toEuclideanLin.restrict (hq h) + + + let map_second_unitary (h: Subgroup.centralizer {g}): Matrix.unitaryGroup _ ℂ := { + val := LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥q) (map_second h) + property := by + apply matrix_unitary_of_norm_map + intro x + exact unitary_preserves_norm n h.val x.val + } + + let map_second_hom: MonoidHom (Subgroup.centralizer {g}) _ := { + toFun := map_second_unitary + -- TODO - deduplicate these with 'map_first_hom' + map_one' := by + have h_one : map_second 1 = 1 := by + apply LinearMap.ext + intro x + apply Subtype.ext + change Matrix.toEuclideanLin (1 : Matrix (Fin n) (Fin n) ℂ) x.val = x.val + simp [Matrix.toEuclideanLin_eq_toLin_orthonormal] + apply Subtype.ext + exact (congrArg (LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥q)) h_one).trans (map_one _) + map_mul' := by + intro x y + have h_mul : map_second (x * y) = map_second x * map_second y := by + apply LinearMap.ext + intro z + apply Subtype.ext + change Matrix.toEuclideanLin (x.val.val * y.val.val) z.val = + Matrix.toEuclideanLin x.val.val (Matrix.toEuclideanLin y.val.val z.val) + simp only [Matrix.toEuclideanLin, Matrix.toLpLin_mul_same, LinearMap.comp_apply] + apply Subtype.ext + exact (congrArg (LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥q)) h_mul).trans + (map_mul _ _ _) + } + + let prod_hom := MonoidHom.prod map_first_hom.rangeRestrict map_second_hom.rangeRestrict + let prod_iso := MulEquiv.ofBijective prod_hom (by + unfold Function.Bijective + refine ⟨?_, ?_⟩ + . + intro x y hxy + have hfirst : map_first_hom x = map_first_hom y := + congrArg (fun z => z.1.val) hxy + have hsecond : map_second_hom x = map_second_hom y := + congrArg (fun z => z.2.val) hxy + have hfirst' : map_first x = map_first y := + (LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥p)).injective + (congrArg Subtype.val hfirst) + have hsecond' : map_second x = map_second y := + (LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥q)).injective + (congrArg Subtype.val hsecond) + apply Subtype.ext + apply Subtype.ext + apply Matrix.toEuclideanLin.injective + apply LinearMap.ext + intro z + obtain ⟨zp, zq, hz, _⟩ := Submodule.existsUnique_add_of_isCompl hcomp z + rw [← hz, map_add, map_add] + exact congrArg₂ (· + ·) + (congrArg Subtype.val (DFunLike.congr_fun hfirst' zp)) + (congrArg Subtype.val (DFunLike.congr_fun hsecond' zq)) + . + intro a + have first_prop := a.fst.property + have second_prop := a.snd.property + simp only [prod_hom] + rw [MonoidHom.mem_range] at first_prop + rw [MonoidHom.mem_range] at second_prop + + obtain ⟨x, hx⟩ := first_prop + obtain ⟨y, hy⟩ := second_prop + + let map_first_x_new: p →ₗ[ℂ] (EuclideanSpace ℂ (Fin n)) := { + toFun := fun a => map_first x a + map_add' := by simp + map_smul' := by simp + } + + let map_second_y_new: ↑q →ₗ[ℂ] (EuclideanSpace ℂ (Fin n)) := { + toFun := fun a => map_second y a + map_add' := by simp + map_smul' := by simp + } + + have map_first_x_unitary : + (ContinuousLinearMap.adjoint (𝕜 := ℂ) (E := p) + (F := EuclideanSpace ℂ (Fin n)) map_first_x_new.toContinuousLinearMap).comp + map_first_x_new.toContinuousLinearMap = 1 := by + rw [← ContinuousLinearMap.norm_map_iff_adjoint_comp_self] + intro z + exact unitary_preserves_norm n x.val z.val + apply_fun (fun f => f.toLinearMap) at map_first_x_unitary + simp at map_first_x_unitary + have map_second_y_unitary : + (ContinuousLinearMap.adjoint (𝕜 := ℂ) (E := q) + (F := EuclideanSpace ℂ (Fin n)) map_second_y_new.toContinuousLinearMap).comp + map_second_y_new.toContinuousLinearMap = 1 := by + rw [← ContinuousLinearMap.norm_map_iff_adjoint_comp_self] + intro z + exact unitary_preserves_norm n y.val z.val + apply_fun (fun f => f.toLinearMap) at map_second_y_unitary + simp at map_second_y_unitary + + let new := LinearMap.ofIsCompl hcomp map_first_x_new map_second_y_new + use ⟨⟨(Matrix.toEuclideanLin.symm new), (by + simp [Matrix.mem_unitaryGroup_iff'] + apply_fun (fun f => Matrix.toEuclideanLin f) + . simp [-EmbeddingLike.apply_eq_iff_eq, new] + rw [Matrix.star_eq_conjTranspose] + simp_rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] + simp + rw [← LinearMap.toMatrix_adjoint] + simp + + + conv => + rhs + equals 1 => + ext z + simp + + + apply ofIsCompl_adjoint_comp + . exact horth + . + apply map_first_x_unitary + . intro v + exact (map_first x v).2 + . + apply map_second_y_unitary + . intro v + exact (map_second y v).2 + . intro x y hxy + simpa using hxy + )⟩, (by + rw [Subgroup.mem_centralizer_iff] + simp + apply_fun (fun f => Matrix.toEuclideanLin f.val) + simp only [] + simp_rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] + simp only [Matrix.toLin_symm, Submonoid.coe_mul] + rw [Matrix.toLin_mul (v₂ := (EuclideanSpace.basisFun (Fin n) ℂ).toBasis )] + simp + rw [Matrix.toLin_mul (v₂ := (EuclideanSpace.basisFun (Fin n) ℂ).toBasis )] + simp [new] + rw [eq_comm] + apply ofIsCompl_commute + . intro z + change x.val.val.toEuclideanLin (g.val.toEuclideanLin z.val) = + g.val.toEuclideanLin (x.val.val.toEuclideanLin z.val) + exact DFunLike.congr_fun (comm_g_h x).eq.symm z.val + . intro z + change y.val.val.toEuclideanLin (g.val.toEuclideanLin z.val) = + g.val.toEuclideanLin (y.val.val.toEuclideanLin z.val) + exact DFunLike.congr_fun (comm_g_h y).eq.symm z.val + . exact fun z => hgp z.property + . exact fun z => hqg z.property + . intro a b hab + simpa using hab + + )⟩ + + + apply Prod.ext + . + rw [Subtype.ext_iff] + conv => + rhs + rw [← hx] + simp + simp [map_first_hom, map_first_unitary] + apply LinearMap.ext + intro z + apply Subtype.ext + simp only [LinearMap.coe_restrict_apply, new, LinearEquiv.apply_symm_apply, + LinearMap.ofIsCompl_apply_left, map_first_x_new, map_first, LinearMap.coe_mk, + AddHom.coe_mk] + . + rw [Subtype.ext_iff] + conv => + rhs + rw [← hy] + simp + simp [map_second_hom, map_second_unitary] + simp [map_second] + rw [LinearMap.ext_iff] + intro z + rw [Subtype.ext_iff] + simp [new] + simp [map_second_y_new, map_second] + ) + exact ⟨map_first_hom.range, map_second_hom.range, ⟨prod_iso⟩⟩ + -- The rewrites below name their scalar field, source and target explicitly. Left implicit, -- each would leave a metavariable whose instances sit across a diamond on these spaces -- (`Submodule`'s subtype/`addCommGroup`/`module` vs the `NormedAddCommGroup`/ -- `InnerProductSpace` structures), which only reconciles at a raised `maxSynthPendingDepth`. -- Note the two rewrites in each block act on *different* spaces: the restricted eigenspace -- and the ambient `EuclideanSpace ℂ (Fin n)`. -set_option maxHeartbeats 4000000 in -set_option synthInstance.maxHeartbeats 100000 in lemma centralizer_iso {n: ℕ} [hn: NeZero n] (G: Subgroup (Matrix.unitaryGroup (Fin n) ℂ)) (g: G) (g_not: ∀ z: ℂ, g.val.val ≠ z • 1): Nonempty (IsoData g) := by @@ -84,562 +366,34 @@ lemma centralizer_iso {n: ℕ} [hn: NeZero n] (G: Subgroup (Matrix.unitaryGroup --simp_rw [Module.End.mem_invtSubmodule_iff_forall_mem_of_mem] at other_invariant - let map_first (h: Subgroup.centralizer {g.val}) := h.val.val.toEuclideanLin.restrict (Module.End.mapsTo_genEigenspace_of_comm (f := g.val.val.toEuclideanLin) (g := h.val.val.toEuclideanLin) (by - apply comm_g_h - ) k ⊤) - - - let d := (Module.finrank ℂ ↥((Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤)) - let map_first_unitary (h: Subgroup.centralizer {g.val}): Matrix.unitaryGroup (Fin d) ℂ := { - val := LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥((Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤)) (map_first h) - property := by - - - rw [Matrix.mem_unitaryGroup_iff'] - - conv => - lhs - lhs - -- TODO - why does this timeout when not inside 'conv'? - rw [Matrix.star_eq_conjTranspose] - - simp only [LinearMap.toMatrixOrthonormal_apply] - simp [] - conv => - lhs - lhs - -- TODO - why does this timeout when not inside 'conv'? - rw [← LinearMap.toMatrix_adjoint] - arg 2 - rw [← LinearMap.toMatrix_mul] - - apply_fun Matrix.toLin (stdOrthonormalBasis ℂ _).toBasis (stdOrthonormalBasis ℂ _).toBasis - rw [Matrix.toLin_toMatrix] - rw [Matrix.toLin_one] - conv => - rhs - equals 1 => - ext a - simp - - simp [map_first] - have h_unitary := Unitary.star_mul_self_of_mem h.val.property - apply_fun Matrix.toEuclideanLin at h_unitary - rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] at h_unitary - conv at h_unitary => - lhs - equals (Matrix.toEuclideanLin (star h.val.val)) ∘ₗ (Matrix.toEuclideanLin (h.val.val)) => - rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - rw [← Matrix.toLin_mul] - rw [← Matrix.toEuclideanLin_eq_toLin_orthonormal] at h_unitary - rw [Matrix.star_eq_conjTranspose] at h_unitary - rw [Matrix.toEuclideanLin_conjTranspose_eq_adjoint] at h_unitary - conv at h_unitary => - rhs - rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - equals 1 => - ext z - simp - - apply_fun (fun f => LinearMap.toContinuousLinearMap f) - simp [-EmbeddingLike.apply_eq_iff_eq] - conv => - lhs - rw [Module.End.mul_eq_comp] - rw [linearmap_comp_toContinuousLinearMap] - rw [ContinuousLinearMap.mul_def] - lhs - rw [LinearMap.adjoint_toContinuousLinearMap (𝕜 := ℂ) (E := ↥((Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤)) (F := ↥((Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤))] - - conv => - rhs - equals 1 => - ext z - simp - rw [← ContinuousLinearMap.norm_map_iff_adjoint_comp_self] - simp only [LinearMap.coe_toContinuousLinearMap'] - conv => - intro x - rw [LinearMap.restrict_apply (by - apply Module.End.mapsTo_genEigenspace_of_comm (by - apply comm_g_h - ) - )] - simp - rw [← LinearMap.coe_toContinuousLinearMap'] - - - apply_fun (fun f => LinearMap.toContinuousLinearMap f) at h_unitary - simp [-EmbeddingLike.apply_eq_iff_eq] at h_unitary - conv at h_unitary => - lhs - rw [linearmap_comp_toContinuousLinearMap] - rw [ContinuousLinearMap.mul_def] - lhs - rw [LinearMap.adjoint_toContinuousLinearMap (𝕜 := ℂ) (E := EuclideanSpace ℂ (Fin n)) (F := EuclideanSpace ℂ (Fin n))] - - conv at h_unitary => - rhs - equals 1 => - ext x - simp - rw [← ContinuousLinearMap.norm_map_iff_adjoint_comp_self] at h_unitary + let d := Module.finrank ℂ ↥((Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤) + have horth : (Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤ ⟂ + (⨆ i : ℂ, ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i) := by + change Module.End.maxGenEigenspace _ k ⟂ _ + rw [star_normal_maxGenEigenspace_eq_eigenspace (by simp)] + conv => + rhs + arg 1 intro x - specialize h_unitary x.val - exact h_unitary - . exact LinearEquiv.injective LinearMap.toContinuousLinearMap - . intro x y hxy - simpa using hxy - } - - - let map_first_hom: MonoidHom (Subgroup.centralizer {g.val}) _ := { - toFun := map_first_unitary - map_one' := by - simp [map_first_unitary, map_first] - apply_fun Matrix.toLin (stdOrthonormalBasis ℂ _).toBasis (stdOrthonormalBasis ℂ _).toBasis - . - simp - simp_rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - ext a - rfl - . intro x y hxy - simpa using hxy - map_mul' := by - intro x y - simp [map_first_unitary, map_first] - apply_fun Matrix.toLin (stdOrthonormalBasis ℂ _).toBasis (stdOrthonormalBasis ℂ _).toBasis - . - simp - rw [LinearMap.ext_iff] - intro a - rw [← LinearMap.toMatrix_mul] - simp - simp_rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - conv => - lhs - arg 1 - arg 1 - -- TODO - figure out why toLin_mul doesn't work here - equals ((Matrix.toLin (EuclideanSpace.basisFun (Fin n) ℂ).toBasis (EuclideanSpace.basisFun (Fin n) ℂ).toBasis) (↑↑↑x)) ∘ₗ (((Matrix.toLin (EuclideanSpace.basisFun (Fin n) ℂ).toBasis (EuclideanSpace.basisFun (Fin n) ℂ).toBasis) (↑↑↑y))) => - rw [← Matrix.toLin_mul] - - rfl - . intro x y hxy - simpa using hxy - } - - let first_range := map_first_hom.range - - - let map_second (h: Subgroup.centralizer {g.val}) := h.val.val.toEuclideanLin.restrict - (p := ↑((iSup fun (i : ℂ) ↦ ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i))) - (q := ↑((iSup fun (i : ℂ) ↦ ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i))) + arg 1 + intro x + rw [star_normal_maxGenEigenspace_eq_eigenspace (by simp)] + simp + intro i hi + apply eigenspace_orthogonal + · simp + · omega + obtain ⟨A, B, ⟨prod_iso⟩⟩ := unitary_centralizer_blocks g.val _ _ a_b_compl horth + (fun h => Module.End.mapsTo_genEigenspace_of_comm (comm_g_h h) k ⊤) + (fun h => by + apply LinearMap.mapsTo_biSup_of_mapsTo + intro i + exact Module.End.mapsTo_maxGenEigenspace_of_comm (comm_g_h h) i) + (Module.End.mapsTo_genEigenspace_of_comm (by simp) k ⊤) (by - intro x hx apply LinearMap.mapsTo_biSup_of_mapsTo - . - intro z - apply Module.End.mapsTo_maxGenEigenspace_of_comm - apply comm_g_h - . exact hx - ) - - - let map_second_unitary (h: Subgroup.centralizer {g.val}): Matrix.unitaryGroup _ ℂ := { - val := LinearMap.toMatrixOrthonormal (stdOrthonormalBasis ℂ ↥((iSup fun (i : ℂ) ↦ ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i))) (map_second h) - property := by - -- TODO - deduplicate this with 'map_first_unitary' - rw [Matrix.mem_unitaryGroup_iff'] - - conv => - lhs - lhs - -- TODO - why does this timeout when not inside 'conv'? - rw [Matrix.star_eq_conjTranspose] - - simp only [LinearMap.toMatrixOrthonormal_apply] - simp [] - conv => - lhs - lhs - -- TODO - why does this timeout when not inside 'conv'? - rw [← LinearMap.toMatrix_adjoint] - arg 2 - rw [← LinearMap.toMatrix_mul] - - apply_fun Matrix.toLin (stdOrthonormalBasis ℂ _).toBasis (stdOrthonormalBasis ℂ _).toBasis - rw [Matrix.toLin_toMatrix] - rw [Matrix.toLin_one] - conv => - rhs - equals 1 => - ext a - simp - - simp [map_second] - have h_unitary := Unitary.star_mul_self_of_mem h.val.property - apply_fun Matrix.toEuclideanLin at h_unitary - rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] at h_unitary - conv at h_unitary => - lhs - equals (Matrix.toEuclideanLin (star h.val.val)) ∘ₗ (Matrix.toEuclideanLin (h.val.val)) => - rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - rw [← Matrix.toLin_mul] - rw [← Matrix.toEuclideanLin_eq_toLin_orthonormal] at h_unitary - rw [Matrix.star_eq_conjTranspose] at h_unitary - rw [Matrix.toEuclideanLin_conjTranspose_eq_adjoint] at h_unitary - conv at h_unitary => - rhs - rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - equals 1 => - ext z - simp - - apply_fun (fun f => LinearMap.toContinuousLinearMap f) - simp [-EmbeddingLike.apply_eq_iff_eq] - conv => - lhs - rw [Module.End.mul_eq_comp] - rw [linearmap_comp_toContinuousLinearMap] - rw [ContinuousLinearMap.mul_def] - lhs - rw [LinearMap.adjoint_toContinuousLinearMap (𝕜 := ℂ) (E := ↥((iSup fun (i : ℂ) ↦ ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i))) (F := ↥((iSup fun (i : ℂ) ↦ ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i)))] - - conv => - rhs - equals 1 => - ext z - simp - rw [← ContinuousLinearMap.norm_map_iff_adjoint_comp_self] - simp only [LinearMap.coe_toContinuousLinearMap'] - conv => - intro x - rw [LinearMap.restrict_apply (by - apply LinearMap.mapsTo_biSup_of_mapsTo - intro z - apply Module.End.mapsTo_maxGenEigenspace_of_comm - apply comm_g_h - )] - simp - rw [← LinearMap.coe_toContinuousLinearMap'] - - - apply_fun (fun f => LinearMap.toContinuousLinearMap f) at h_unitary - simp [-EmbeddingLike.apply_eq_iff_eq] at h_unitary - conv at h_unitary => - lhs - rw [linearmap_comp_toContinuousLinearMap] - rw [ContinuousLinearMap.mul_def] - lhs - rw [LinearMap.adjoint_toContinuousLinearMap (𝕜 := ℂ) (E := EuclideanSpace ℂ (Fin n)) (F := EuclideanSpace ℂ (Fin n))] - - conv at h_unitary => - rhs - equals 1 => - ext x - simp - rw [← ContinuousLinearMap.norm_map_iff_adjoint_comp_self] at h_unitary - intro x - specialize h_unitary x.val - exact h_unitary - . exact LinearEquiv.injective LinearMap.toContinuousLinearMap - . intro x y hxy - simpa using hxy - } - - let map_second_hom: MonoidHom (Subgroup.centralizer {g.val}) _ := { - toFun := map_second_unitary - -- TODO - deduplicate these with 'map_first_hom' - map_one' := by - simp [map_second_unitary, map_second] - apply_fun Matrix.toLin (stdOrthonormalBasis ℂ _).toBasis (stdOrthonormalBasis ℂ _).toBasis - . - simp - simp_rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - ext a - rfl - . intro x y hxy - simpa using hxy - map_mul' := by - intro x y - simp [map_second_unitary, map_second] - apply_fun Matrix.toLin (stdOrthonormalBasis ℂ _).toBasis (stdOrthonormalBasis ℂ _).toBasis - . - simp - rw [LinearMap.ext_iff] - intro a - rw [← LinearMap.toMatrix_mul] - simp - simp_rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - conv => - lhs - arg 1 - arg 1 - -- TODO - figure out why toLin_mul doesn't work here - equals ((Matrix.toLin (EuclideanSpace.basisFun (Fin n) ℂ).toBasis (EuclideanSpace.basisFun (Fin n) ℂ).toBasis) (↑↑↑x)) ∘ₗ (((Matrix.toLin (EuclideanSpace.basisFun (Fin n) ℂ).toBasis (EuclideanSpace.basisFun (Fin n) ℂ).toBasis) (↑↑↑y))) => - rw [← Matrix.toLin_mul] - - rfl - . intro x y hxy - simpa using hxy - } - - let prod_hom := MonoidHom.prod map_first_hom.rangeRestrict map_second_hom.rangeRestrict - let prod_iso := MulEquiv.ofBijective prod_hom (by - unfold Function.Bijective - refine ⟨?_, ?_⟩ - . - -- TODO - this can probably be much simpler - simp [prod_hom] - intro x y hxy - simp at hxy - obtain ⟨first_eq, second_eq⟩ := hxy - - let map_first_x_new: ((Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤) →ₗ[ℂ] (EuclideanSpace ℂ (Fin n)) := { - toFun := fun a => map_first x a - map_add' := by simp - map_smul' := by simp - } - - let map_second_x_new: ↑((iSup fun (i : ℂ) ↦ ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i)) →ₗ[ℂ] (EuclideanSpace ℂ (Fin n)) := { - toFun := fun a => map_second x a - map_add' := by simp - map_smul' := by simp - } - - let x_map := LinearMap.ofIsCompl a_b_compl (map_first_x_new) (map_second_x_new) - - let map_first_y_new: ((Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤) →ₗ[ℂ] (EuclideanSpace ℂ (Fin n)) := { - toFun := fun a => map_first y a - map_add' := by simp - map_smul' := by simp - } - - let map_second_y_new: ↑((iSup fun (i : ℂ) ↦ ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i)) →ₗ[ℂ] (EuclideanSpace ℂ (Fin n)) := { - toFun := fun a => map_second y a - map_add' := by simp - map_smul' := by simp - } - - let y_map := LinearMap.ofIsCompl a_b_compl (map_first_y_new) (map_second_y_new) - - have first_eq_second: x_map = y_map := by - simp [x_map] - apply LinearMap.ofIsCompl_eq - . intro z - simp [y_map] - simp [map_first_x_new, map_first_y_new] - apply_fun (fun f => f.val) at first_eq - simp at first_eq - simp [map_first_hom, map_first_unitary] at first_eq - rw [first_eq] - . intro z - simp [y_map] - simp [map_second_x_new, map_second_y_new] - apply_fun (fun f => f.val) at second_eq - simp at second_eq - simp [map_second_hom, map_second_unitary] at second_eq - congr - - - have x_map_eq: x_map = x.val.val.toEuclideanLin := by - simp [x_map] - apply LinearMap.ofIsCompl_eq - . intro z - rfl - . intro z - rfl - - have y_map_eq: y_map = y.val.val.toEuclideanLin := by - simp [y_map] - apply LinearMap.ofIsCompl_eq - . intro z - rfl - . intro z - rfl - - - rw [x_map_eq, y_map_eq] at first_eq_second - simp at first_eq_second - exact first_eq_second - . - intro a - have first_prop := a.fst.property - have second_prop := a.snd.property - simp only [prod_hom] - rw [MonoidHom.mem_range] at first_prop - rw [MonoidHom.mem_range] at second_prop - - obtain ⟨x, hx⟩ := first_prop - obtain ⟨y, hy⟩ := second_prop - - let map_first_x_new: ((Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤) →ₗ[ℂ] (EuclideanSpace ℂ (Fin n)) := { - toFun := fun a => map_first x a - map_add' := by simp - map_smul' := by simp - } - - let map_second_y_new: ↑((iSup fun (i : ℂ) ↦ ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i)) →ₗ[ℂ] (EuclideanSpace ℂ (Fin n)) := { - toFun := fun a => map_second y a - map_add' := by simp - map_smul' := by simp - } - - have map_first_x_unitary: (ContinuousLinearMap.adjoint (𝕜 := ℂ) (E := ↥((Module.End.genEigenspace (Matrix.toEuclideanLin g.val.val) k) ⊤)) (F := EuclideanSpace ℂ (Fin n)) map_first_x_new.toContinuousLinearMap).comp map_first_x_new.toContinuousLinearMap = 1 := by - rw [← ContinuousLinearMap.norm_map_iff_adjoint_comp_self] - intro z - simp [map_first_x_new, map_first] - apply unitary_preserves_norm - - apply_fun (fun f => f.toLinearMap) at map_first_x_unitary - simp at map_first_x_unitary - - have map_second_y_unitary: (ContinuousLinearMap.adjoint (𝕜 := ℂ) (E := ↥((iSup fun (i : ℂ) ↦ ⨆ (_ : i ≠ k), Module.End.maxGenEigenspace (Matrix.toEuclideanLin g.val.val) i))) (F := EuclideanSpace ℂ (Fin n)) map_second_y_new.toContinuousLinearMap).comp map_second_y_new.toContinuousLinearMap = 1 := by - rw [← ContinuousLinearMap.norm_map_iff_adjoint_comp_self] - intro z - simp [map_second_y_new, map_second] - apply unitary_preserves_norm - - apply_fun (fun f => f.toLinearMap) at map_second_y_unitary - simp at map_second_y_unitary - - let new := LinearMap.ofIsCompl a_b_compl map_first_x_new map_second_y_new - use ⟨⟨(Matrix.toEuclideanLin.symm new), (by - simp [Matrix.mem_unitaryGroup_iff'] - apply_fun (fun f => Matrix.toEuclideanLin f) - . simp [-EmbeddingLike.apply_eq_iff_eq, new] - rw [Matrix.star_eq_conjTranspose] - simp_rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - simp - rw [← LinearMap.toMatrix_adjoint] - simp - - - conv => - rhs - equals 1 => - ext z - simp - - - apply ofIsCompl_adjoint_comp - . - rw [star_normal_maxGenEigenspace_eq_eigenspace (by simp)] - conv => - rhs - arg 1 - intro x - arg 1 - intro x - rw [star_normal_maxGenEigenspace_eq_eigenspace (by simp)] - simp - intro i hi - apply eigenspace_orthogonal - . simp - . omega - . - apply map_first_x_unitary - . intro v - exact (map_first x v).2 - . - apply map_second_y_unitary - . intro v - exact (map_second y v).2 - . intro x y hxy - simpa using hxy - )⟩, (by - rw [Subgroup.mem_centralizer_iff] - simp - apply_fun (fun f => Matrix.toEuclideanLin f.val) - simp only [] - simp_rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - simp only [Matrix.toLin_symm, Submonoid.coe_mul] - rw [Matrix.toLin_mul (v₂ := (EuclideanSpace.basisFun (Fin n) ℂ).toBasis )] - simp - rw [Matrix.toLin_mul (v₂ := (EuclideanSpace.basisFun (Fin n) ℂ).toBasis )] - simp [new] - rw [eq_comm] - apply ofIsCompl_commute - . - intro z - simp [map_first_x_new, map_first] - simp_rw [← Matrix.toEuclideanLin_eq_toLin_orthonormal] - have x_prop := x.property - rw [Subgroup.mem_centralizer_iff] at x_prop - simp at x_prop - rw [Subtype.ext_iff] at x_prop - simp at x_prop - show (Matrix.toEuclideanLin (↑↑x : Matrix (Fin n) (Fin n) ℂ)) - ((Matrix.toEuclideanLin (↑↑g : Matrix (Fin n) (Fin n) ℂ)) (↑z : EuclideanSpace ℂ (Fin n))) - = (Matrix.toEuclideanLin (↑↑g : Matrix (Fin n) (Fin n) ℂ)) - ((Matrix.toEuclideanLin (↑↑x : Matrix (Fin n) (Fin n) ℂ)) (↑z : EuclideanSpace ℂ (Fin n))) - simp only [Matrix.toEuclideanLin_apply, WithLp.ofLp_toLp, Matrix.mulVec_mulVec] - rw [x_prop] - . - intro z - simp [map_second_y_new, map_second] - simp_rw [← Matrix.toEuclideanLin_eq_toLin_orthonormal] - rw [Matrix.toEuclideanLin_apply] - rw [Matrix.toEuclideanLin_apply] - rw [Matrix.toEuclideanLin_apply] - rw [Matrix.toEuclideanLin_apply] - simp - have y_prop := y.property - rw [Subgroup.mem_centralizer_iff] at y_prop - simp at y_prop - rw [Subtype.ext_iff] at y_prop - simp at y_prop - rw [y_prop] - . - intro z - apply Module.End.mapsTo_maxGenEigenspace_of_comm - rw [commute_iff_eq] - rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - simp - . - intro x - apply LinearMap.mapsTo_biSup_of_mapsTo - . - intro z - apply Module.End.mapsTo_maxGenEigenspace_of_comm - rw [commute_iff_eq] - rw [Matrix.toEuclideanLin_eq_toLin_orthonormal] - . simp - . intro a b hab - simpa using hab - - )⟩ - - - apply Prod.ext - . - rw [Subtype.ext_iff] - conv => - rhs - rw [← hx] - simp - simp [map_first_hom, map_first_unitary] - apply LinearMap.ext - intro z - apply Subtype.ext - simp only [LinearMap.restrict_coe_apply, new, LinearEquiv.apply_symm_apply, - LinearMap.ofIsCompl_apply_left, map_first_x_new, map_first, LinearMap.coe_mk, - AddHom.coe_mk] - . - rw [Subtype.ext_iff] - conv => - rhs - rw [← hy] - simp - simp [map_second_hom, map_second_unitary] - simp [map_second] - rw [LinearMap.ext_iff] - intro z - rw [Subtype.ext_iff] - simp [new] - simp [map_second_y_new, map_second] - ) + intro i + exact Module.End.mapsTo_maxGenEigenspace_of_comm (by simp) i) -- Submodule.finrank_add_eq_of_isCompl @@ -676,9 +430,8 @@ lemma centralizer_iso {n: ℕ} [hn: NeZero n] (G: Subgroup (Matrix.unitaryGroup apply Submodule.finrank_lt at gen_eigenspace_top rw [sum_eq] at gen_eigenspace_top simp at gen_eigenspace_top - A := _ - B := _ + A := A + B := B iso := prod_iso } -#print axioms centralizer_iso diff --git a/Gromov/ToMathlib/Data/List/Infix.lean b/Gromov/ToMathlib/Data/List/Infix.lean index aa5c209..d5a4ed5 100644 --- a/Gromov/ToMathlib/Data/List/Infix.lean +++ b/Gromov/ToMathlib/Data/List/Infix.lean @@ -167,4 +167,3 @@ lemma list_adjacent_elements {A: Type*} (l: List A) (p: A → Bool) (n : ℕ): rw [Nat.one_le_div_iff hn] omega -#print axioms list_adjacent_elements diff --git a/Gromov/ToMathlib/GroupTheory/Closure.lean b/Gromov/ToMathlib/GroupTheory/Closure.lean index 58aa14c..d01b3f7 100644 --- a/Gromov/ToMathlib/GroupTheory/Closure.lean +++ b/Gromov/ToMathlib/GroupTheory/Closure.lean @@ -12,7 +12,6 @@ public section open scoped Pointwise Finset -set_option maxHeartbeats 300000 in lemma closure_iterate_mulact {T: Type*} [Group T] [DecidableEq T] (a b: T) (n: ℤ) (conj_in: (a^n * b * a^(-n)) ∈ (Subgroup.closure (G := T) (Set.image (fun (m: ℤ) => a^m * b * a^(-m)) (Set.Ioo (-n.natAbs) n.natAbs)))) (conj_inv_in: (a^(-n) * b * a^(n)) ∈ (Subgroup.closure (G := T) (Set.image (fun (m: ℤ) => a^m * b * a^(-m)) (Set.Ioo (-n.natAbs) n.natAbs)))) : @@ -316,7 +315,6 @@ lemma closure_iterate_mulact {T: Type*} [Group T] [DecidableEq T] (a b: T) (n: | inv y hy y_mem => apply Subgroup.inv_mem _ y_mem -#print axioms closure_iterate_mulact namespace Subgroup @@ -390,7 +388,6 @@ lemma closure_set_union_normal {G: Type*} [Group G] (S: Set G) (N: Subgroup G) ( simp group -#print axioms closure_set_union_normal -- TODO - deduplicate with with 'mem_S_prod_list' lemma mem_closure_prod_list {G: Type*} [Group G] (S: Set G) (S_eq_Sinv: S = S⁻¹) (x: G) (hx: x ∈ Subgroup.closure S): ∃ l: List S, l.unattach.prod = x := by diff --git a/Gromov/ToMathlib/LinearAlgebra/Matrix/Det.lean b/Gromov/ToMathlib/LinearAlgebra/Matrix/Det.lean index f9574a1..ce1739e 100644 --- a/Gromov/ToMathlib/LinearAlgebra/Matrix/Det.lean +++ b/Gromov/ToMathlib/LinearAlgebra/Matrix/Det.lean @@ -7,17 +7,12 @@ public import Gromov.ToMathlib.LinearAlgebra.Matrix.ToMatrix /-! # Determinants of matrices of bilinear forms -General-purpose material extracted from the Gromov development, destined for mathlib. +Basis changes preserve determinant ratios; positive semidefinite comparison +controls determinants of positive definite matrices. -/ public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false - open scoped Finset open scoped Pointwise @@ -50,19 +45,19 @@ theorem LinearMap.toMatrix₂_det_basis_change {M ι κ : Type*} [AddCommGroup M Matrix.det_mul, Matrix.det_mul, Matrix.det_transpose, ← Module.Basis.det_apply] ring - open MatrixOrder in -lemma matrix_det_montone {n: Type*} [Fintype n] [DecidableEq n] (A B: Matrix n n ℝ) (hb: B.PosDef) (hab: (A - B).PosSemidef): B.det ≤ A.det := by - - have invert_sqrt: Invertible (CFC.sqrt B) := by +lemma matrix_det_montone {n : Type*} [Fintype n] [DecidableEq n] + (A B : Matrix n n ℝ) (hb : B.PosDef) (hab : (A - B).PosSemidef) : + B.det ≤ A.det := by + have invert_sqrt : Invertible (CFC.sqrt B) := by apply Matrix.invertibleOfIsUnitDet rw [Matrix.PosSemidef.det_sqrt hb.posSemidef] simp rw [← ne_eq, Real.sqrt_ne_zero] - . grind [hb.det_pos] - . grind [hb.det_pos] + · grind [hb.det_pos] + · grind [hb.det_pos] - have det_prod_eq: A.det = B.det * ((CFC.sqrt B)⁻¹ * (A - B) * (CFC.sqrt B)⁻¹ + 1).det := by + have det_prod_eq : A.det = B.det * ((CFC.sqrt B)⁻¹ * (A - B) * (CFC.sqrt B)⁻¹ + 1).det := by conv => lhs arg 1 @@ -73,7 +68,7 @@ lemma matrix_det_montone {n: Type*} [Fintype n] [DecidableEq n] (A B: Matrix n n rw [Matrix.det_mul] rw [← mul_assoc, ← mul_assoc] rw [Matrix.det_mul] - ring + ring_nf rw [hb.posSemidef.det_sqrt] simp only [RCLike.sqrt_real] rw [Real.sq_sqrt (by grind [hb.det_pos])] @@ -93,7 +88,7 @@ lemma matrix_det_montone {n: Type*} [Fintype n] [DecidableEq n] (A B: Matrix n n rw [det_prod_eq] rw [le_mul_iff_one_le_right] - . + · apply matrix_psd_det_one rw [hb.posSemidef.inv_sqrt] have foo := (CFC.sqrt_nonneg B⁻¹) @@ -102,17 +97,17 @@ lemma matrix_det_montone {n: Type*} [Fintype n] [DecidableEq n] (A B: Matrix n n nth_rw 2 [← foo.isHermitian.eq] apply Matrix.PosSemidef.mul_mul_conjTranspose_same exact hab - . apply hb.det_pos + · apply hb.det_pos --- TODO - upstream. Mathlib only has `Finset.sum_biUnion` (which needs `PairwiseDisjoint`) --- and the `ENNReal` `tsum` versions. -theorem Finset.sum_biUnion_le {κ α : Type*} [DecidableEq α] {s: Finset κ} {t: κ → Finset α} - {f: α → ℝ} (hf: ∀ x, 0 ≤ f x): ∑ x ∈ s.biUnion t, f x ≤ ∑ i ∈ s, ∑ x ∈ t i, f x := by +/-- The sum over a finite union is bounded by the sum over its possibly +overlapping members when all summands are nonnegative. -/ +theorem Finset.sum_biUnion_le {κ α : Type*} [DecidableEq α] {s : Finset κ} {t : κ → Finset α} + {f : α → ℝ} (hf : ∀ x, 0 ≤ f x) : ∑ x ∈ s.biUnion t, f x ≤ ∑ i ∈ s, ∑ x ∈ t i, f x := by classical induction s using Finset.induction with | empty => simp | insert a s ha ih => rw [Finset.biUnion_insert, Finset.sum_insert ha] have hunion := Finset.sum_union_inter (s₁ := t a) (s₂ := s.biUnion t) (f := f) - have hnn: 0 ≤ ∑ x ∈ t a ∩ s.biUnion t, f x := Finset.sum_nonneg fun x _ => hf x + have hnn : 0 ≤ ∑ x ∈ t a ∩ s.biUnion t, f x := Finset.sum_nonneg fun x _ => hf x linarith diff --git a/Gromov/ToMathlib/LinearAlgebra/Matrix/PosDef.lean b/Gromov/ToMathlib/LinearAlgebra/Matrix/PosDef.lean index f074374..76cb7dc 100644 --- a/Gromov/ToMathlib/LinearAlgebra/Matrix/PosDef.lean +++ b/Gromov/ToMathlib/LinearAlgebra/Matrix/PosDef.lean @@ -29,7 +29,7 @@ lemma matrix_psd_det_one {n: Type*} [Fintype n] [DecidableEq n] (A: Matrix n n rw [← Matrix.diagonal_one'] rw [Matrix.diagonal_add] simp - apply Finset.one_le_prod + apply Finset.one_le_prod₀ intro i _ have foo := ha.eigenvalues_nonneg grind diff --git a/Gromov/Unipotent/Commutator.lean b/Gromov/Unipotent/Commutator.lean index 394e1e4..9a0f3b3 100644 --- a/Gromov/Unipotent/Commutator.lean +++ b/Gromov/Unipotent/Commutator.lean @@ -17,9 +17,6 @@ public import Gromov.ToMathlib.Order.Prod.Lex public section -set_option linter.style.longLine false -set_option linter.style.commandStart false -set_option linter.style.cdot false open scoped commutatorElement IsMulCommutative Pointwise @@ -45,7 +42,7 @@ lemma iterate_comm_set_eq_fold {G: Type*} [Group G] [DecidableEq G] (S: Finset G ext g simp refine ⟨?_, ?_⟩ - . + · intro h obtain ⟨s, s_mem, ⟨x, x_mem, comm_eq⟩⟩ := h rw [← Finset.mem_coe] at x_mem @@ -56,12 +53,12 @@ lemma iterate_comm_set_eq_fold {G: Type*} [Group G] [DecidableEq G] (S: Finset G refine ⟨t_mem, ?_⟩ use (⟨s, s_mem⟩ :: l) refine ⟨?_, ?_⟩ - . grind - . + · grind + · simp rw [← comm_eq] rw [← l_fold_eq] - . + · intro h obtain ⟨t, t_mem, l, l_len, l_fold_eq⟩ := h have l_len_eq := l_len @@ -84,16 +81,15 @@ lemma iterate_comm_set_eq_fold {G: Type*} [Group G] [DecidableEq G] (S: Finset G use List.foldr (fun x b ↦ ⁅b, x⁆) t tail.unattach refine ⟨?_, ?_⟩ - . + · rw [← Finset.mem_coe] rw [ih] simp use t refine ⟨t_mem, ?_⟩ use tail - . exact l_fold_eq + · exact l_fold_eq -#print axioms iterate_comm_set_eq_fold lemma comm_prod {G: Type*} [Group G] (x y z: G): ⁅x * y, z⁆ = ⁅x, ⁅y, z⁆⁆ * ⁅y, z⁆ * ⁅x, z⁆ := by @@ -129,12 +125,12 @@ lemma double_comm_mem {G: Type*} [DecidableEq G] [Group G] (S: Finset G) {l': G simp apply Subgroup.mem_closure_of_mem apply Set.mem_union_right - simp [mem_lowerCentralSeries_succ_iff] + simp apply Subgroup.mem_closure_of_mem simp use ⁅g'.val, l'⁆ refine ⟨?_, ?_⟩ - . + · rw [← Subgroup.inv_mem_iff] simp @@ -142,27 +138,26 @@ lemma double_comm_mem {G: Type*} [DecidableEq G] [Group G] (S: Finset G) {l': G simp use l' refine ⟨?_, ?_⟩ - . rw [ih] + · rw [ih] simp at l'_mem cases l'_mem - . + · rename_i l'_mem_forward apply Subgroup.mem_closure_of_mem apply Set.mem_union_left exact l'_mem_forward - . rename_i l'_mem_inv + · rename_i l'_mem_inv rw [← Subgroup.closure_inv] apply Subgroup.mem_closure_of_mem simp left exact l'_mem_inv - . + · use g' - . + · use l'⁻¹ -set_option maxHeartbeats 400000 in lemma triple_comm_mem {G: Type*} [Group G] [DecidableEq G] (S: Finset G) {l': G} (n: ℕ) (ih: (⊤ : Subgroup G).lowerCentralSeries n = Subgroup.closure (iterate_comm_set (S ∪ S⁻¹) n ∪ ↑((⊤ : Subgroup G).lowerCentralSeries (n + 1)))) (g': ↑(S ∪ S⁻¹)) (l'_mem_comm: l' ∈ iterate_comm_set (S ∪ S⁻¹) n ∨ l'⁻¹ ∈ iterate_comm_set (S ∪ S⁻¹) n): ⁅l'⁻¹, ⁅g'.val, l'⁆⁆ * ⁅g'.val, l'⁆ ∈ Subgroup.closure (iterate_comm_set (S ∪ S⁻¹) (n + 1) ∪ ↑((⊤ : Subgroup G).lowerCentralSeries (n + 1 + 1))) := by @@ -171,36 +166,36 @@ lemma triple_comm_mem {G: Type*} [Group G] [DecidableEq G] (S: Finset G) {l': G} cases l'_mem_comm - . + · rw [← Subgroup.inv_mem_iff] simp rename_i l'_mem - . apply Subgroup.mul_mem - . + · apply Subgroup.mul_mem + · apply Subgroup.mem_closure_of_mem apply Set.mem_union_left simp [iterate_comm_set] use g' refine ⟨by simpa using g'_prop, ?_⟩ use l' - . + · rw [← Subgroup.inv_mem_iff] simp apply double_comm_mem - . exact ih - . simp [l'_mem] + · exact ih + · simp [l'_mem] - . + · rename_i l'_inv_mem - . apply Subgroup.mul_mem - . + · apply Subgroup.mul_mem + · apply double_comm_mem exact ih simp [l'_inv_mem] - . + · rw [← Subgroup.inv_mem_iff] simp conv => @@ -211,7 +206,7 @@ lemma triple_comm_mem {G: Type*} [Group G] [DecidableEq G] (S: Finset G) {l': G} rw [comm_first_inv] simp apply Subgroup.mul_mem - . + · have foo := double_comm_mem (l' := l'⁻¹ ) _ _ ih g' (by simp left @@ -219,7 +214,7 @@ lemma triple_comm_mem {G: Type*} [Group G] [DecidableEq G] (S: Finset G) {l': G} ) simp at foo exact foo - . + · rw [← Subgroup.inv_mem_iff] simp apply Subgroup.mem_closure_of_mem @@ -231,11 +226,9 @@ lemma triple_comm_mem {G: Type*} [Group G] [DecidableEq G] (S: Finset G) {l': G} use l'⁻¹ -#print axioms triple_comm_mem -- Lemma 13.44. in https://www.math.ucdavis.edu/~kapovich/EPR/ggt.pdf -- Note - the book seems to implicitly assume that the generating set is symmetric -set_option maxHeartbeats 400000 in lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Finset G) (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ): (⊤ : Subgroup G).lowerCentralSeries n = Subgroup.closure ((iterate_comm_set (S ∪ S⁻¹) n) ∪ ↑((⊤ : Subgroup G).lowerCentralSeries (n + 1))) := by induction n with @@ -247,9 +240,9 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins | succ n ih => ext a refine ⟨?_, ?_⟩ - . + · intro ha - rw [mem_lowerCentralSeries_succ_iff] at ha + rw [Subgroup.mem_lowerCentralSeries_succ_iff] at ha apply (Subgroup.closure_le _).mp ?_ ha simp intro p hp @@ -266,7 +259,7 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins rw [comm_prod] have x_comm_mem: ⁅x.val, g⁆ ∈ (⊤ : Subgroup G).lowerCentralSeries (n + 1 + 1) := by - rw [mem_lowerCentralSeries_succ_iff] + rw [Subgroup.mem_lowerCentralSeries_succ_iff] apply Subgroup.mem_closure_of_mem simp use x @@ -274,8 +267,8 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins apply Subgroup.mul_mem - . apply Subgroup.mul_mem - . + · apply Subgroup.mul_mem + · conv => arg 2 @@ -284,25 +277,25 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins apply Subgroup.mul_mem - . + · apply Subgroup.mem_closure_of_mem apply Set.mem_union_right simp apply Subgroup.Normal.conj_mem - . infer_instance - . exact x_comm_mem - . + · infer_instance + · exact x_comm_mem + · apply Subgroup.mem_closure_of_mem apply Set.mem_union_right simp only [SetLike.mem_coe] rw [Subgroup.inv_mem_iff] apply x_comm_mem - . + · apply Subgroup.mem_closure_of_mem apply Set.mem_union_right simp only [SetLike.mem_coe] apply x_comm_mem - . + · obtain ⟨g_list, g_prod⟩ := new_mem_S_prod_list (S := S) (x := g) (by simp [hS]) --clear ha a p_eq_comm p c_prod c_mem c x_comm_mem rw [← g_prod] @@ -319,20 +312,20 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins by_cases g_list_zero: g_list.length = 0 - . simp at g_list_zero + · simp at g_list_zero simp [g_list_zero] - . + · simp at g_list_zero by_cases l_len_ne_zero: l.unattach.length = 0 - . have l_empty: l.unattach = [] := by + · have l_empty: l.unattach = [] := by exact List.eq_nil_iff_length_eq_zero.mpr l_len_ne_zero simp [l_empty] by_cases both_eq_one: g_list.length = 1 ∧ l.unattach.length = 1 - . + · obtain ⟨g_len_one, l_len_one⟩ := both_eq_one obtain ⟨g', h_g'⟩ := List.length_eq_one_iff.mp g_len_one obtain ⟨l', h_l'⟩ := List.length_eq_one_iff.mp l_len_one @@ -369,7 +362,7 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins rw [not_and_or] at both_eq_one cases both_eq_one - . rename_i g_len_ne_one + · rename_i g_len_ne_one have g_len_ne_zero: g_list.length ≠ 0 := by simp @@ -385,16 +378,16 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins rw [List.unattach_append] simp rw [comm_prod_right] - . apply Subgroup.mul_mem - . apply Subgroup.mul_mem - . + · apply Subgroup.mul_mem + · apply Subgroup.mul_mem + · have prev := hk k (by simp) l (List.take (g_list.length - 1) g_list) (by simp omega ) exact prev - . + · rw [← Subgroup.inv_mem_iff] @@ -409,10 +402,10 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins simp at hx obtain ⟨x_mem, x_subtype_mem⟩ := hx cases x_mem - . rename_i x_mem_forward + · rename_i x_mem_forward apply Subgroup.mem_closure_of_mem grind - . rename_i x_mem_inv + · rename_i x_mem_inv rw [← Subgroup.closure_inv] apply Subgroup.mem_closure_of_mem simp @@ -421,7 +414,7 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins exact Subgroup.commutator_mem_commutator (Subgroup.commutator_mem_commutator l_prod_mem (Subgroup.mem_top _)) (Subgroup.mem_top _) - . + · have prev := hk (l.length + 1) (by omega) l [(g_list.getLast g_list_zero)] (by simp @@ -430,7 +423,7 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins simp at prev exact prev - . + · rename_i l_len_ne_one simp at l_len_ne_one have l_ne_zero: l.length ≠ 0 := by @@ -447,8 +440,8 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins rw [comm_prod] simp at h_len apply Subgroup.mul_mem - . apply Subgroup.mul_mem - . + · apply Subgroup.mul_mem + · rw [← Subgroup.inv_mem_iff] simp apply Subgroup.mem_closure_of_mem @@ -460,10 +453,10 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins have l_prop := (l.getLast (by simpa using l_ne_zero)).prop rw [Set.mem_union] at l_prop cases l_prop - . rename_i l_prop_forward + · rename_i l_prop_forward apply Subgroup.mem_closure_of_mem grind - . rename_i l_prop_inv + · rename_i l_prop_inv rw [← Subgroup.closure_inv] simp apply Subgroup.mem_closure_of_mem @@ -471,12 +464,12 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins exact Subgroup.commutator_mem_commutator (Subgroup.commutator_mem_commutator last_mem (Subgroup.mem_top _)) (Subgroup.mem_top _) - . + · have foo := hk (g_list.length + 1) (by omega) [l.getLast (by simpa using l_ne_zero)] g_list (by simp) simp at foo exact foo - . + · have foo := hk k (by simp) (List.take (l.length - 1) l) g_list (by simp omega @@ -484,7 +477,7 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins exact foo intro ha - rw [mem_lowerCentralSeries_succ_iff] + rw [Subgroup.mem_lowerCentralSeries_succ_iff] have closure_le: (Subgroup.closure ((iterate_comm_set (S ∪ S⁻¹) (n + 1)) ∪ ↑((⊤ : Subgroup G).lowerCentralSeries (n + 1 + 1)))) ≤ (Subgroup.closure {x | ∃ p ∈ (⊤ : Subgroup G).lowerCentralSeries n, ∃ q ∈ (⊤ : Subgroup G), ⁅p, q⁆ = x}) := by @@ -492,7 +485,7 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins intro x hx simp at hx cases hx - . + · rename_i x_mem_comm apply Subgroup.mem_closure_of_mem simp @@ -501,19 +494,18 @@ lemma lower_central_generates_succ {G: Type*} [Group G] [DecidableEq G] (S: Fins obtain ⟨s, s_mem, ⟨c, c_mem, c_comm⟩⟩ := x_mem_comm use c refine ⟨?_, ?_⟩ - . apply Subgroup.mem_closure_of_mem + · apply Subgroup.mem_closure_of_mem grind - . use s - . + · use s + · rename_i x_mem_lower_two have x_mem_lower_succ: x ∈ (⊤ : Subgroup G).lowerCentralSeries (n + 1) := Subgroup.commutator_le_left _ _ x_mem_lower_two - rw [mem_lowerCentralSeries_succ_iff] at x_mem_lower_succ + rw [Subgroup.mem_lowerCentralSeries_succ_iff] at x_mem_lower_succ simpa using x_mem_lower_succ apply closure_le ha -#print axioms lower_central_generates_succ diff --git a/Gromov/Unipotent/FG.lean b/Gromov/Unipotent/FG.lean index 6a68e4d..f39faa3 100644 --- a/Gromov/Unipotent/FG.lean +++ b/Gromov/Unipotent/FG.lean @@ -12,9 +12,6 @@ the supporting transfer lemmas along homomorphisms. public section -set_option linter.style.longLine false -set_option linter.style.commandStart false -set_option linter.style.cdot false open scoped commutatorElement IsMulCommutative Pointwise @@ -38,10 +35,10 @@ lemma iterate_comm_generates (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ): grw [closure_le] apply Subgroup.closure_le_normalClosure | succ n ih => - simp [lowerCentralSeries] + simp rw [le_antisymm_iff] refine ⟨?_, ?_⟩ - . + · simp [Subgroup.normalClosure] intro y hy simp [Group.conjugatesOfSet, iterate_comm_set] at hy @@ -50,10 +47,10 @@ lemma iterate_comm_generates (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ): obtain ⟨x, x_mem⟩ := c_comm rw [← x_mem] apply Subgroup.Normal.conj_mem - . infer_instance - . + · infer_instance + · apply Subgroup.commutator_mem_commutator - . + · rw [← ih] apply Subgroup.mem_closure_of_mem simp [Group.conjugatesOfSet] @@ -62,8 +59,8 @@ lemma iterate_comm_generates (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ): simp [conjugatesOf] use 1 simp - . simp - . + · simp + · have image_commute: ∀ s ∈ S, ∀ g ∈ (iterate_comm_set (S) n), QuotientGroup.mk' (((Subgroup.normalClosure (iterate_comm_set (S) (n + 1))))) (s * g) = QuotientGroup.mk' (((Subgroup.normalClosure (iterate_comm_set (S) (n + 1))))) (g * s) := by intro s hs g hg @@ -80,13 +77,13 @@ lemma iterate_comm_generates (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ): simp only [conjugatesOf] use g * s * g⁻¹ * s⁻¹ refine ⟨?_, ?_⟩ - . simp [iterate_comm_set] + · simp [iterate_comm_set] use s refine ⟨by simp [hs], ?_⟩ use g refine ⟨hg, ?_⟩ simp [Bracket.bracket] - . + · simp use s⁻¹ * g⁻¹ group @@ -113,7 +110,7 @@ lemma iterate_comm_generates (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ): -- TODO - figure out how to get the 'induction' tactic working here apply Subgroup.closure_induction (p := fun y hy => a⁻¹ * y⁻¹ * (a * y) ∈ Subgroup.normalClosure (iterate_comm_set (S) (n + 1))) (hx := b_mem_top) - . + · intro s hs have comm := image_commute s hs a a_mem simp at comm @@ -122,24 +119,24 @@ lemma iterate_comm_generates (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ): rw [QuotientGroup.eq] at comm simp at comm exact comm - . simp - . intro y hy z hz y_mem z_mem + · simp + · intro y hy z hz y_mem z_mem simp conv => arg 2 equals (a⁻¹ * hy⁻¹ * a * hy) * (hy⁻¹ * a⁻¹ * y⁻¹ * a * y * hy) => group apply Subgroup.mul_mem - . group + · group group at z_mem exact z_mem - . + · have foo := (Subgroup.normalClosure_normal).conj_mem _ y_mem hy⁻¹ simp at foo group at foo group exact foo - . + · intro y hy y_mem rw [← Subgroup.inv_mem_iff] simp @@ -158,7 +155,7 @@ lemma iterate_comm_generates (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ): rw [ih] at normal_le_center simp have a_mem_center := @normal_le_center a⁻¹ ?_ - . + · rw [Subgroup.mem_center_iff] at a_mem_center specialize a_mem_center (QuotientGroup.mk b⁻¹) rw [← QuotientGroup.mk_inv] at a_mem_center @@ -170,14 +167,13 @@ lemma iterate_comm_generates (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ): group at a_mem_center group exact a_mem_center - . simp + · simp use a simp exact QuotientGroup.mk_surjective -#print axioms iterate_comm_generates -- Lemma 13.55 from https://www.math.ucdavis.edu/~kapovich/EPR/ggt.pdf lemma comm_trivial_implies_nilpotent {G: Type*} [DecidableEq G] [Group G] (S: Finset G) (hS: Subgroup.closure (S: Set G) = ⊤) (n: ℕ) (h_comm: iterate_comm_set (S) (n) = {1}): @@ -201,8 +197,8 @@ lemma normal_comm_mem {G: Type*} [Group G] {N: Subgroup G} (N_normal: N.Normal) equals a * (b * a⁻¹ * b⁻¹) => group apply Subgroup.mul_mem - . exact ha - . exact conj_mem + · exact ha + · exact conj_mem -- TODO - cleanup and upstream to mathlib @@ -253,16 +249,16 @@ lemma fg_extension {A: Type*} [Group A] (N: Subgroup A) [N.Normal] (hN: N.FG) (h rw [SQ_eq] at hS_Q use S_N ∪ SQ_out refine ⟨?_, ?_⟩ - . + · simp [SQ_out] rw [Subgroup.closure_union] simp [hS_N] ext a simp by_cases mem_N: a ∈ N - . apply Subgroup.mem_sup_left + · apply Subgroup.mem_sup_left exact mem_N - . + · let a_map: (A ⧸ N) := a have a_mem_top: a_map ∈ (⊤ : Subgroup (A ⧸ N)) := by simp @@ -277,14 +273,14 @@ lemma fg_extension {A: Type*} [Group A] (N: Subgroup A) [N.Normal] (hN: N.FG) (h have a_eq := hk.2 rw [QuotientGroup.eq] at a_eq rw [← Subgroup.mul_mem_cancel_left (x := k⁻¹)] - . + · apply Subgroup.mem_sup_left exact a_eq - . apply Subgroup.mem_sup_right + · apply Subgroup.mem_sup_right simp exact hk.1 - . simp + · simp lemma fg_domain_of_ker_range {A B: Type*} [Group A] [Group B] (f : A →* B) (hA: Subgroup.FG f.ker) (hB: Subgroup.FG f.range): Group.FG A := by have new_fg := fg_extension (f.ker) hA @@ -300,7 +296,6 @@ lemma Group.FG.of_mulEquiv {G H : Type*} [Group G] [Group H] (e : G ≃* H) (h : haveI := h Group.fg_of_surjective (f := e.toMonoidHom) e.surjective -set_option maxHeartbeats 5000000 in lemma fg_of_subgroup_fg_nilpotent {A: Type*} [DecidableEq A] [Group A] [Group.IsNilpotent A] (A_fg: Group.FG A) (H: Subgroup A): H.FG := by classical revert H @@ -320,9 +315,6 @@ lemma fg_of_subgroup_fg_nilpotent {A: Type*} [DecidableEq A] [Group A] [Group.Is have comm_eq := Subgroup.lowerCentralSeries_succ (⊤ : Subgroup A) n rw [← hn] at comm_eq rw [Subgroup.lowerCentralSeries_nilpotencyClass] at comm_eq - conv at comm_eq => - rhs - simp rw [eq_comm, Subgroup.commutator_eq_bot_iff_le_centralizer] at comm_eq simp [Subgroup.centralizer_univ] at comm_eq have n_fg: (Subgroup.lowerCentralSeries (⊤ : Subgroup A) n).FG := by @@ -366,7 +358,7 @@ lemma fg_of_subgroup_fg_nilpotent {A: Type*} [DecidableEq A] [Group A] [Group.Is rw [← Group.fg_iff_subgroup_fg] apply fg_domain_of_ker_range ((QuotientGroup.mk' ((⊤: Subgroup A).lowerCentralSeries n)).comp H.subtype) - . + · -- The kernel is `N.subgroupOf H = (H ⊓ N).subgroupOf H`, which is the same abstract group as -- `(H ⊓ N).subgroupOf N` — the version we proved FG using that `N` is abelian. rw [← MonoidHom.comap_ker, QuotientGroup.ker_mk', Subgroup.comap_subtype, @@ -375,7 +367,7 @@ lemma fg_of_subgroup_fg_nilpotent {A: Type*} [DecidableEq A] [Group A] [Group.Is ((Subgroup.subgroupOfEquivOfLe inf_le_right).trans (Subgroup.subgroupOfEquivOfLe inf_le_left).symm) ((Group.fg_iff_subgroup_fg _).mpr h_inf_fg) - . + · -- The range is the image of `H` in `A ⧸ Cⁿ A`, which is FG by the induction hypothesis. rw [MonoidHom.range_comp, Subgroup.range_subtype] exact ih (Subgroup.map (QuotientGroup.mk' _) H) diff --git a/Gromov/Unipotent/GammaN.lean b/Gromov/Unipotent/GammaN.lean index b60722b..126c821 100644 --- a/Gromov/Unipotent/GammaN.lean +++ b/Gromov/Unipotent/GammaN.lean @@ -11,9 +11,6 @@ public import Gromov.Unipotent.FG public section -set_option linter.style.longLine false -set_option linter.style.commandStart false -set_option linter.style.cdot false open scoped commutatorElement IsMulCommutative Pointwise @@ -112,9 +109,252 @@ theorem log_pow_sq_lt_of_lt (M p q K : ℕ) (hp : 0 < p) def gamma_conj_bound {H: Type*} [DecidableEq H] [Group H] {N': Subgroup H} (gamma: MulAut N') := ∀ k: ℕ, (0 < k) → ∀ g, ∃ p q: ℕ, 0 < p ∧ ∀ b: ℕ, 0 < b → ∀ a: ℕ, (0 < a) → (a < b) → ((Finset.image (fun x ↦ (List.map (fun (i: ↥(Finset.Ico a b)) ↦ (gamma)^[k * ↑i] g) x.toList).prod)) (Finset.Ico a b).attach.powerset).card ≤ p * (b^q) * (b - a)^q -set_option maxHeartbeats 1000000 in -set_option synthInstance.maxHeartbeats 40000 in -lemma exists_gamma_n_unipotent_center_N' {H: Type*} [DecidableEq H] [Group H] {N': Subgroup H} [N'_normal: N'.Normal] (N'_nilpotent: Group.IsNilpotent N') (hN': Subgroup.FG N') (gamma: MulAut N') +/-- The finite-free abelian part of the argument, separated from torsion lifting. -/ +private lemma free_abelian_gamma_unipotent {A : Type*} [CommGroup A] [DecidableEq A] + [Module.Finite ℤ (Additive A)] [Module.Free ℤ (Additive A)] + (gamma_lift : MulAut A) (r : ℕ) (hr : 0 < r) + (gamma_lift_conj : ∀ k : ℕ, 0 < k → ∀ g : A, ∃ p q : ℕ, 0 < p ∧ + ∀ b : ℕ, 0 < b → ∀ a : ℕ, 0 < a → a < b → + (Finset.image (fun x ↦ (List.map (fun i : ↥(Finset.Ico a b) ↦ + gamma_lift^[k * ↑i] g) x.toList).prod) (Finset.Ico a b).attach.powerset).card ≤ + p * b ^ q * (b - a) ^ q) : + ∃ a, 0 < a ∧ ∀ p : ℕ, 0 < p → ∃ n, ∀ g : A, + (fun x ↦ x * gamma_lift^[a * r * p] x⁻¹)^[n] g = 1 := by + classical + rcases subsingleton_or_nontrivial A with hA | hA + · exact ⟨1, by simp, fun p _ => ⟨1, fun g => Subsingleton.elim _ _⟩⟩ + let gamma_add := gamma_lift.toAdditive.toAddMonoidHom.toIntLinearMap + let B := (Module.finBasis ℤ (Additive (A))) + let gamma_matrix := gamma_add.toMatrix B B + have invertible_gamma: Invertible gamma_matrix := { + invOf := ((gamma_lift.toAdditive).symm.toAddMonoidHom).toIntLinearMap.toMatrix B B + invOf_mul_self := by + simp [gamma_matrix, gamma_add] + rw [← LinearMap.toMatrix_mul] + rw [← toIntLinearMap_comp_mul] + simp + mul_invOf_self := by + simp [gamma_matrix, gamma_add] + rw [← LinearMap.toMatrix_mul] + rw [← toIntLinearMap_comp_mul] + simp + } + + let dim := Module.finrank ℤ (Additive (A)) + let equiv (v: Fin _ → ℤ) := (Finsupp.linearEquivFunOnFinite ℤ _ (Fin dim)).symm v + let remap (v: Fin _ → ℤ) := Finsupp.linearCombination _ B (equiv v) + + have gamma_matrix_mulVec: ∀ v: (Fin dim) → ℤ , remap ((gamma_matrix).mulVec (equiv v)) = Additive.ofMul (gamma_lift (Additive.toMul (remap v))) := by + intro v + unfold gamma_matrix + rw [← Module.Basis.repr_linearCombination (v := (equiv v)) (b := B)] + rw [LinearMap.toMatrix_mulVec_repr] + simp [remap, gamma_add, equiv] + + + have gamma_matrix_mulVec_pow: ∀ n: ℕ, ∀ v: (Fin dim) → ℤ , remap ((gamma_matrix^n).mulVec (equiv v)) = Additive.ofMul (gamma_lift^[n] (Additive.toMul (remap v))) := by + intro n + induction n with + | zero => + intro v + simp [remap, equiv] + | succ n ih => + intro v + rw [Function.iterate_succ_apply', pow_succ', ← Matrix.mulVec_mulVec] + rw [show ((gamma_matrix ^ n).mulVec ⇑(equiv v)) + = ⇑(equiv ((gamma_matrix ^ n).mulVec ⇑(equiv v))) from rfl] + rw [gamma_matrix_mulVec, ih] + rfl + + + have rank_nonzero: NeZero (Module.finrank ℤ (Additive (A))) := by + apply NeZero.of_pos + apply Module.finrank_pos + + + have eigen_norm_one: ∀ (k : Module.End.Eigenvalues (Matrix.toLin' (((unitOfInvertible gamma_matrix).val).map (Int.castRingHom ℂ)))), ‖k.val‖ = 1 := by + apply int_matrix_poly_growth_eigenvalue + · + intro k hk v + -- name the (fixed) group element the iterates are applied to + set g : A := + Additive.toMul ((Finsupp.linearCombination ℤ ⇑B) + ((Finsupp.linearEquivFunOnFinite ℤ ℤ (Fin dim)).symm v)) with hg + + + obtain ⟨p, q, p_pos, hq⟩ := gamma_lift_conj ⌈Real.logb ‖k‖ 3⌉₊ (by + simp + apply Real.logb_pos + · grind + · grind + ) g + let K: ℕ := (⌈4 * ((8 * ↑q + Real.log ↑p) ^ 2 / Real.log 2 ^ 2) ^ 2⌉₊ + 2 * ⌈Real.logb ‖k‖ 3⌉₊) + 1 + + + have hpq := hq K (by simp [K]) ⌈Real.logb ‖k‖ 3⌉₊ (by + simp + apply Real.logb_pos + · grind + · grind + ) (by + simp [K] + rw [two_mul] + grw [Nat.le_ceil (a := Real.logb ‖k‖ 3)] + grind + ) + + use p * K ^ q + use q + use K + + refine ⟨?_, ?_, ?_, ?_⟩ + · apply mul_pos + · exact p_pos + · apply pow_pos + simp [K] + + · simp [K] + rw [two_mul] + grw [Nat.le_ceil (a := Real.logb ‖k‖ 3)] + grind + · + -- Isolate `K` on the right of + -- `X < Real.log 2 * (↑K - ↑⌈Real.logb ‖k‖ 3⌉₊) ^ (1/2)`. + -- Divide by `Real.log 2 > 0`, bound the LHS by its absolute value (so no sign + -- assumption on `X` is needed), rewrite `|y| = √(y ^ 2)` and use strict + -- monotonicity of `√`, then move the subtraction across. `K` is never unfolded. + have hlog2 : 0 < Real.log 2 := Real.log_pos (by norm_num) + rw [← Real.sqrt_eq_rpow, ← div_lt_iff₀' hlog2] + refine lt_of_le_of_lt (le_abs_self _) ?_ + rw [← Real.sqrt_sq_eq_abs] + refine Real.sqrt_lt_sqrt (sq_nonneg _) ?_ + rw [lt_sub_iff_add_lt] + -- `K` still occurs on the left inside `Real.log ↑(p * K ^ q)`. This splits that + -- logarithm and eliminates the resulting `Real.log ↑K`, leaving a goal in `ℕ` with + -- `K` alone on the right. + refine log_pow_sq_lt_of_lt _ p q K p_pos ?_ + -- ⊢ ⌈4 * ((8 * ↑q + Real.log ↑p) ^ 2 / Real.log 2 ^ 2) ^ 2⌉₊ + -- + 2 * ⌈Real.logb ‖k‖ 3⌉₊ < K + simp [K] + · + rw [← (Finset.card_image_iff (f := fun a => remap (Finsupp.equivFunOnFinite.symm a))).mpr] + · + rw [Finset.image_image] + simp [remap, equiv] + rw [Function.comp_def] + simp_rw [map_sum] + simp [remap, equiv] at gamma_matrix_mulVec_pow + simp_rw [← pow_mul] + simp_rw [gamma_matrix_mulVec_pow] + -- Turn each subsum into `Additive.ofMul` of a product in the group, keeping the + -- index set as the subtype `↥(Finset.Ico N_1 N_2)`. + simp_rw [← ofMul_prod] + -- `Additive.ofMul` is a bijection, so it does not affect the cardinality: pull it + -- out of the image and discard it. + rw [← Function.comp_def Additive.ofMul, ← Finset.image_image, + Finset.card_image_of_injective _ (Equiv.injective _)] + + + simp_rw [← Finset.prod_map_toList] + + grw [hpq] + -- TODO - we might be able to make the goal stronger, if we don't actually need the factor of 2 in it + rw [pow_mul'] + apply mul_le_mul + · simp + · apply Nat.le_pow + simp + · simp + · simp + · apply Function.Injective.injOn + intro a b hab + simp [remap, equiv] at hab + rw [Function.Injective.eq_iff (linearIndependent_iff_injective_finsuppLinearCombination.mp ?_)] at hab + · simpa using hab + · apply Module.Basis.linearIndependent + + + let a := KroneckerPow (unitOfInvertible gamma_matrix) eigen_norm_one + use a + refine ⟨(by + apply KroneckerPow_pos + ), ?_⟩ + intro p hp + + + have unipotent_gamma_matrix := int_matrix_unipotent (by + apply Module.finrank_pos + ) (unitOfInvertible gamma_matrix) (by + apply eigen_norm_one + ) (n := p * r) (hn := by positivity) + obtain ⟨n, hm⟩ := unipotent_gamma_matrix + + + use n + intro g + apply_fun (fun f => f.toLin (Module.finBasis _ _) (Module.finBasis _ _)) at hm + rw [LinearMap.ext_iff] at hm + specialize hm g + simp [gamma_matrix] at hm + simp [gamma_add] at hm + conv at hm => + rhs + equals 0 => rfl + + + apply_fun (fun f => (f).toMul) at hm + conv at hm => + rhs + equals 1 => rfl + + rw [← neg_sub] at hm + rw [neg_pow] at hm + simp at hm + rw [Module.End.mul_eq_comp] at hm + simp at hm + simp [Function.comp_def] at hm + apply (LinearMap.ker_eq_bot'.mp (by + ext a + clear hm + induction n with + | zero => simp + | succ n ih => + rw [pow_succ] + simp + simp at ih + exact ih + )) at hm + rw [← toMul_eq_one] at hm + rw [← hm] + clear hm + + have x_mul_gamma_eq: ∀ q: ℕ, (fun x => x * (⇑gamma_lift)^[q] x⁻¹) = Additive.toMul ∘ (-((MonoidHom.toAdditive gamma_lift.toMonoidHom).toIntLinearMap ^ (q) - LinearMap.id)).toFun ∘ (Additive.ofMul) := by + intro q + ext x + conv => + rhs + equals Additive.toMul ((-((MonoidHom.toAdditive gamma_lift.toMonoidHom).toIntLinearMap ^ (q) - LinearMap.id)).toFun (Additive.ofMul x)) => + rfl + simp + rw [toIntLinearMap_pow_apply] + simp + rw [Function.comp_def] + rw [div_eq_mul_inv] + simp + rfl + + rw [x_mul_gamma_eq] + simp + rw [Module.End.coe_pow] + -- collapse the `Matrix.toLin B B (LinearMap.toMatrix B B _)` round-trip, which plain + -- `rfl` cannot see through + rw [Matrix.toLin_toMatrix] + + have mul_eq: a * r * p = p * r * a := by ring + simp_rw [mul_eq] + rfl + +lemma exists_gamma_n_unipotent_center_N' {H: Type*} [DecidableEq H] [Group H] {N': Subgroup H} [_N'_normal: N'.Normal] (N'_nilpotent: Group.IsNilpotent N') (hN': Subgroup.FG N') (gamma: MulAut N') (gamma_conj: gamma_conj_bound gamma): ∃ a, a ≠ 0 ∧ ∀ k: ℕ, 0 < k → ∃ n, ∀ g ∈ Subgroup.center N', Nat.iterate (fun x => x * ((gamma^[a*k]) x⁻¹)) n g = 1 := by @@ -163,47 +403,6 @@ lemma exists_gamma_n_unipotent_center_N' {H: Type*} [DecidableEq H] [Group H] {N let gamma_center := MulAut.characteristic (Subgroup.center N') gamma have t_char: torsion.Characteristic := torsion_characteristic let torsion_N := Subgroup.map (Subgroup.subtype _) torsion - let gamma_torsion := MonoidHom.domRestrict gamma.toMonoidHom torsion_N - let new_gamma_torsion_hom := MonoidHom.codRestrict gamma_torsion torsion_N (by - rw [Subgroup.characteristic_iff_map_le] at t_char - specialize t_char - intro x - simp [torsion_N] - use ?_ - . - rw [CommGroup.mem_torsion] - simp [gamma_torsion] - rw [isOfFinOrder_iff_pow_eq_one] - simp - rw [← isOfFinOrder_iff_pow_eq_one] - conv => - arg 1 - equals gamma.toMonoidHom x => - simp - apply MonoidHom.isOfFinOrder - have x_prop := x.prop - unfold torsion_N at x_prop - simp [-SetLike.coe_mem] at x_prop - obtain ⟨x_mem, x_mem_torsion⟩ := x_prop - rw [CommGroup.mem_torsion] at x_mem_torsion - rw [isOfFinOrder_iff_pow_eq_one] at x_mem_torsion - simp at x_mem_torsion - rw [← isOfFinOrder_iff_pow_eq_one] at x_mem_torsion - simpa using x_mem_torsion - . - simp [gamma_torsion] - have char_center := Subgroup.centerCharacteristic (G := N') - rw [Subgroup.characteristic_iff_map_eq] at char_center - specialize char_center gamma - rw [← char_center] - simp - have x_prop := x.prop - unfold torsion_N at x_prop - simp [-SetLike.coe_mem] at x_prop - obtain ⟨x_center, hx⟩ := x_prop - exact x_center - ) - let new_gamma_torsion := MulAut.characteristic torsion_N gamma @@ -225,7 +424,7 @@ lemma exists_gamma_n_unipotent_center_N' {H: Type*} [DecidableEq H] [Group H] {N rw [Function.iterate_succ] simp rw [ih] - simp [new_gamma_torsion, new_gamma_torsion_hom, gamma_torsion] + simp [new_gamma_torsion] let gamma_lift := QuotientGroup.congr (torsion) torsion gamma_center (by @@ -275,284 +474,27 @@ lemma exists_gamma_n_unipotent_center_N' {H: Type*} [DecidableEq H] [Group H] {N simp_rw [Function.iterate_succ'] simp - have unipotent_on_quot: ∃ a, 0 < a ∧ ∀ p: ℕ, 0 < p → ∃ n, ∀ g : (Subgroup.center ↥N') ⧸ torsion, Nat.iterate (fun x => x * ((gamma_lift^[a * orderOf new_gamma_torsion * p] x⁻¹))) n g = 1 := by - wlog nontrivial_quot: Nontrivial ((Subgroup.center ↥N') ⧸ torsion) - . - clear this - simp at nontrivial_quot - use 1 - refine ⟨by simp, ?_⟩ - intro p hp - use 1 - simp - intro g - have quot_subsingelton: Subsingleton ((Subgroup.center ↥N') ⧸ torsion) := by - rw [QuotientGroup.subsingleton_iff] - exact nontrivial_quot - - have g_eq := Subsingleton.eq_one g - simp [g_eq] - - - let foo: CommGroup (Subgroup.center N') := by infer_instance - -- if the additive picture is wanted, this is *definitionally* the same type: - have add_torsion_free: IsAddTorsionFree - (Additive ↥(Subgroup.center ↥N') ⧸ AddCommGroup.torsion (Additive ↥(Subgroup.center ↥N'))) := by - infer_instance - - let add_quot := (Additive ↥(Subgroup.center ↥N') ⧸ AddCommGroup.torsion (Additive ↥(Subgroup.center ↥N'))) - - - let fin_dim: Module.Finite ℤ add_quot := by infer_instance - - let gamma_add := gamma_lift.toAdditive.toAddMonoidHom.toIntLinearMap - let B := (Module.finBasis ℤ (Additive (↥(Subgroup.center ↥N') ⧸ torsion))) - let gamma_matrix := gamma_add.toMatrix B B - have invertible_gamma: Invertible gamma_matrix := { - invOf := ((gamma_lift.toAdditive).symm.toAddMonoidHom).toIntLinearMap.toMatrix B B - invOf_mul_self := by - simp [gamma_matrix, gamma_add] - rw [← LinearMap.toMatrix_mul] - rw [← toIntLinearMap_comp_mul] - simp - mul_invOf_self := by - simp [gamma_matrix, gamma_add] - rw [← LinearMap.toMatrix_mul] - rw [← toIntLinearMap_comp_mul] - simp - } - - let dim := Module.finrank ℤ (Additive (↥(Subgroup.center ↥N') ⧸ torsion)) - let equiv (v: Fin _ → ℤ) := (Finsupp.linearEquivFunOnFinite ℤ _ (Fin dim)).symm v - let remap (v: Fin _ → ℤ) := Finsupp.linearCombination _ B (equiv v) - - have gamma_matrix_mulVec: ∀ v: (Fin dim) → ℤ , remap ((gamma_matrix).mulVec (equiv v)) = Additive.ofMul (gamma_lift (Additive.toMul (remap v))) := by - intro v - unfold gamma_matrix - rw [← Module.Basis.repr_linearCombination (v := (equiv v)) (b := B)] - rw [LinearMap.toMatrix_mulVec_repr] - simp [remap, gamma_add, equiv] - - - have gamma_matrix_mulVec_pow: ∀ n: ℕ, ∀ v: (Fin dim) → ℤ , remap ((gamma_matrix^n).mulVec (equiv v)) = Additive.ofMul (gamma_lift^[n] (Additive.toMul (remap v))) := by - intro n - induction n with - | zero => - intro v - simp [remap, equiv] - | succ n ih => - intro v - rw [Function.iterate_succ_apply', pow_succ', ← Matrix.mulVec_mulVec] - rw [show ((gamma_matrix ^ n).mulVec ⇑(equiv v)) - = ⇑(equiv ((gamma_matrix ^ n).mulVec ⇑(equiv v))) from rfl] - rw [gamma_matrix_mulVec, ih] - rfl - - - have rank_nonzero: NeZero (Module.finrank ℤ (Additive (↥(Subgroup.center ↥N') ⧸ torsion))) := by - apply NeZero.of_pos - apply Module.finrank_pos - - - have gamma_lift_conj: ∀ k: ℕ, (0 < k) → ∀ g, ∃ p q: ℕ, 0 < p ∧ ∀ b: ℕ, 0 < b → ∀ a: ℕ, (0 < a) → (a < b) → (Finset.image (fun x ↦ (List.map (fun (i: ↥(Finset.Ico a b)) ↦ (gamma_lift)^[k * ↑i] g) x.toList).prod) - (Finset.Ico a b).attach.powerset).card ≤ p * (b^q) * (b - a)^q := by - - -- Same shape as the `final_gamma` transport: the products live in - -- `↥(Subgroup.center ↥N')`, mapped out injectively by `Subgroup.subtype` (where - -- `gamma_conj` gives the bound) and surjectively by `QuotientGroup.mk'` (where it - -- is wanted). - classical - exact conjBound_transport - (fC := fun x : ↥(Subgroup.center ↥N') => - (⟨gamma x, gamma_mem_center x⟩ : ↥(Subgroup.center ↥N'))) - (fQ := ⇑gamma_lift) (fN := ⇑gamma) - (QuotientGroup.mk' torsion) (QuotientGroup.mk'_surjective _) - ((Subgroup.center ↥N').subtype) (Subgroup.subtype_injective _) - (fun x => (swap_gamma_lift x).symm) (fun x => rfl) gamma_conj - - have eigen_norm_one: ∀ (k : Module.End.Eigenvalues (Matrix.toLin' (((unitOfInvertible gamma_matrix).val).map (Int.castRingHom ℂ)))), ‖k.val‖ = 1 := by - apply int_matrix_poly_growth_eigenvalue - . - intro k hk v - -- name the (fixed) group element the iterates are applied to - set g : ↥(Subgroup.center ↥N') ⧸ torsion := - Additive.toMul ((Finsupp.linearCombination ℤ ⇑B) - ((Finsupp.linearEquivFunOnFinite ℤ ℤ (Fin dim)).symm v)) with hg - - - obtain ⟨p, q, p_pos, hq⟩ := gamma_lift_conj ⌈Real.logb ‖k‖ 3⌉₊ (by - simp - apply Real.logb_pos - . grind - . grind - ) g - let K: ℕ := (⌈4 * ((8 * ↑q + Real.log ↑p) ^ 2 / Real.log 2 ^ 2) ^ 2⌉₊ + 2 * ⌈Real.logb ‖k‖ 3⌉₊) + 1 - - - have hpq := hq K (by simp [K]) ⌈Real.logb ‖k‖ 3⌉₊ (by - simp - apply Real.logb_pos - . grind - . grind - ) (by - simp [K] - rw [two_mul] - grw [Nat.le_ceil (a := Real.logb ‖k‖ 3)] - grind - ) - - use p * K ^ q - use q - use K - - refine ⟨?_, ?_, ?_, ?_⟩ - . apply mul_pos - . exact p_pos - . apply pow_pos - simp [K] - - . simp [K] - rw [two_mul] - grw [Nat.le_ceil (a := Real.logb ‖k‖ 3)] - grind - . - -- Isolate `K` on the right of - -- `X < Real.log 2 * (↑K - ↑⌈Real.logb ‖k‖ 3⌉₊) ^ (1/2)`. - -- Divide by `Real.log 2 > 0`, bound the LHS by its absolute value (so no sign - -- assumption on `X` is needed), rewrite `|y| = √(y ^ 2)` and use strict - -- monotonicity of `√`, then move the subtraction across. `K` is never unfolded. - have hlog2 : 0 < Real.log 2 := Real.log_pos (by norm_num) - rw [← Real.sqrt_eq_rpow, ← div_lt_iff₀' hlog2] - refine lt_of_le_of_lt (le_abs_self _) ?_ - rw [← Real.sqrt_sq_eq_abs] - refine Real.sqrt_lt_sqrt (sq_nonneg _) ?_ - rw [lt_sub_iff_add_lt] - -- `K` still occurs on the left inside `Real.log ↑(p * K ^ q)`. This splits that - -- logarithm and eliminates the resulting `Real.log ↑K`, leaving a goal in `ℕ` with - -- `K` alone on the right. - refine log_pow_sq_lt_of_lt _ p q K p_pos ?_ - -- ⊢ ⌈4 * ((8 * ↑q + Real.log ↑p) ^ 2 / Real.log 2 ^ 2) ^ 2⌉₊ - -- + 2 * ⌈Real.logb ‖k‖ 3⌉₊ < K - simp [K] - . - rw [← (Finset.card_image_iff (f := fun a => remap (Finsupp.equivFunOnFinite.symm a))).mpr] - . - rw [Finset.image_image] - simp [remap, equiv] - rw [Function.comp_def] - simp_rw [map_sum] - simp [remap, equiv] at gamma_matrix_mulVec_pow - simp_rw [← pow_mul] - simp_rw [gamma_matrix_mulVec_pow] - -- Turn each subsum into `Additive.ofMul` of a product in the group, keeping the - -- index set as the subtype `↥(Finset.Ico N_1 N_2)`. - simp_rw [← ofMul_prod] - -- `Additive.ofMul` is a bijection, so it does not affect the cardinality: pull it - -- out of the image and discard it. - rw [← Function.comp_def Additive.ofMul, ← Finset.image_image, - Finset.card_image_of_injective _ (Equiv.injective _)] - - - simp_rw [← Finset.prod_map_toList] - - grw [hpq] - -- TODO - we might be able to make the goal stronger, if we don't actually need the factor of 2 in it - rw [pow_mul'] - apply mul_le_mul - . simp - . apply Nat.le_pow - simp - . simp - . simp - . apply Function.Injective.injOn - intro a b hab - simp [remap, equiv] at hab - rw [Function.Injective.eq_iff (linearIndependent_iff_injective_finsuppLinearCombination.mp ?_)] at hab - . simpa using hab - . apply Module.Basis.linearIndependent - - - let a := KroneckerPow (unitOfInvertible gamma_matrix) eigen_norm_one - use a - refine ⟨(by - apply KroneckerPow_pos - ), ?_⟩ - intro p hp - - - have unipotent_gamma_matrix := int_matrix_unipotent (by - apply Module.finrank_pos - ) (unitOfInvertible gamma_matrix) (by - apply eigen_norm_one - ) (n := p * orderOf new_gamma_torsion) (hn := by positivity) - obtain ⟨n, hm⟩ := unipotent_gamma_matrix - - - use n - intro g - apply_fun (fun f => f.toLin (Module.finBasis _ _) (Module.finBasis _ _)) at hm - rw [LinearMap.ext_iff] at hm - specialize hm g - simp [gamma_matrix] at hm - simp [gamma_add] at hm - conv at hm => - rhs - equals 0 => rfl - - - apply_fun (fun f => (f).toMul) at hm - conv at hm => - rhs - equals 1 => rfl - - rw [← neg_sub] at hm - rw [neg_pow] at hm - simp at hm - rw [Module.End.mul_eq_comp] at hm - simp at hm - simp [Function.comp_def] at hm - apply (LinearMap.ker_eq_bot'.mp (by - ext a - clear hm - induction n with - | zero => simp - | succ n ih => - rw [pow_succ] - simp - simp at ih - exact ih - )) at hm - rw [← toMul_eq_one] at hm - rw [← hm] - clear hm - - have x_mul_gamma_eq: ∀ q: ℕ, (fun x => x * (⇑gamma_lift)^[q] x⁻¹) = Additive.toMul ∘ (-((MonoidHom.toAdditive gamma_lift.toMonoidHom).toIntLinearMap ^ (q) - LinearMap.id)).toFun ∘ (Additive.ofMul) := by - intro q - ext x - conv => - rhs - equals Additive.toMul ((-((MonoidHom.toAdditive gamma_lift.toMonoidHom).toIntLinearMap ^ (q) - LinearMap.id)).toFun (Additive.ofMul x)) => - rfl - simp - rw [toIntLinearMap_pow_apply] - simp - rw [Function.comp_def] - rw [div_eq_mul_inv] - simp - rfl - - rw [x_mul_gamma_eq] - simp - rw [Module.End.coe_pow] - -- collapse the `Matrix.toLin B B (LinearMap.toMatrix B B _)` round-trip, which plain - -- `rfl` cannot see through - rw [Matrix.toLin_toMatrix] - - -- TODO - figure out how the order gets swapped - have mul_eq: a * orderOf new_gamma_torsion * p = p * orderOf new_gamma_torsion * a := by ring - simp_rw [mul_eq] - rfl - + have gamma_lift_conj: ∀ k: ℕ, (0 < k) → ∀ g, ∃ p q: ℕ, 0 < p ∧ ∀ b: ℕ, 0 < b → ∀ a: ℕ, (0 < a) → (a < b) → (Finset.image (fun x ↦ (List.map (fun (i: ↥(Finset.Ico a b)) ↦ (gamma_lift)^[k * ↑i] g) x.toList).prod) + (Finset.Ico a b).attach.powerset).card ≤ p * (b^q) * (b - a)^q := by + + -- Same shape as the `final_gamma` transport: the products live in + -- `↥(Subgroup.center ↥N')`, mapped out injectively by `Subgroup.subtype` (where + -- `gamma_conj` gives the bound) and surjectively by `QuotientGroup.mk'` (where it + -- is wanted). + classical + exact conjBound_transport + (fC := fun x : ↥(Subgroup.center ↥N') => + (⟨gamma x, gamma_mem_center x⟩ : ↥(Subgroup.center ↥N'))) + (fQ := ⇑gamma_lift) (fN := ⇑gamma) + (QuotientGroup.mk' torsion) (QuotientGroup.mk'_surjective _) + ((Subgroup.center ↥N').subtype) (Subgroup.subtype_injective _) + (fun x => (swap_gamma_lift x).symm) (fun x => rfl) gamma_conj + + have unipotent_on_quot : ∃ a, 0 < a ∧ ∀ p : ℕ, 0 < p → ∃ n, + ∀ g : (Subgroup.center ↥N') ⧸ torsion, + (fun x ↦ x * gamma_lift^[a * orderOf new_gamma_torsion * p] x⁻¹)^[n] g = 1 := + free_abelian_gamma_unipotent gamma_lift (orderOf new_gamma_torsion) order_pos + gamma_lift_conj obtain ⟨quot_pow, quot_pow_pos, h_quot_pow⟩ := unipotent_on_quot use (quot_pow * ( orderOf new_gamma_torsion)) @@ -587,8 +529,8 @@ lemma exists_gamma_n_unipotent_center_N' {H: Type*} [DecidableEq H] [Group H] {N simp have mul_mem_center: (↑g * ((gamma ^ (quot_pow * orderOf new_gamma_torsion * p )) ↑g)⁻¹) ∈ Subgroup.center N' := by apply Subgroup.mul_mem - . simp - . + · simp + · simp have center_char: (Subgroup.center N').Characteristic := by infer_instance @@ -639,8 +581,6 @@ lemma exists_gamma_n_unipotent_center_N' {H: Type*} [DecidableEq H] [Group H] {N -- OLD CODE -set_option maxHeartbeats 2000000 in -set_option synthInstance.maxHeartbeats 160000 in /--{G: Type*} [DecidableEq G] [Group G] (H: Subgroup G) [H.Normal]--/ lemma exists_gamma_n_unipotent_N' {H: Type*} [DecidableEq H] [Group H] {N': Subgroup H} [N'_normal: N'.Normal] (N'_nilpotent: Group.IsNilpotent N') (hN': Subgroup.FG N') (gamma: MulAut N') (gamma_conj: gamma_conj_bound gamma): ∀ p: ℕ, 0 < p → ∃ a n, a ≠ 0 ∧ ∀ g : N', Nat.iterate (fun x => x * ((gamma^[a*p]) x⁻¹)) n g = 1 := by @@ -648,7 +588,7 @@ lemma exists_gamma_n_unipotent_N' {H: Type*} [DecidableEq H] [Group H] {N': Subg classical by_cases N'_subsingle: Subsingleton N' - . + · intro p hp use 1 use 1 @@ -656,7 +596,7 @@ lemma exists_gamma_n_unipotent_N' {H: Type*} [DecidableEq H] [Group H] {N': Subg intro a ha have order := Subsingleton.orderOf_eq (⟨_, ha⟩ : N') simp at order - simp [order, iteratedCommutator] + simp [order] rw [mul_aut_iterate] simp @@ -679,7 +619,7 @@ lemma exists_gamma_n_unipotent_N' {H: Type*} [DecidableEq H] [Group H] {N': Subg let final_gamma := aut_transfer gamma_quot by_cases top_subsingle: Subsingleton (⊤ : Subgroup (↥N' ⧸ Subgroup.center ↥N')) - . + · intro p hp obtain ⟨z_a, h_z_a, z_a_temp⟩ := exists_gamma_n_unipotent_center_N' (N' := N') (N'_nilpotent) (hN') gamma gamma_conj obtain ⟨z_n, h_z_unipotent⟩ := z_a_temp p hp @@ -702,12 +642,12 @@ lemma exists_gamma_n_unipotent_N' {H: Type*} [DecidableEq H] [Group H] {N': Subg have foo := ih (Group.nilpotencyClass (⊤ : Subgroup (↥N' ⧸ Subgroup.center ↥N'))) (by grw [Subgroup.nilpotencyClass_le] - simp [nilpotencyClass_quotient_center] + simp [Group.nilpotencyClass_quotient_center] rw [← hn] simp by_contra! simp at this - rw [nilpotencyClass_zero_iff_subsingleton] at this + rw [Group.nilpotencyClass_zero_iff_subsingleton] at this contradiction ) (H := N' ⧸ Subgroup.center N') (N' := ⊤) (by simp; apply Group.nilpotent_quotient_of_nilpotent) (by have fg_quot: Group.FG (↥N' ⧸ Subgroup.center ↥N') := by @@ -746,7 +686,7 @@ lemma exists_gamma_n_unipotent_N' {H: Type*} [DecidableEq H] [Group H] {N': Subg rw [Function.iterate_add_apply] specialize h_z_unipotent ((fun x ↦ x * ((gamma^[a*z_a*p]) (x⁻¹)))^[n] g) ?_ - . + · have swap_gamma_base: ∀ x, (gamma) x = ((final_gamma) ⟨x, by simp⟩).val := by intro x @@ -787,7 +727,7 @@ lemma exists_gamma_n_unipotent_N' {H: Type*} [DecidableEq H] [Group H] {N': Subg simpa using h_prev - . + · simp_rw [mul_aut_iterate] at h_z_unipotent rw [mul_aut_iterate] simp_rw [← mul_assoc] at h_z_unipotent diff --git a/Gromov/UnipotentGromov.lean b/Gromov/UnipotentGromov.lean index f90d0aa..13fc5f8 100644 --- a/Gromov/UnipotentGromov.lean +++ b/Gromov/UnipotentGromov.lean @@ -13,9 +13,6 @@ Root of the `Gromov.Unipotent` hierarchy. public section -set_option linter.style.longLine false -set_option linter.style.commandStart false -set_option linter.style.cdot false open scoped commutatorElement IsMulCommutative Pointwise @@ -31,8 +28,8 @@ lemma normal_comm_mem_right {G: Type*} [Group G] {N: Subgroup G} (N_normal: N.No equals (a * b * a⁻¹) * b⁻¹ => group apply Subgroup.mul_mem - . exact conj_mem - . simpa using hb + · exact conj_mem + · simpa using hb lemma iterated_mem_iterated_set {G: Type*} [DecidableEq G] [Group G] (base right: G) (S: Finset G) (base_mem: base ∈ S) (right_mem: right ∈ S) (n: ℕ): iteratedCommutator base right n ∈ iterate_comm_set S n := by @@ -63,19 +60,18 @@ lemma comm_subgroup_mem {G: Type*} [DecidableEq G] [Group G] {H: Subgroup G} (S: simp | succ n ih => simp [iterate_comm_set] - intro h h_mem h_mem_s - intro a ha + intro h h_mem h_mem_s a ha simp have a_mem := ih ha simp [Bracket.bracket] apply Subgroup.mul_mem - . apply Subgroup.mul_mem - . apply Subgroup.mul_mem - . exact a_mem - . exact h_mem - . simp + · apply Subgroup.mul_mem + · apply Subgroup.mul_mem + · exact a_mem + · exact h_mem + · simp exact a_mem - . simp + · simp exact h_mem @@ -88,39 +84,39 @@ lemma iterate_comm_subgroup {G: Type*} [DecidableEq G] [Group G] {H: Subgroup G} dsimp [iterate_comm_set] simp refine ⟨?_, ?_⟩ - . + · intro h_mem obtain ⟨b, b_mem, ⟨b_mem_S, a, h_eq⟩⟩ := h_mem obtain ⟨a_mem_h, a_mem_comm, h_eq_comm⟩ := h_eq use b use ?_ - . use a + · use a refine ⟨?_, ?_⟩ - . + · rw [ih] at a_mem_comm simp at a_mem_comm exact a_mem_comm - . rw [← h_eq_comm] + · rw [← h_eq_comm] simp [Bracket.bracket] - . use b_mem - . intro data_mem + · use b_mem + · intro data_mem obtain ⟨b, ⟨b_mem_H, b_mem_S⟩, ⟨a, a_mem_comm, h_eq⟩⟩ := data_mem use b use b_mem_H refine ⟨?_, ?_⟩ - . exact b_mem_S - . use a + · exact b_mem_S + · use a use ?_ - . refine ⟨?_, ?_⟩ - . + · refine ⟨?_, ?_⟩ + · rw [ih] simp exact a_mem_comm - . + · ext rw [← h_eq] simp [Bracket.bracket] - . + · simp [Bracket.bracket] at h_eq have iterate_subset := comm_subgroup_mem S n a_mem_comm simpa using iterate_subset @@ -171,29 +167,29 @@ lemma count_mem_group_implies_lowercentral {G: Type*} [Group G] {N': Subgroup G} simp at l_nonempty | cons head tail ih => by_cases head_in_N': head ∈ N' - . - simp only [List.countP_cons, List.foldr_cons, head_in_N', decide_true, if_true, + · + simp only [List.countP_cons, List.foldr_cons, head_in_N', decide_true, ite_true, Nat.add_sub_cancel] by_cases tail_empty: tail = [] - . + · simp [tail_empty] apply normal_comm_mem_right N'_normal exact head_in_N' - . + · by_cases count_eq_zero: (tail.countP (fun a => decide (a ∈ N'))) = 0 - . + · simp [count_eq_zero] apply normal_comm_mem_right N'_normal exact head_in_N' - . + · have count_sub_eq: (tail.countP (fun a => decide (a ∈ N'))) = (tail.countP (fun a => decide (a ∈ N'))) - 1 + 1 := by omega rw [count_sub_eq] specialize ih (by simpa using tail_empty) count_eq_zero exact Subgroup.commutator_mem_commutator ih head_in_N' - . rw [List.countP_cons] + · rw [List.countP_cons] simp only [head_in_N', decide_false, Bool.false_eq_true, ↓reduceIte] @@ -208,11 +204,10 @@ lemma count_mem_group_implies_lowercentral {G: Type*} [Group G] {N': Subgroup G} specialize ih tail_nonempty count_ne_zero rw [List.foldr_cons] apply normal_comm_mem - . infer_instance - . exact ih + · infer_instance + · exact ih -#print axioms count_mem_group_implies_lowercentral -- `Subgroup.map_toSubmonoid` rewrites the `.carrier` predicate of `Subgroup.map`, which breaks the @@ -229,22 +224,22 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg classical by_cases m_eq: m = 0 - . + · simp [iteratedCommutator, m_eq] at h_gamma_alpha have N'_bot: N' = ⊥ := by rw [Subgroup.eq_bot_iff_forall] simpa using h_gamma_alpha - let foo := Subgroup.closureCommGroupOfComm (k := (↑(Finset.image (⇑H.subtype) S) ∪ {gamma_alpha})) ?_ - . + have foo := Subgroup.isMulCommutative_closure (k := (↑(Finset.image (⇑H.subtype) S) ∪ {gamma_alpha})) ?_ + · apply CommGroup.isNilpotent - . intro x hx y hy + · intro x hx y hy by_cases S_empty: S = ∅ - . simp [S_empty] at hx hy + · simp [S_empty] at hx hy grind - . + · have S_eq: S = {1} := by simp only [N'_bot, Subgroup.closure_eq_bot_iff] at hS have S_subset: S ⊆ {1} := by @@ -265,10 +260,10 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg have nilpotent_map: Group.IsNilpotent ↥(Subgroup.map H.subtype N') := by apply map_nilpotent - . exact Subgroup.subtype_injective H - . exact N'_nilpotent + · exact Subgroup.subtype_injective H + · exact N'_nilpotent - rw [nilpotent_iff_lowerCentralSeries] + rw [Subgroup.nilpotent_iff_lowerCentralSeries] use ((1 + (Group.nilpotencyClass ↥(Subgroup.map H.subtype N'))) * (m + 1)) + 2 apply comm_trivial_implies_nilpotent (S := Finset.image (fun (a: ↑((Finset.image (Subgroup.subtype _) S) ∪ {gamma_alpha})) => ⟨a.val, by ( @@ -278,7 +273,7 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg simp exact a_prop )⟩) Finset.univ) - . + · simp only [Finset.coe_image, Finset.coe_univ, Set.image_univ] @@ -297,7 +292,7 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg · intro hg exact ⟨⟨g, by apply Subgroup.mem_closure_of_mem; exact hg⟩, ⟨⟨g, by simpa using hg⟩, rfl⟩, rfl⟩ - . + · ext a rw [iterate_comm_subgroup] @@ -312,11 +307,11 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg exact Finset.attach_image_val refine ⟨?_, ?_⟩ - . + · intro a_mem rw [← Finset.mem_coe] at a_mem rw [iterate_comm_set_eq_fold] at a_mem - simp only [Set.mem_setOf_eq] at a_mem + simp only [Set.mem_ofPred_eq] at a_mem obtain ⟨s, l, l_length, a_eq⟩ := a_mem -- TODO - extract this to its own lemma @@ -341,22 +336,21 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg rw [Function.iterate_succ'] simp apply normal_comm_mem - . infer_instance - . exact ih + · infer_instance + · exact ih have comm_in_N': (fun x ↦ ⁅x, gamma_alpha⁆)^[t] g ∈ (Subgroup.map (Subgroup.subtype _) N') := by clear ht induction t with | zero => - simpa using g_mem + simp | succ t ih => simp_rw [Function.iterate_succ'] - simp only [Function.comp_apply, Subgroup.subtype_apply, - Subtype.exists, exists_and_right, exists_eq_right] + simp only [Function.comp_apply] apply normal_comm_mem - . + · infer_instance - . exact ih + · exact ih simp at comm_in_N' obtain ⟨foo, bar⟩ := comm_in_N' @@ -367,7 +361,7 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg have adjacent_or_count := list_adjacent_elements l (fun x => decide (x = gamma_alpha)) (m + 1) rw [l_length] at adjacent_or_count cases adjacent_or_count - . + · rename_i adjancent_gamma obtain ⟨gamma_list, h_gamma_list, gamma_list_len, eq_gamma_alpha⟩ := adjancent_gamma @@ -406,10 +400,10 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg have s_mem := s.property rw [Finset.mem_union] at s_mem cases s_mem - . rename_i s_mem_N' + · rename_i s_mem_N' rw [subsequent_comm_one] - . rw [list_fold_comm_one] - . + · rw [list_fold_comm_one] + · clear h_list_eq induction l_suffix with | nil => @@ -420,9 +414,9 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg | cons head tail ih => simp apply normal_comm_mem - . infer_instance - . exact ih - . + · infer_instance + · exact ih + · clear h_list_eq rw [← Subgroup.mem_map_iff_mem (f := H.subtype) (Subgroup.subtype_injective H)] induction l_suffix with @@ -437,9 +431,9 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg simp [-Subgroup.mem_map] apply normal_comm_mem (by infer_instance) exact ih - . rw [List.length_unattach] + · rw [List.length_unattach] omega - . + · rename_i s_eq_gamma simp at s_eq_gamma rw [s_eq_gamma] @@ -463,23 +457,23 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg rw [Finset.mem_union] at head_prop cases head_prop - . + · rename_i head_in_N rw [Set.mem_union] at ih apply Set.mem_union_left apply normal_comm_mem (by infer_instance) apply normal_comm_mem_right (by infer_instance) exact image_sub_map _ head_in_N - . rename_i head_gamma + · rename_i head_gamma simp at head_gamma cases ih - . rename_i left + · rename_i left simp only [List.unattach_cons, List.foldr_cons] rw [head_gamma] apply Set.mem_union_left apply normal_comm_mem (by infer_instance) exact left - . + · rename_i right apply Set.mem_union_left simp at right @@ -490,17 +484,17 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg rw [Set.mem_union] at fold_mem cases fold_mem - . rename_i fold_in_N + · rename_i fold_in_N simp at fold_in_N rw [subsequent_comm_one] - . rw [list_fold_comm_one] - . + · rw [list_fold_comm_one] + · obtain ⟨foo, bar⟩ := fold_in_N exact foo - . obtain ⟨foo, bar⟩ := fold_in_N + · obtain ⟨foo, bar⟩ := fold_in_N exact bar - . omega - . rename_i fold_eq_gamma + · omega + · rename_i fold_eq_gamma simp at fold_eq_gamma rw [fold_eq_gamma] @@ -512,13 +506,13 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg rw [nat_iterate_comm_one] rw [list_fold_comm_one] - . + · rename_i count_not_gamma simp at count_not_gamma rw [mul_comm] at count_not_gamma rw [Nat.mul_add_div] at count_not_gamma rw [Nat.div_eq_of_lt] at count_not_gamma - . simp at count_not_gamma + · simp at count_not_gamma refine Finset.mem_singleton.mpr ?_ ext @@ -534,19 +528,19 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg congr simp refine ⟨?_, ?_⟩ - . intro hx other + · intro hx other rw [← hx] at gamma_not_n simp at gamma_not_n apply gamma_not_n other - . intro hx + · intro hx have x_prop := x.prop rw [Finset.mem_union] at x_prop - simp [hx] at x_prop + simp at x_prop cases x_prop - . rename_i mem_N' + · rename_i mem_N' obtain ⟨mem_H, mem_N⟩ := mem_N' exact absurd (S_sub_N' _ mem_N) (hx mem_H) - . rename_i x_eq + · rename_i x_eq exact x_eq @@ -561,11 +555,11 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg have foo := count_mem_group_implies_lowercentral (N' := (Subgroup.map H.subtype N')) (by infer_instance) l.unattach s ?_ ?_ - . + · rw [Subgroup.lowerCentralSeries_eq_bot_of_nilpotencyClass_le (by omega)] at foo simpa using foo - . + · -- TODO - this is ridiculously overcomplicated have l_len_ne: l.length ≠ 0 := by @@ -573,10 +567,10 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg grind - . omega - . omega - . omega - . + · omega + · omega + · omega + · intro a_eq replace a_eq : a = 1 := Finset.mem_singleton.mp a_eq -- `S` need not contain `1`, so start the iterated commutator at `gamma_alpha` @@ -593,4 +587,3 @@ lemma unipotent_commutator_trivial {G: Type*} [DecidableEq G] [Group G] (H: Subg rw [a_eq] simpa using iterate_mem -#print axioms unipotent_commutator_trivial diff --git a/Gromov/Unitary/Basic.lean b/Gromov/Unitary/Basic.lean index afa60f5..b159646 100644 --- a/Gromov/Unitary/Basic.lean +++ b/Gromov/Unitary/Basic.lean @@ -16,8 +16,6 @@ public section open scoped Matrix.Norms.L2Operator ComplexInnerProductSpace -set_option linter.style.longLine false -set_option linter.style.commandStart false open Subgroup Pointwise Finset open scoped Pointwise Finset @@ -190,7 +188,6 @@ lemma poly_growth_equiv {G: Type*} [DecidableEq G] [Group G] (a d: ℕ) exact Nat.one_le_pow d n hn -#print axioms poly_growth_equiv -- Lemma 3.29 (Shrinking Conjugators) @@ -247,7 +244,6 @@ instance unitary_proper (n : ℕ) : ProperSpace ↥(Matrix.unitaryGroup (Fin n) apply ProperSpace.of_isClosed apply unitary_closed -#synth Nontrivial (Matrix (Fin 1) (Fin 1) ℂ) @[expose] @@ -363,16 +359,15 @@ lemma small_dist_matrix (n : ℕ) (hn : 2 ≤ n) : linarith · simp [dists] apply Set.Finite.image - apply Set.Finite.diff + apply Set.Finite.sdiff apply Set.Finite.image have finite_roots : Finite ↥(rootsOfUnity n ℂ) := by infer_instance - -- TODO - how is this working??? exact finite_roots - · --have n_gt_one : 1 < n := by omega + · simp [dists] - rw [Set.diff_nonempty] + rw [Set.sdiff_nonempty] simp let my_root : Units ℂ := { @@ -413,6 +408,5 @@ lemma small_dist_matrix (n : ℕ) (hn : 2 ≤ n) : norm_cast at abs_lt_one linarith [Int.one_le_abs a_eq_zero] -#print axioms small_dist_matrix -- Lemma 3.31 (Volume Packing) diff --git a/Gromov/Unitary/CentralTrivial.lean b/Gromov/Unitary/CentralTrivial.lean index 817f510..ade1ee0 100644 --- a/Gromov/Unitary/CentralTrivial.lean +++ b/Gromov/Unitary/CentralTrivial.lean @@ -13,8 +13,6 @@ public section open scoped Matrix.Norms.L2Operator ComplexInnerProductSpace -set_option linter.style.longLine false -set_option linter.style.commandStart false open Subgroup Pointwise Finset open scoped Pointwise Finset @@ -48,23 +46,23 @@ lemma H_n_contradiction (data : HnData) simp [c'] rw [Nat.one_le_iff_ne_zero] apply Nat.mul_ne_zero - . apply Nat.mul_ne_zero - . apply Nat.mul_ne_zero - . simp - . + · apply Nat.mul_ne_zero + · apply Nat.mul_ne_zero + · simp + · simp apply c_mul_pos - . omega - . simp + · omega + · simp ) have lower_bound := H_n_ball_S_card m_gt data c c_pos c_lt have ineq := le_trans lower_bound upper_bound rify at ineq rw [← Real.log_le_log_iff] at ineq - . + · simp at ineq rw [Real.log_mul] at ineq - . + · simp at ineq rw [Real.log_mul] at ineq simp at ineq @@ -83,17 +81,17 @@ lemma H_n_contradiction (data : HnData) have log_m_gt: ↑data.S_poly_deg < Real.log ↑m := by rw [← Real.exp_lt_exp] rw [Real.exp_log] - . + · unfold m apply Nat.lt_of_ceil_lt apply lt_max_of_lt_right simp - . simp + · simp omega rw [Real.log_mul] - . + · rw [mul_add] rw [add_comm] rw [← add_assoc] @@ -109,87 +107,80 @@ lemma H_n_contradiction (data : HnData) rw [← lt_tsub_iff_right] rw [← mul_sub] rw [← div_lt_iff₀] - . + · dsimp [m] apply Nat.lt_of_ceil_lt apply lt_max_of_lt_left apply lt_max_of_lt_right simp - . + · simp rw [lt_tsub_iff_right] rw [← Real.exp_lt_exp] rw [Real.exp_log] - . - rw [← gt_iff_lt] - grw [(Nat.sub_one_lt_floor _).gt] - rw [gt_iff_lt] - rw [lt_tsub_iff_right] - field_simp - rw [lt_div_iff₀'] - rw [← lt_div_iff₀] - . - exact eps_div_lt - . positivity - . apply H_n_eps_pos - . + · + apply lt_trans ?_ (Nat.sub_one_lt_floor _) + rw [← div_eq_mul_inv, lt_sub_iff_add_lt, + lt_div_iff₀ (H_n_eps_pos data.hd)] + simpa only [mul_comm] using + (lt_div_iff₀ (show 0 < Real.exp (4 + ↑data.S_poly_deg * Real.log 2) + 1 by positivity)).mp eps_div_lt + · simp rw [Nat.floor_pos] exact c_mul_pos - . simp - . simp - . simp - . + · simp + · simp + · simp + · simp refine ⟨by simp [c'], ?_⟩ exact c_mul_pos - . simp + · simp omega unfold swap_le at reverse_ineq - . linarith - . have m_ne_zero: m ≠ 0 := by + · linarith + · have m_ne_zero: m ≠ 0 := by omega simp [c', m_ne_zero] exact c_mul_pos - . simp + · simp - . + · exact Nat.cast_ne_zero.mpr (id (Ne.symm data.S_poly_const_pos)) - . + · apply ne_zero_of_pos apply pow_pos simp apply mul_pos - . + · simp [c'] rw [Nat.floor_pos] exact c_mul_pos - . exact Nat.cast_pos'.mpr m_gt - . + · exact Nat.cast_pos'.mpr m_gt + · norm_cast apply Nat.pow_pos rw [Nat.floor_pos] exact c_mul_pos - . + · apply mul_pos - . simp + · simp exact Nat.zero_lt_of_ne_zero (id (Ne.symm data.S_poly_const_pos)) - . + · apply pow_pos simp [c'] apply mul_pos - . simp + · simp rw [Nat.floor_pos] exact c_mul_pos - . exact Nat.cast_pos'.mpr m_gt + · exact Nat.cast_pos'.mpr m_gt -#print axioms H_n_contradiction -- Note - Vikman proves a much weaker statement (an upper boud n terms of 2^n) -- The norms are actually bounded by a constant, which makes the rest of the proof easier @@ -203,8 +194,302 @@ open scoped Pointwise -- Theorem 3.8, case with only trivial elements in the center -set_option synthInstance.maxHeartbeats 100000 in -set_option maxHeartbeats 2200000 in +private lemma small_finite_generators (n : ℕ) (hn : 2 ≤ n) + (G : Subgroup (Matrix.unitaryGroup (Fin n) ℂ)) + (S_poly_data : SPolyData (G' n (H_n_eps hn) G)) : + ∃ S : Set G, (∀ s ∈ S, ‖s.val.val - 1‖ < H_n_eps hn) ∧ + S.Finite ∧ S = S⁻¹ ∧ Subgroup.closure S = G' n (H_n_eps hn) G ∧ 1 ∈ S := by + classical + let S' := S_poly_data.S + have S'_finite := S_poly_data.S_finite + + -- Add identity and inverses to S' to make things easier + let S'' := S' + have S''_finite: Set.Finite S'' := by + dsimp [S''] + apply S'_finite + + + have S''_eq_S''inv: S'' = S''⁻¹ := by + unfold S'' + apply S_poly_data.S_inv + + + have S''_generates: Subgroup.closure S'' = ⊤ := by + dsimp [S''] + apply S_poly_data.S_generates + + + have s_list (s: S'') := (mem_closure_prod_list ((Metric.ball (1 : G) (H_n_eps hn)) ∪ (Metric.ball (1 : G) (H_n_eps hn))⁻¹) (by + simp + rw [Set.union_comm] + ) s (by + have s_prop := s.val.property + simp only [G'] at s_prop + rw [Subgroup.closure_union] + simp [s_prop] + )) + + -- Write each element in S'' as a product of elements of S', and then collect all of the used elements into a set + -- We may need to manually union this with S⁻¹, since the inverse of the produces + -- could be chosen to be built with different elements (not the inverses of the ones in the original list) + let pre_S := ⋃ s : S''_finite.toFinset, ((s_list ⟨s, by ( + have foo := s.property + rw [Set.Finite.mem_toFinset] at foo + exact foo + )⟩).choose.unattach.toFinset : Set ↥G) ∪ {1} + let S := pre_S ∪ pre_S⁻¹ ∪ {1} + + have S_dist: ∀ s ∈ S, ‖s.val.val - 1‖ < H_n_eps hn := by + intro s hs + dsimp [S] at hs + + rw [Set.union_assoc] at hs + cases hs + · rename_i s_mem + dsimp [pre_S] at s_mem + rw [Set.mem_iUnion] at s_mem + obtain ⟨y, y_mem⟩ := s_mem + simp only [List.coe_toFinset, List.mem_unattach, Set.mem_union, Set.mem_inv, + Set.mem_ofPred_eq] at y_mem + obtain ⟨s_mem_S'', s_mem_choose⟩ := y_mem + simp at s_mem_S'' + simp only [Subtype.dist_eq, dist_eq_norm_sub] at s_mem_S'' + conv at s_mem_S'' => + right + arg 1 + arg 1 + equals (star s.val.val * 1 - (star s.val.val) * s.val.val) => + simp + + rw [← mul_sub] at s_mem_S'' + rw [← Unitary.coe_star] at s_mem_S'' + rw [CStarRing.norm_coe_unitary_mul] at s_mem_S'' + nth_rw 2 [norm_sub_rev] at s_mem_S'' + simp at s_mem_S'' + · exact s_mem_S'' + · + rename_i s_eq_one + simp at s_eq_one + simp [s_eq_one] + have foo := H_n_eps_pos hn + linarith + · + -- TODO - deduplicate most of this with the above case + rename_i s_mem + rw [Set.union_comm] at s_mem + cases s_mem + · rename_i s_mem_one + simp at s_mem_one + simp [s_mem_one] + apply H_n_eps_pos + + rename_i s_mem + dsimp [pre_S] at s_mem + rw [Set.iUnion_inv] at s_mem + rw [Set.mem_iUnion] at s_mem + obtain ⟨y, y_mem⟩ := s_mem + simp only [List.coe_toFinset, List.mem_unattach, Set.mem_union, Set.mem_inv, + Set.mem_ofPred_eq] at y_mem + obtain ⟨s_mem_S'', s_mem_choose⟩ := y_mem + simp at s_mem_S'' + simp only [Subtype.dist_eq, dist_eq_norm_sub] at s_mem_S'' + rw [or_comm] at s_mem_S'' + conv at s_mem_S'' => + right + arg 1 + arg 1 + equals (star s.val.val * 1 - (star s.val.val) * s.val.val) => + simp + + rw [← mul_sub] at s_mem_S'' + rw [← Unitary.coe_star] at s_mem_S'' + rw [CStarRing.norm_coe_unitary_mul] at s_mem_S'' + nth_rw 2 [norm_sub_rev] at s_mem_S'' + simp at s_mem_S'' + · exact s_mem_S'' + · + rename_i s_eq_one + simp at s_eq_one + simp [s_eq_one] + have foo := H_n_eps_pos hn + linarith + + + have S_finite: Set.Finite S := by + dsimp [S] + apply Set.Finite.union + · + simp + dsimp [pre_S] + apply Set.Finite.sUnion + · + apply Set.finite_range + · + intro y hy + rw [Set.mem_range] at hy + obtain ⟨x, x_mem, y_eq⟩ := hy + apply Set.Finite.union + · apply Finset.finite_toSet + · simp + · simp + + have S_union_Sinv: S ∪ S⁻¹ = S := by + dsimp [S] + simp [-Set.union_singleton] + grind + + have S_eq_Sinv: S = S⁻¹ := by + rw [← S_union_Sinv] + simp + rw [Set.union_comm] + + have S_generates : Subgroup.closure S = G' n (H_n_eps hn) G := by + apply le_antisymm + · apply (Subgroup.closure_le (K := G' n (H_n_eps hn) G)).2 + intro g hg + apply Subgroup.subset_closure + simpa only [Metric.mem_ball, Subtype.dist_eq, dist_eq_norm_sub, norm_sub_rev, + Subgroup.coe_one, Submonoid.coe_one] + using S_dist g hg + · have hgen : ∀ g : G' n (H_n_eps hn) G, g.val ∈ Subgroup.closure S := by + intro g + have hg : g ∈ Subgroup.closure S'' := by rw [S''_generates]; trivial + induction hg using Subgroup.closure_induction with + | mem g hg => + have hprod := (s_list ⟨g, hg⟩).choose_spec + rw [← hprod] + apply Subgroup.list_prod_mem + intro x hx + apply Subgroup.subset_closure + apply Set.mem_union_left + apply Set.mem_union_left + apply Set.mem_iUnion.mpr + refine ⟨⟨g, S''_finite.mem_toFinset.mpr hg⟩, Or.inl ?_⟩ + exact List.mem_toFinset.mpr hx + | one => exact Subgroup.one_mem _ + | mul x y hx hy hx' hy' => exact Subgroup.mul_mem _ hx' hy' + | inv x hx hx' => exact Subgroup.inv_mem _ hx' + intro g hg + exact hgen ⟨g, hg⟩ + + exact ⟨S, S_dist, S_finite, S_eq_Sinv, S_generates, by simp [S]⟩ + +private lemma small_generators_growth (n : ℕ) (hn : 2 ≤ n) + (G : Subgroup (Matrix.unitaryGroup (Fin n) ℂ)) + (S_poly_data : SPolyData (G' n (H_n_eps hn) G)) + (S : Set G) (S_finite : S.Finite) + (s_to_map : S_finite.toFinset → Subgroup.map G.subtype (G' n (H_n_eps hn) G)) + (h_map : ∀ a, (s_to_map a).val = a.val.val) : + ∃ a : ℕ, a ≥ 1 ∧ ∀ r ≥ 1, + #(Finset.image s_to_map S_finite.toFinset.attach ^ r) ≤ a * r ^ S_poly_data.S_poly_deg := by + classical + have poly_pos := S_poly_data.S_poly_const_pos + have new_try := poly_growth_equiv S_poly_data.S_poly_const S_poly_data.S_poly_deg (by omega) (S_poly_data.S_finite.toFinset) + (Finset.image (fun a => ⟨⟨(s_to_map a).val, by (rw [h_map]; exact a.val.property)⟩, by ( + have foo := (s_to_map a).property + rw [Subgroup.mem_map] at foo + obtain ⟨x, x_mem, x_eq⟩ := foo + simp_rw [← x_eq] + simp [x_mem] + )⟩) S_finite.toFinset.attach) ?_ ?_ ?_ ?_ + · + obtain ⟨b, b_pos, hb⟩ := new_try + use b + refine ⟨b_pos, ?_⟩ + intro r hr + rw [← Finset.card_image_of_injective (f := Subgroup.subtype _) _ (by apply subtype_injective)] + rw [Finset.image_pow] + rw [Finset.image_image] + simp + conv => + arg 1 + arg 1 + arg 1 + equals Finset.image (Subgroup.subtype _) S_finite.toFinset => + ext a + rw [Finset.mem_image] + refine ⟨?_, ?_⟩ + · intro x + obtain ⟨y, y_mem, y_eq⟩ := x + rw [Finset.mem_image] + use y + rw [← y_eq] + simp [h_map] + · intro x_mem + rw [Finset.mem_image] at x_mem + obtain ⟨y, y_mem, y_eq⟩ := x_mem + use ⟨y, y_mem⟩ + simp [h_map] + exact y_eq + + + specialize hb r hr + rw [← Finset.card_image_of_injective (f := Subgroup.subtype _) _ (by apply subtype_injective)] at hb + rw [Finset.image_pow] at hb + rw [← Finset.card_image_of_injective (f := Subgroup.subtype _) _ (by apply subtype_injective)] at hb + rw [Finset.image_pow] at hb + conv at hb => + arg 1 + arg 1 + arg 1 + equals Finset.image (Subgroup.subtype _) S_finite.toFinset => + ext a + rw [Finset.mem_image] + refine ⟨?_, ?_⟩ + · intro x + obtain ⟨y, y_mem, y_eq⟩ := x + rw [Finset.mem_image] + use y + rw [← y_eq] + simp + rw [Finset.image_image] at y_mem + rw [Finset.mem_image] at y_mem + obtain ⟨z, z_mem, z_eq⟩ := y_mem + simp at z_eq + rw [← z_eq] + simp [h_map] + have z_prop := z.property + rw [Set.Finite.mem_toFinset] at z_prop + exact z_prop + · intro x_mem + rw [Finset.mem_image] at x_mem + obtain ⟨y, y_mem, y_eq⟩ := x_mem + use y + refine ⟨?_, y_eq⟩ + rw [Finset.image_image] + rw [Finset.mem_image] + simp at y_mem + use ⟨y, by simp [y_mem]⟩ + simp [h_map] + exact hb + · + have fintype_s: Fintype ↑S_poly_data.S := by + refine Set.Finite.fintype ?_ + exact S_poly_data.S_finite + + + simp + conv => + rhs + equals (S_poly_data.S).toFinset => + ext a + simp + nth_rw 1 [S_poly_data.S_inv] + simp + · + simp + apply S_poly_data.S_one + · + simp + exact S_poly_data.S_generates + · + intro n hn + have S_poly := S_poly_data.S_poly n hn + exact S_poly + + + lemma central_trivial_virtually_abelian (n : ℕ) (hn : 2 ≤ n) (G : Subgroup (Matrix.unitaryGroup (Fin n) ℂ)) (G_FG : G.FG) (G'_central_trivial : ∀ g : (G' n (H_n_eps hn) G), g ∈ Set.center (G' n (H_n_eps hn) G) → ∃ z : ℂ, g.val.val.val = z • 1) (G'_finite_index: (G' n (H_n_eps hn) G).FiniteIndex) @@ -240,247 +525,12 @@ lemma central_trivial_virtually_abelian (n : ℕ) (hn : 2 ≤ n) (G : Subgroup ( let S' := S_poly_data.S - have S'_finite := S_poly_data.S_finite - - -- Add identity and inverses to S' to make things easier let S'' := S' - have S''_finite: Set.Finite S'' := by - dsimp [S''] - apply S'_finite - - - have S''_eq_S''inv: S'' = S''⁻¹ := by - unfold S'' - apply S_poly_data.S_inv - - - have S''_generates: Subgroup.closure S'' = ⊤ := by - dsimp [S''] - apply S_poly_data.S_generates - - - have s_list (s: S'') := (mem_closure_prod_list ((Metric.ball (1 : G) (H_n_eps hn)) ∪ (Metric.ball (1 : G) (H_n_eps hn))⁻¹) (by - simp - rw [Set.union_comm] - ) s (by - have s_prop := s.val.property - simp only [G'] at s_prop - rw [Subgroup.closure_union] - simp [s_prop] - )) - - -- Write each element in S'' as a product of elements of S', and then collect all of the used elements into a set - -- We may need to manually union this with S⁻¹, since the inverse of the produces - -- could be chosen to be built with different elements (not the inverses of the ones in the original list) - let pre_S := ⋃ s : S''_finite.toFinset, ((s_list ⟨s, by ( - have foo := s.property - rw [Set.Finite.mem_toFinset] at foo - exact foo - )⟩).choose.unattach.toFinset : Set ↥G) ∪ {1} - let S := pre_S ∪ pre_S⁻¹ ∪ {1} - - have S_dist: ∀ s ∈ S, ‖s.val.val - 1‖ < H_n_eps hn := by - intro s hs - dsimp [S] at hs - - rw [Set.union_assoc] at hs - cases hs - . rename_i s_mem - dsimp [pre_S] at s_mem - rw [Set.mem_iUnion] at s_mem - obtain ⟨y, y_mem⟩ := s_mem - simp only [List.coe_toFinset, List.mem_unattach, Set.mem_union, Set.mem_inv, - Set.mem_setOf_eq] at y_mem - obtain ⟨s_mem_S'', s_mem_choose⟩ := y_mem - simp at s_mem_S'' - simp only [Subtype.dist_eq, dist_eq_norm_sub] at s_mem_S'' - conv at s_mem_S'' => - right - arg 1 - arg 1 - equals (star s.val.val * 1 - (star s.val.val) * s.val.val) => - simp - - rw [← mul_sub] at s_mem_S'' - rw [← Unitary.coe_star] at s_mem_S'' - rw [CStarRing.norm_coe_unitary_mul] at s_mem_S'' - nth_rw 2 [norm_sub_rev] at s_mem_S'' - simp at s_mem_S'' - . exact s_mem_S'' - . - rename_i s_eq_one - simp at s_eq_one - simp [s_eq_one] - have foo := H_n_eps_pos hn - linarith - . - -- TODO - deduplicate most of this with the above case - rename_i s_mem - rw [Set.union_comm] at s_mem - cases s_mem - . rename_i s_mem_one - simp at s_mem_one - simp [s_mem_one] - apply H_n_eps_pos - - rename_i s_mem - dsimp [pre_S] at s_mem - rw [Set.iUnion_inv] at s_mem - rw [Set.mem_iUnion] at s_mem - obtain ⟨y, y_mem⟩ := s_mem - simp only [List.coe_toFinset, List.mem_unattach, Set.mem_union, Set.mem_inv, - Set.mem_setOf_eq] at y_mem - obtain ⟨s_mem_S'', s_mem_choose⟩ := y_mem - simp at s_mem_S'' - simp only [Subtype.dist_eq, dist_eq_norm_sub] at s_mem_S'' - rw [or_comm] at s_mem_S'' - conv at s_mem_S'' => - right - arg 1 - arg 1 - equals (star s.val.val * 1 - (star s.val.val) * s.val.val) => - simp - - rw [← mul_sub] at s_mem_S'' - rw [← Unitary.coe_star] at s_mem_S'' - rw [CStarRing.norm_coe_unitary_mul] at s_mem_S'' - nth_rw 2 [norm_sub_rev] at s_mem_S'' - simp at s_mem_S'' - . exact s_mem_S'' - . - rename_i s_eq_one - simp at s_eq_one - simp [s_eq_one] - have foo := H_n_eps_pos hn - linarith - - - have S_finite: Set.Finite S := by - dsimp [S] - apply Set.Finite.union - . - simp - dsimp [pre_S] - apply Set.Finite.sUnion - . - apply Set.finite_range - . - intro y hy - rw [Set.mem_range] at hy - obtain ⟨x, x_mem, y_eq⟩ := hy - apply Set.Finite.union - . apply Finset.finite_toSet - . simp - . simp - - have S_union_Sinv: S ∪ S⁻¹ = S := by - dsimp [S] - simp [-Set.union_singleton] - grind - - have S_eq_Sinv: S = S⁻¹ := by - rw [← S_union_Sinv] - simp - rw [Set.union_comm] - - have S_generates: Subgroup.closure S = (G' n (H_n_eps hn) G) := by - - ext a - unfold S - rw [Subgroup.closure_union] - simp - rw [Subgroup.closure_union] - simp - unfold pre_S - refine ⟨?_, ?_⟩ - . intro ha - -- TODO - only the 'mem' case is non-trivial. We probably don't actually need a full induction proof - induction ha using Subgroup.closure_induction with - | one => - simp [G'] - | mem x hx => - rw [Set.mem_iUnion] at hx - obtain ⟨y, y_mem⟩ := hx - have y_prop := y.property - rw [Set.Finite.mem_toFinset] at y_prop - cases y_mem - . - rename_i y_mem - simp at y_mem - obtain ⟨x_dist, x_mem⟩ := y_mem - simp [G'] - apply Subgroup.mem_closure_of_mem - simp - cases x_dist - . rename_i x_dist_le - exact x_dist_le - . rename_i x_inv_dist - - -- TODO - deduplicate this, in particular the 'CStarRing.norm_coe_unitary_mul' code - simp only [Subtype.dist_eq, dist_eq_norm_sub] at x_inv_dist - conv at x_inv_dist => - lhs - arg 1 - equals (star x.val.val * 1 - (star x.val.val) * x.val.val) => - simp - - rw [← mul_sub] at x_inv_dist - rw [← Unitary.coe_star] at x_inv_dist - rw [CStarRing.norm_coe_unitary_mul] at x_inv_dist - rw [norm_sub_rev] at x_inv_dist - simp only [Subtype.dist_eq, dist_eq_norm_sub] - exact x_inv_dist - . - rename_i x_mem_one - simp at x_mem_one - simp [x_mem_one] - | mul x y hx hy x_mem y_mem => - apply Subgroup.mul_mem - . exact x_mem - . exact y_mem - | inv x hx x_mem => - apply Subgroup.inv_mem - exact x_mem - . - intro ha - apply_fun (Subgroup.map (G' n (H_n_eps hn) G).subtype) at S''_generates - conv at S''_generates => - rhs - equals (G' n (H_n_eps hn) G) => - ext a - simp - - rw [← S''_generates] at ha - simp at ha - obtain ⟨a_mem_g', a_mem_closure⟩ := ha - rw [← Subgroup.mem_toSubmonoid] at a_mem_closure - rw [Subgroup.closure_toSubmonoid] at a_mem_closure - obtain ⟨l, l_mem, l_prod_eq⟩ := Submonoid.exists_list_of_mem_closure a_mem_closure - rw [Subtype.ext_iff] at l_prod_eq - simp at l_prod_eq - rw [← l_prod_eq] - apply Subgroup.list_prod_mem - intro x x_mem_l - simp at x_mem_l - obtain ⟨x_mem_g', x_mem_l⟩ := x_mem_l - have x_mem_ball := l_mem _ x_mem_l - - rw [Subgroup.closure_iUnion] - rw [← S''_eq_S''inv] at x_mem_ball - simp at x_mem_ball - apply Subgroup.mem_iSup_of_mem (i := ⟨⟨x, x_mem_g'⟩, (by simp; apply x_mem_ball)⟩) - have my_spec := (s_list ⟨⟨x, x_mem_g'⟩, x_mem_ball⟩).choose_spec - simp at my_spec - conv => - arg 2 - rw [← my_spec] - - apply Subgroup.list_prod_mem - intro b b_mem - apply Subgroup.mem_closure_of_mem - apply Set.mem_union_left - simpa using b_mem - + have S''_generates : Subgroup.closure S'' = ⊤ := S_poly_data.S_generates + have S''_eq_S''inv : S'' = S''⁻¹ := S_poly_data.S_inv + obtain ⟨S, S_dist, S_finite, S_eq_Sinv, S_generates, S_one⟩ := + small_finite_generators n hn G S_poly_data + have S_union_Sinv : S ∪ S⁻¹ = S := by rw [← S_eq_Sinv]; simp have nontrivial_h: ∃ h: S, ∀ z: ℂ, h.val.val.val ≠ z • 1 := by by_contra! @@ -497,7 +547,7 @@ lemma central_trivial_virtually_abelian (n : ℕ) (hn : 2 ≤ n) (G : Subgroup ( have list_prod_trivial: ∃ z: ℂ, l.unattach.unattach.prod = z • 1 := by apply List.prod_induction (p := fun a => ∃ z: ℂ, a = z • 1) - . + · intro a b a_diag b_diag obtain ⟨a_z, a_eq⟩ := a_diag obtain ⟨b_z, b_eq⟩ := b_diag @@ -505,9 +555,9 @@ lemma central_trivial_virtually_abelian (n : ℕ) (hn : 2 ≤ n) (G : Subgroup ( rw [a_eq, b_eq] rw [mul_smul] simp - . use 1 + · use 1 simp - . + · intro x x_mem rw [List.mem_unattach] at x_mem obtain ⟨a, ha⟩ := x_mem @@ -548,111 +598,8 @@ lemma central_trivial_virtually_abelian (n : ℕ) (hn : 2 ≤ n) (G : Subgroup ( have poly_pos := S_poly_data.S_poly_const_pos - have my_map: ∃ a: ℕ, a ≥ 1 ∧ ∀ r ≥ 1, #(Finset.image s_to_map S_finite.toFinset.attach ^ r) ≤ a * r ^ (S_poly_data.S_poly_deg) := by - have new_try := poly_growth_equiv S_poly_data.S_poly_const S_poly_data.S_poly_deg (by omega) (S_poly_data.S_finite.toFinset) - (Finset.image (fun a => ⟨⟨(s_to_map a).val, by (apply SetLike.coe_mem)⟩, by ( - have foo := (s_to_map a).property - rw [Subgroup.mem_map] at foo - obtain ⟨x, x_mem, x_eq⟩ := foo - simp_rw [← x_eq] - simp [x_mem] - )⟩) S_finite.toFinset.attach) ?_ ?_ ?_ ?_ - . - obtain ⟨b, b_pos, hb⟩ := new_try - use b - refine ⟨b_pos, ?_⟩ - intro r hr - rw [← Finset.card_image_of_injective (f := Subgroup.subtype _) _ (by apply subtype_injective)] - rw [Finset.image_pow] - rw [Finset.image_image] - simp - conv => - arg 1 - arg 1 - arg 1 - equals Finset.image (Subgroup.subtype _) S_finite.toFinset => - ext a - rw [Finset.mem_image] - refine ⟨?_, ?_⟩ - . intro x - obtain ⟨y, y_mem, y_eq⟩ := x - rw [Finset.mem_image] - use y - rw [← y_eq] - simp [s_to_map] - . intro x_mem - rw [Finset.mem_image] at x_mem - obtain ⟨y, y_mem, y_eq⟩ := x_mem - use ⟨y, y_mem⟩ - simp [s_to_map] - exact y_eq - - - specialize hb r hr - rw [← Finset.card_image_of_injective (f := Subgroup.subtype _) _ (by apply subtype_injective)] at hb - rw [Finset.image_pow] at hb - rw [← Finset.card_image_of_injective (f := Subgroup.subtype _) _ (by apply subtype_injective)] at hb - rw [Finset.image_pow] at hb - conv at hb => - arg 1 - arg 1 - arg 1 - equals Finset.image (Subgroup.subtype _) S_finite.toFinset => - ext a - rw [Finset.mem_image] - refine ⟨?_, ?_⟩ - . intro x - obtain ⟨y, y_mem, y_eq⟩ := x - rw [Finset.mem_image] - use y - rw [← y_eq] - simp [s_to_map] - rw [Finset.image_image] at y_mem - rw [Finset.mem_image] at y_mem - obtain ⟨z, z_mem, z_eq⟩ := y_mem - simp at z_eq - rw [← z_eq] - simp [s_to_map] - have z_prop := z.property - rw [Set.Finite.mem_toFinset] at z_prop - exact z_prop - . intro x_mem - rw [Finset.mem_image] at x_mem - obtain ⟨y, y_mem, y_eq⟩ := x_mem - use y - refine ⟨?_, y_eq⟩ - rw [Finset.image_image] - rw [Finset.mem_image] - simp at y_mem - use ⟨y, by simp [y_mem]⟩ - simp [s_to_map] - exact hb - . - have fintype_s: Fintype ↑S_poly_data.S := by - refine Set.Finite.fintype ?_ - exact S_poly_data.S_finite - - - simp - conv => - rhs - unfold Set.Finite.toFinset - equals (S_poly_data.S).toFinset => - ext a - simp - nth_rw 1 [S_poly_data.S_inv] - simp - . - simp - apply S_poly_data.S_one - . - simp - exact S_poly_data.S_generates - . - intro n hn - have S_poly := S_poly_data.S_poly n hn - exact S_poly - + have my_map := small_generators_growth n hn G S_poly_data S S_finite + s_to_map (by intro a; rfl) obtain ⟨new_const, new_const_pos, h_poly_new_const⟩ := my_map @@ -700,146 +647,29 @@ lemma central_trivial_virtually_abelian (n : ℕ) (hn : 2 ≤ n) (G : Subgroup ( S := (((Finset.image s_to_map) S_finite.toFinset.attach : Finset _) : Set _) S_generates := by - simp - have orig_S'' := S''_generates - apply_fun (Subgroup.map (G' n (H_n_eps hn) G).subtype) at S''_generates - conv at S''_generates => - rhs - equals (G' n (H_n_eps hn) G) => - ext a - simp - - apply_fun (Subgroup.map ({ - toFun := fun a => (⟨a.val, (by - have prop := a.property - rw [Subgroup.mem_map] at prop - obtain ⟨x, x_mem, x_eq⟩ := prop - rw [← x_eq] - simp - )⟩ : G), - map_one' := by - simp - map_mul' := by - intro a b - simp - })) using (?_) - . conv => - rhs - equals (G' n (H_n_eps hn) G) => - ext a - rw [Subgroup.mem_map] - refine ⟨?_, ?_⟩ - . - intro exists_x - obtain ⟨x, x_mem, a_eq⟩ := exists_x - simp at a_eq - have x_prop := x.property - rw [Subgroup.mem_map] at x_prop - obtain ⟨y, y_mem, x_eq_y⟩ := x_prop - rw [← a_eq] - conv => - arg 2 - simp [← x_eq_y] - exact y_mem - . intro a_mem - use ⟨a, ?_⟩ - . refine ⟨by simp, ?_⟩ - simp - . rw [Subgroup.mem_map] - use ⟨a, ?_⟩ - . refine ⟨by simp; apply a_mem, ?_⟩ - simp - . simp - - conv => - rhs - rw [← S''_generates] - ext a - rw [Subgroup.mem_map] - refine ⟨?_, ?_⟩ - . - intro ha - simp at ha - simp - obtain ⟨b, b_mem, a_mem_g, b_mem_closure, a_eq_b⟩ := ha - use ?_ - . conv => - arg 2 - simp only [← a_eq_b] - - rw [orig_S''] - simp - . obtain ⟨b_mem, b_mem_g'⟩ := a_mem_g - rw [← a_eq_b] - simp [b_mem_g'] - . intro ha - have a_val_mem: a.val ∈ Subgroup.map G.subtype (G' n (H_n_eps hn) G) := by - simp at ha - simp - obtain ⟨a_mem_g', a_mem_closure⟩ := ha - apply a_mem_g' - - use ⟨a, ?_⟩ - . refine ⟨?_, by simp⟩ - rw [← Subgroup.mem_toSubmonoid] - rw [Subgroup.closure_toSubmonoid] - rw [← SetLike.mem_coe] - rw [Submonoid.closure_eq_image_prod] - rw [Set.mem_image] - rw [Subgroup.mem_map] at ha - obtain ⟨b, b_mem, a_eq_b⟩ := ha - have b_prop := b.property - conv at b_prop => - arg 1 - rw [← S_generates] - have b_list := mem_closure_prod_list S S_eq_Sinv b b_prop - obtain ⟨l, l_prod⟩ := b_list - use List.map (fun d => ⟨d.val, ?_⟩) l - . - refine ⟨?_, ?_⟩ - . - rw [Set.mem_setOf (a := List.map _ _)] - intro p p_mem - apply Set.mem_union_left - rw [List.mem_map] at p_mem - rw [Set.mem_range] - obtain ⟨z, z_mem, z_eq_p⟩ := p_mem - use ⟨z, by simp⟩ - rw [← z_eq_p] - . - conv => - rhs - simp [← a_eq_b] - conv => - rhs - simp [← l_prod] - apply Subtype.ext - simp - rw [List.comp_map] - simp - apply congrArg - ext i g - simp - - . - have my_mem := S_mem_G' d (by simp) - apply Subgroup.mem_map_of_mem - apply my_mem - . exact a_val_mem + let L := Subgroup.map G.subtype (G' n (H_n_eps hn) G) + apply Subgroup.map_injective (f := L.subtype) Subtype.val_injective + rw [MonoidHom.map_closure] + have himg : L.subtype '' (Finset.image s_to_map S_finite.toFinset.attach : Set L) + = G.subtype '' S := by + ext u + constructor + · rintro ⟨t, ht, rfl⟩ + obtain ⟨a, ha, rfl⟩ := Finset.mem_image.mp ht + exact ⟨a.val, S_finite.mem_toFinset.mp a.property, rfl⟩ + · rintro ⟨g, hg, rfl⟩ + let a : S_finite.toFinset := ⟨g, S_finite.mem_toFinset.mpr hg⟩ + exact ⟨s_to_map a, Finset.mem_image.mpr ⟨a, by simp, rfl⟩, rfl⟩ + rw [himg, ← MonoidHom.map_closure, S_generates] + rw [← MonoidHom.range_eq_map, Subgroup.range_subtype] S_finite := by simp apply Set.finite_range S_one := by - simp - dsimp [S] - use 1 - use (by simp) - use (by apply Subgroup.one_mem) - use ?_ + rw [Finset.mem_coe, Finset.mem_image] + refine ⟨⟨1, S_finite.mem_toFinset.mpr S_one⟩, by simp, ?_⟩ simp [s_to_map] - apply Set.mem_union_right - simp S_inv := by intro s hs rw [Finset.mem_coe] at hs @@ -848,11 +678,11 @@ lemma central_trivial_virtually_abelian (n : ℕ) (hn : 2 ≤ n) (G : Subgroup ( obtain ⟨x, x_mem, s_eq⟩ := hs rw [Finset.mem_image] use ⟨x⁻¹, ?_⟩ - . + · simp rw [← s_eq] rfl - . simp + · simp nth_rw 1 [S_eq_Sinv] simp @@ -876,74 +706,31 @@ lemma central_trivial_virtually_abelian (n : ℕ) (hn : 2 ≤ n) (G : Subgroup ( S_poly := by simp apply h_poly_new_const - h := ⟨⟨h.val.val, by ( - have h_prop := h.property - simp only [S] at h_prop - simp - cases h_prop - . rename_i h_mem - . cases h_mem - . rename_i h_prop - dsimp [pre_S] at h_prop - rw [Set.mem_iUnion] at h_prop - obtain ⟨y, y_mem⟩ := h_prop - simp [-Set.mem_inv] at y_mem - have h_dist := S_dist h (by simp) - simp [G'] - apply Subgroup.mem_closure_of_mem - simp - simp only [Subtype.dist_eq, dist_eq_norm_sub] - exact h_dist - . rename_i h_prop - -- TODo: deduplicate - dsimp [pre_S] at h_prop - simp_rw [Set.iUnion_inv] at h_prop - rw [Set.mem_iUnion] at h_prop - obtain ⟨y, y_mem⟩ := h_prop - simp [-Set.mem_inv] at y_mem - have h_dist := S_dist h (by simp) - simp [G'] - apply Subgroup.mem_closure_of_mem - simp - simp only [Subtype.dist_eq, dist_eq_norm_sub] - exact h_dist - . rename_i h_mem - simp at h_mem - simp [G'] - simp [h_mem] - )⟩, by - rw [Finset.mem_coe] - rw [Finset.mem_image] - use ⟨h.val, by simp⟩ - simp [s_to_map] - ⟩ + h := ⟨⟨h.val.val, Subgroup.mem_map_of_mem G.subtype (S_mem_G' h.val h.property)⟩, by + rw [Finset.mem_coe, Finset.mem_image] + refine ⟨⟨h.val, S_finite.mem_toFinset.mpr h.property⟩, by simp, ?_⟩ + rfl⟩ h_nontrivial := by simpa using h_nontrivial } - . - apply Subgroup.map_injective - simp - intro x y hxy - simpa using hxy - have contra := H_n_contradiction h_n_data (1 / 50) ?_ ?_ ?_ ?_ - . contradiction - . simp - . simp + · contradiction + · simp + · simp norm_num - . + · rw [← div_le_iff₀'] - . + · rw [le_inv_comm₀] - . + · simp simp [H_n_eps] left norm_num - . simp - . apply H_n_eps_pos - . simp - . + · simp + · apply H_n_eps_pos + · simp + · simp unfold H_n_eps @@ -954,10 +741,10 @@ lemma central_trivial_virtually_abelian (n : ℕ) (hn : 2 ≤ n) (G : Subgroup ( simp [h_n_data] norm_num apply div_lt_div₀ - . norm_num - . apply le_refl - . norm_num - . positivity + · norm_num + · apply le_refl + · norm_num + · positivity end HnEpsData diff --git a/Gromov/Unitary/HnEps.lean b/Gromov/Unitary/HnEps.lean index cfaf26d..83c61b0 100644 --- a/Gromov/Unitary/HnEps.lean +++ b/Gromov/Unitary/HnEps.lean @@ -14,8 +14,6 @@ public section open scoped Matrix.Norms.L2Operator ComplexInnerProductSpace -set_option linter.style.longLine false -set_option linter.style.commandStart false open Subgroup Pointwise Finset open scoped Pointwise Finset @@ -198,7 +196,6 @@ theorem theorem_3_8_h_n_left_S (data: HnData) (prev: Theorem3_8_Data data): ∃ -- 'h' is our initial element - we define ε in terms of ‖h - 1‖, so that we can obtain the proper bound -- for the commutators in the inductive case -set_option maxHeartbeats 500000 in @[expose] noncomputable def theorem_3_8_h_n (data : HnData) (n : ℕ): Theorem3_8_Data data := match hn : n with | 0 => { @@ -260,7 +257,6 @@ termination_by n decreasing_by simp -#print axioms theorem_3_8_h_n omit h_n_eps_data in lemma unitary_shrink {n : ℕ} (a b : Matrix.unitaryGroup (Fin n) ℂ): ‖(a * b).val - 1‖ ≤ ‖a.val - 1‖ + ‖b.val - 1‖ := by @@ -326,10 +322,9 @@ lemma H_n_pow_le {a k : ℕ } {m : ℕ} (a_k_lt : a + k ≤ m) (pows : Fin m | zero => simp [List.ofFn, List.prod_nil] | succ k ih => - simp only [ne_eq, List.ofFn_succ'] - simp only [Fin.coe_castSucc, Fin.val_last, List.concat_eq_append, List.prod_append, - List.prod_cons, List.prod_nil, mul_one, Subgroup.val_list_prod, - List.map_ofFn] + simp only [List.ofFn_succ'] + simp only [Fin.val_castSucc, Fin.val_last, List.concat_eq_append, List.prod_append, + List.prod_cons, List.prod_nil, mul_one] rw [Subgroup.coe_mul] grw [unitary_shrink] @@ -398,7 +393,7 @@ lemma H_n_prod_le_k {a k : ℕ } {m : ℕ} (a_k_lt : a + k + 1 ≤ m) (c : ℝ) field_simp [eps_ne_zero] grw [c_lt] - ring + ring_nf rfl · positivity · grw [H_n_eps_lt data.hd] @@ -418,8 +413,6 @@ lemma H_n_prod_le_k {a k : ℕ } {m : ℕ} (a_k_lt : a + k + 1 ≤ m) (c : ℝ) grw [pows_le] · omega -#print axioms H_n_prod_le_k -#synth Semiring (Matrix (Fin 2) (Fin 2) ℂ) end HnEpsData diff --git a/Gromov/Unitary/HnLowerBound.lean b/Gromov/Unitary/HnLowerBound.lean index 8c9b440..7ee4180 100644 --- a/Gromov/Unitary/HnLowerBound.lean +++ b/Gromov/Unitary/HnLowerBound.lean @@ -13,8 +13,6 @@ public section open scoped Matrix.Norms.L2Operator ComplexInnerProductSpace -set_option linter.style.longLine false -set_option linter.style.commandStart false open Subgroup Pointwise Finset open scoped Pointwise Finset @@ -63,7 +61,8 @@ lemma f_deriv (a: ℝ) (ha: 0 < 1 + a) (x: ℝ): (deriv (f a)) x = 2*a - (Real.l exact ha -lemma f_deriv_at_one (a: ℝ) (a_pos: 0 < a) (a_lt: a < 1) (ha: 0 < 1 + a): 0 < (deriv (f a) 1) := by +omit h_n_eps_data in +lemma f_deriv_at_one [_h_n_eps_data : HnEpsData] (a: ℝ) (a_pos: 0 < a) (a_lt: a < 1) (ha: 0 < 1 + a): 0 < (deriv (f a) 1) := by rw [f_deriv _ ha] grw [Real.log_le_sub_one_of_pos] · have a_mul_self := mul_lt_of_lt_one_left (a := a) (b := a) (by linarith) (by linarith) @@ -72,7 +71,8 @@ lemma f_deriv_at_one (a: ℝ) (a_pos: 0 < a) (a_lt: a < 1) (ha: 0 < 1 + a): 0 < simp [ha] -lemma f_deriv_lower (a: ℝ) (ha: 0 < 1 + a) (a_pos: 0 < a) (x: ℝ) (f_zero: (deriv (f a)) x = 0): (Real.log 2) / a ≤ x := by +omit h_n_eps_data in +lemma f_deriv_lower [_h_n_eps_data : HnEpsData] (a: ℝ) (ha: 0 < 1 + a) (a_pos: 0 < a) (x: ℝ) (f_zero: (deriv (f a)) x = 0): (Real.log 2) / a ≤ x := by have log_plus_le: Real.log (1 + a) ≤ a := by grw [Real.log_le_sub_one_of_pos] · simp @@ -112,28 +112,28 @@ lemma f_pos_on (a: ℝ) (ha: 0 < 1 + a) (a_pos: 0 < a) (a_lt: a < 1) (a_lt_log: have one_lt : 1 < Real.log (2) / a := by rw [lt_div_iff₀] - . simp + · simp exact a_lt_log - . exact a_pos + · exact a_pos have f_strict := strictMonoOn_of_deriv_pos (f := f a) (D := Set.Icc 1 ((Real.log (2 )) / a)) (by apply convex_Icc) ?_ ?_ - . + · intro x hx have f_lt := f_strict.lt_iff_lt (a := 1) (b := x) ?_ ?_ rw [f_one_eq_zero] at f_lt have x_prop := hx.left simp [x_prop] at f_lt - . exact f_lt - . simp + · exact f_lt + · simp linarith - . simp + · simp simp at hx refine ⟨by linarith, hx.right⟩ - . apply Continuous.continuousOn + · apply Continuous.continuousOn unfold f have one_plus: 1 + a ≠ 0 := by linarith fun_prop (disch:=assumption) - . + · intro x hx simp at hx @@ -154,30 +154,27 @@ lemma f_pos_on (a: ℝ) (ha: 0 < 1 + a) (a_pos: 0 < a) (a_lt: a < 1) (a_lt_log: rw [Set.mem_image] at deriv_zero obtain ⟨y, y_mem, y_deriv⟩ := deriv_zero have y_nonzero := deriv_nonzero y y_mem - . contradiction - . apply Continuous.continuousOn + · contradiction + · apply Continuous.continuousOn unfold f have one_plus: ∀ x: ℝ, 1 + a ≠ 0 := by intro x linarith fun_prop (disch:=assumption) - . simp + · simp refine ⟨by linarith, hx.right⟩ - . simp + · simp exact one_lt have not_zero := deriv_nonzero x ?_ - . exact lt_of_le_of_ne deriv_pos (id (Ne.symm not_zero)) - . simp + · exact lt_of_le_of_ne deriv_pos (id (Ne.symm not_zero)) + · simp refine ⟨by linarith, hx.right⟩ -#print axioms f_pos_on lemma H_n_single_pow_lower_bound {n : ℕ} {m : ℕ} (m_gt: 1 ≤ m) (data : HnData) (m_lt: m < (1/2) / ‖(theorem_3_8_h_n data n).g.val.val - 1‖) : ‖((theorem_3_8_h_n data n).g.val.val^m) - 1‖ ≥ ‖((theorem_3_8_h_n data n).g.val).val - 1‖ := by - push_cast - -- TODO: figure out how to get 'SubgroupClass.coe_zpow' to fire for Matrix.unitaryGroup conv => lhs @@ -227,15 +224,15 @@ lemma H_n_single_pow_lower_bound {n : ℕ} {m : ℕ} (m_gt: 1 ≤ m) (data : HnD grw [norm_sum_le] grw [Finset.sum_le_sum (g := fun i => ‖((theorem_3_8_h_n data n).g.val.val - 1)‖ ^ (i + 1 + 1) * (m.choose (i + 1 + 1)))] - . + · rw [← my_pow] have S_le : (1 + ‖((theorem_3_8_h_n data n).g).val.val - 1‖)^m - ((‖(theorem_3_8_h_n data n).g.val.val - 1‖) * (m : ℝ) + 1) ≤ (m - 1) * ‖(theorem_3_8_h_n data n).g.val.val - 1‖ := by by_cases m_eq_one: m = 1 - . + · simp [m_eq_one] rw [add_comm] - . + · have my_bound := f_pos_on ‖((theorem_3_8_h_n data n).g.val.val - 1)‖ ?_ ?_ ?_ ?_ m ?_ simp [f] at my_bound rw [two_mul] at my_bound @@ -248,23 +245,23 @@ lemma H_n_single_pow_lower_bound {n : ℕ} {m : ℕ} (m_gt: 1 ≤ m) (data : HnD grw [my_bound] simp ring_nf - . rfl - . positivity - . + · rfl + · positivity + · have val_ne := (theorem_3_8_h_n data n).g_dist_nonzero positivity - . + · have val_le := (theorem_3_8_h_n data n).g_dist grw [val_le] grw [H_n_eps_lt] norm_num - . + · have val_le := (theorem_3_8_h_n data n).g_dist grw [val_le] grw [H_n_eps_lt] norm_num linarith [Real.log_two_gt_d9] - . simp + · simp refine ⟨by omega, ?_⟩ grw [← ge_iff_le] grw [Real.log_two_gt_d9.gt] @@ -272,11 +269,11 @@ lemma H_n_single_pow_lower_bound {n : ℕ} {m : ℕ} (m_gt: 1 ≤ m) (data : HnD grw [m_lt] simp apply div_le_div₀ - . norm_num - . norm_num - . have ne_zero := (theorem_3_8_h_n data n).g_dist_nonzero + · norm_num + · norm_num + · have ne_zero := (theorem_3_8_h_n data n).g_dist_nonzero positivity - . rfl + · rfl rw [add_comm] @@ -300,29 +297,25 @@ lemma H_n_single_pow_lower_bound {n : ℕ} {m : ℕ} (m_gt: 1 ≤ m) (data : HnD ring_nf rfl - . intro i hi + · intro i hi grw [norm_mul_le] grw [norm_pow_le] nth_rw 2 [Matrix.l2_opNorm_def] grw [ContinuousLinearMap.opNorm_le_bound (M := m.choose (i + 1 + 1))] - . simp - . + · simp + · intro x simp - rw [Matrix.toEuclideanLin_apply] + rw [Matrix.toLpLin_apply] simp rw [norm_smul] simp - --apply_fun Norm.norm at my_pow -#synth DivisionMonoid (Matrix.unitaryGroup (Fin 2) ℂ) -#synth DivInvMonoid (Matrix (Fin 2) (Fin 2) ℂ) --- TODO: upstream to mathlib omit h_n_eps_data in lemma list_ofFn_drop {M: Type*} (a k: ℕ) (f: Fin (k + a) → M): (List.ofFn f).drop a = List.ofFn (fun (i: Fin k) => f ⟨a + i, by omega⟩) := by induction a with diff --git a/Gromov/Unitary/Packing.lean b/Gromov/Unitary/Packing.lean index 2b64abe..1f804fe 100644 --- a/Gromov/Unitary/Packing.lean +++ b/Gromov/Unitary/Packing.lean @@ -14,16 +14,100 @@ public section open scoped Matrix.Norms.L2Operator ComplexInnerProductSpace -set_option linter.style.longLine false -set_option linter.style.commandStart false open Subgroup Pointwise Finset open scoped Pointwise Finset open scoped commutatorElement IsMulCommutative -set_option synthInstance.maxHeartbeats 100000 in -set_option maxHeartbeats 500000 in +private lemma unitary_separated_maximal (n : ℕ) + (A : Set (Matrix.unitaryGroup (Fin n) ℂ)) (ε : ℝ) : + ∃ I, Maximal (fun I => I ⊆ A ∧ + ∀ x ∈ I, ∀ y ∈ I, x ≠ y → ‖x.val - y.val‖ ≥ ε) I := by + let I_sets := { I | I ⊆ A ∧ + ∀ x ∈ I, ∀ y ∈ I, x ≠ y → ‖x.val - y.val‖ ≥ ε } + apply zorn_subset I_sets + intro S S_subset S_chain + refine ⟨S.sUnion, ?_, ?_⟩ + · simp only [ne_eq, ge_iff_le, Set.mem_ofPred_eq, + Set.sUnion_subset_iff, Set.mem_sUnion, forall_exists_index, and_imp, I_sets] + + refine ⟨?_, ?_⟩ + · intro s hs + simp [I_sets] at S_subset + specialize S_subset hs + simp at S_subset + exact S_subset.1 + · simp [I_sets] at S_subset + intro a M M_mem_S a_mem_M b N N_mem_S b_mem_N a_neq_b + simp [IsChain] at S_chain + specialize S_chain M_mem_S N_mem_S + by_cases M_eq_N : M = N + · rw [M_eq_N] at a_mem_M + specialize S_subset N_mem_S + simp at S_subset + exact S_subset.2 a (by simp) (by simp [a_mem_M]) b (by simp) (by simp [b_mem_N]) (by simp [a_neq_b]) + · specialize S_chain M_eq_N + match S_chain with + | .inl h => + have a_mem_N := h a_mem_M + specialize S_subset N_mem_S + simp at S_subset + exact S_subset.2 a (by simp) (by simp [a_mem_N]) b (by simp) (by simp [b_mem_N]) (by simp [a_neq_b]) + | .inr h => + have b_mem_M := h b_mem_N + specialize S_subset M_mem_S + simp at S_subset + exact S_subset.2 a (by simp) (by simp [a_mem_M]) b (by simp) (by simp [b_mem_M]) (by simp [a_neq_b]) + + + · intro s hs + exact Set.subset_sUnion_of_subset S s (fun ⦃a⦄ a ↦ a) hs + +private lemma unitary_cosets_cover (n : ℕ) (ε : ℝ) + (G : Subgroup (Matrix.unitaryGroup (Fin n) ℂ)) + (I : Set (Matrix.unitaryGroup (Fin n) ℂ)) [Fintype I] + (i_mem_G : ∀ i ∈ I, i ∈ G) + (balls_cover : G.carrier ⊆ ⋃ g ∈ I, Metric.ball g ε) + (inter_subset : ∀ g, g ∈ G.carrier → + Metric.ball g ε ∩ G.carrier ⊆ + (fun x => g * x.val) '' (G' n ε G).carrier) : + (⋃ i ∈ I.toFinset.attach, (((⟨i.val, i_mem_G i.val (Set.mem_toFinset.mp i.property)⟩ : G) • (((G' n ε G)) : Set G)) : (Set G))) = (Set.univ : Set G) := by + have balls_inter_cover : G.carrier ⊆ ⋃ g ∈ I, ((Metric.ball g ε) ∩ G.carrier) := by + intro g hg + specialize balls_cover hg + simp only [Set.mem_iUnion] at balls_cover + obtain ⟨i, i_mem, g_mem_i⟩ := balls_cover + simp only [Set.mem_iUnion] + use i + use i_mem + exact Set.mem_inter g_mem_i hg + + + simp + ext a + simp only [Set.mem_univ, iff_true] + have a_mem_g : a.val ∈ G.carrier := by simp + specialize balls_inter_cover a_mem_g + simp only [Set.mem_iUnion] at balls_inter_cover + obtain ⟨i, i_mem, a_mem_i⟩ := balls_inter_cover + have hiG : i ∈ G.carrier := i_mem_G i i_mem + specialize inter_subset i hiG + have a_mem := inter_subset a_mem_i + simp only [Set.mem_image] at a_mem + obtain ⟨x, hx, a_eq_mul⟩ := a_mem + simp only [Set.mem_iUnion] + have i_mem_finset : i ∈ I.toFinset := by + exact Set.mem_toFinset.mpr i_mem + use ⟨i, i_mem_finset⟩ + simp + rw [Set.mem_smul_set] + use x + refine ⟨?_, ?_⟩ + · exact hx + · rw [Subtype.ext_iff] + simp [a_eq_mul] + open Pointwise in lemma volume_packing (n : ℕ) (hn : 0 < n) (ε : ℝ) (hε : 0 < ε) : ∃ C : ℝ, ∀ (G : Subgroup (Matrix.unitaryGroup (Fin n) ℂ)), (G' n ε G).FiniteIndex ∧ (G' n ε G).index ≤ C := by @@ -43,13 +127,13 @@ lemma volume_packing (n : ℕ) (hn : 0 < n) (ε : ℝ) (hε : 0 < ε) : let measure_haar : MeasureTheory.MeasureSpace (Matrix.unitaryGroup (Fin n) ℂ) := { volume := MeasureTheory.Measure.haarMeasure compacts_univ } - haveI hinv : (MeasureTheory.volume : MeasureTheory.Measure ↥(Matrix.unitaryGroup (Fin n) ℂ)).IsMulLeftInvariant := by + have hinv : (MeasureTheory.volume : MeasureTheory.Measure ↥(Matrix.unitaryGroup (Fin n) ℂ)).IsMulLeftInvariant := by show (MeasureTheory.Measure.haarMeasure compacts_univ).IsMulLeftInvariant infer_instance - haveI hfin : MeasureTheory.IsFiniteMeasure (MeasureTheory.volume : MeasureTheory.Measure ↥(Matrix.unitaryGroup (Fin n) ℂ)) := by + have hfin : MeasureTheory.IsFiniteMeasure (MeasureTheory.volume : MeasureTheory.Measure ↥(Matrix.unitaryGroup (Fin n) ℂ)) := by show MeasureTheory.IsFiniteMeasure (MeasureTheory.Measure.haarMeasure compacts_univ) infer_instance - haveI hopen : (MeasureTheory.volume : MeasureTheory.Measure ↥(Matrix.unitaryGroup (Fin n) ℂ)).IsOpenPosMeasure := by + have hopen : (MeasureTheory.volume : MeasureTheory.Measure ↥(Matrix.unitaryGroup (Fin n) ℂ)).IsOpenPosMeasure := by show (MeasureTheory.Measure.haarMeasure compacts_univ).IsOpenPosMeasure infer_instance @@ -58,7 +142,7 @@ lemma volume_packing (n : ℕ) (hn : 0 < n) (ε : ℝ) (hε : 0 < ε) : intro G -- We can find a maximal subset I where ||a - b|| ≥ ε for distinct a, b in I let I_sets := { S | S ⊆ G.carrier ∧ ∀ x ∈ S, ∀ y ∈ S, x ≠ y → ‖x.val - y.val‖ ≥ ε } - have maximal_I := zorn_subset I_sets ?_ + have maximal_I := unitary_separated_maximal n G.carrier ε · obtain ⟨I, hI⟩ := maximal_I have balls_cover : G.carrier ⊆ ⋃ (g ∈ I), Metric.ball g ε := by intro a ha @@ -66,9 +150,8 @@ lemma volume_packing (n : ℕ) (hn : 0 < n) (ε : ℝ) (hε : 0 < ε) : · have a_mem_I : a ∈ I := by have enlarge_I : {a} ∪ I ∈ I_sets := by simp [-Subtype.forall, I_sets] - simp [Maximal] at hI + simp only [Maximal] at hI have I_prop := hI.1 - simp [-Subtype.forall, I_sets] at I_prop refine ⟨?_, ?_⟩ · apply Set.insert_subset ha I_prop.1 · refine ⟨?_, ?_⟩ @@ -105,9 +188,8 @@ lemma volume_packing (n : ℕ) (hn : 0 < n) (ε : ℝ) (hε : 0 < ε) : -- Note - Vikman uses ε/2, but using ε/4 made things easier (it might actually be false for ε/2) have disjoint_balls : I.PairwiseDisjoint (fun g => Metric.ball g ((ε/2)/2)) := by intro a a_mem b b_mem a_neq_b - simp [Maximal] at hI + simp only [Maximal] at hI have I_prop := hI.1 - simp [-Subtype.forall, I_sets] at I_prop have dist_ge := I_prop.2 a a_mem b b_mem a_neq_b simp [Disjoint] intro X X_subset_A X_subset_B @@ -228,58 +310,18 @@ lemma volume_packing (n : ℕ) (hn : 0 < n) (ε : ℝ) (hε : 0 < ε) : have i_mem_G : ∀ i ∈ I, i ∈ G := by intro i i_mem - simp [Maximal] at hI + simp only [Maximal] at hI have I_prop := hI.1 - simp [-Subtype.forall, I_sets] at I_prop apply (I_prop.1 i_mem) - have cosets_cover : (⋃ i ∈ I.toFinset.attach, (((⟨i.val, i_mem_G i.val (Set.mem_toFinset.mp i.property)⟩ : G) • (((G' n ε G)) : Set G)) : (Set G))) = (Set.univ : Set G) := by - have balls_inter_cover : G.carrier ⊆ ⋃ g ∈ I, ((Metric.ball g ε) ∩ G.carrier) := by - intro g hg - specialize balls_cover hg - simp only [Set.mem_iUnion] at balls_cover - obtain ⟨i, i_mem, g_mem_i⟩ := balls_cover - simp only [Set.mem_iUnion] - use i - use i_mem - exact Set.mem_inter g_mem_i hg - - - simp - ext a - simp only [Set.mem_univ, iff_true] - have a_mem_g : a.val ∈ G.carrier := by simp - specialize balls_inter_cover a_mem_g - simp only [Set.mem_iUnion] at balls_inter_cover - obtain ⟨i, i_mem, a_mem_i⟩ := balls_inter_cover - have i_mem_G : i ∈ G.carrier := by - simp [Maximal] at hI - have I_prop := hI.1 - simp [-Subtype.forall, I_sets] at I_prop - apply (I_prop.1 i_mem) - specialize inter_subset i i_mem_G - have a_mem := inter_subset a_mem_i - simp only [Set.mem_image] at a_mem - obtain ⟨x, hx, a_eq_mul⟩ := a_mem - simp only [Set.mem_iUnion] - have i_mem_finset : i ∈ I.toFinset := by - exact Set.mem_toFinset.mpr i_mem - use ⟨i, i_mem_finset⟩ - simp - rw [Set.mem_smul_set] - use x - refine ⟨?_, ?_⟩ - · exact hx - · rw [Subtype.ext_iff] - simp [a_eq_mul] + have cosets_cover := unitary_cosets_cover n ε G I i_mem_G balls_cover inter_subset refine ⟨?_, ?_⟩ · apply Subgroup.finiteIndex_of_leftCoset_cover_const cosets_cover · have I_subset_G : I ⊆ G := by - simp [Maximal] at hI + simp only [Maximal] at hI have i_mem := hI.1 - simp [I_sets] at i_mem exact i_mem.1 @@ -306,44 +348,7 @@ lemma volume_packing (n : ℕ) (hn : 0 < n) (ε : ℝ) (hε : 0 < ε) : MeasureTheory.measure_lt_top _ _⟩ · exact cosets_cover - · intro S S_subset S_chain - refine ⟨S.sUnion, ?_, ?_⟩ - · simp only [ne_eq, ge_iff_le, Set.mem_setOf_eq, - Set.sUnion_subset_iff, Set.mem_sUnion, forall_exists_index, and_imp, I_sets] - - refine ⟨?_, ?_⟩ - · intro s hs - simp [I_sets] at S_subset - specialize S_subset hs - simp at S_subset - exact S_subset.1 - · simp [I_sets] at S_subset - intro a M M_mem_S a_mem_M b N N_mem_S b_mem_N a_neq_b - simp [IsChain] at S_chain - specialize S_chain M_mem_S N_mem_S - by_cases M_eq_N : M = N - · rw [M_eq_N] at a_mem_M - specialize S_subset N_mem_S - simp at S_subset - exact S_subset.2 a (by simp) (by simp [a_mem_M]) b (by simp) (by simp [b_mem_N]) (by simp [a_neq_b]) - · specialize S_chain M_eq_N - match S_chain with - | .inl h => - have a_mem_N := h a_mem_M - specialize S_subset N_mem_S - simp at S_subset - exact S_subset.2 a (by simp) (by simp [a_mem_N]) b (by simp) (by simp [b_mem_N]) (by simp [a_neq_b]) - | .inr h => - have b_mem_M := h b_mem_N - specialize S_subset M_mem_S - simp at S_subset - exact S_subset.2 a (by simp) (by simp [a_mem_M]) b (by simp) (by simp [b_mem_M]) (by simp [a_neq_b]) - - - · intro s hs - exact Set.subset_sUnion_of_subset S s (fun ⦃a⦄ a ↦ a) hs -#print axioms volume_packing @[expose] @@ -352,7 +357,6 @@ def FreshInnerProduct (V : Type*) := V instance (V : Type*) [base_comm : AddCommGroup V]: AddCommGroup (FreshInnerProduct V) := base_comm instance (V : Type*) [AddCommGroup V] [base_module : Module ℂ V]: Module ℂ (FreshInnerProduct V) := base_module -#synth InnerProductSpace ℂ (EuclideanSpace ℂ (Fin 2)) attribute [-simp] MeasureTheory.Measure.inv_eq_self diff --git a/Gromov/Unitary/WeylTrick.lean b/Gromov/Unitary/WeylTrick.lean index 8a2c528..7b5c66a 100644 --- a/Gromov/Unitary/WeylTrick.lean +++ b/Gromov/Unitary/WeylTrick.lean @@ -13,8 +13,6 @@ public section open scoped Matrix.Norms.L2Operator ComplexInnerProductSpace -set_option linter.style.longLine false -set_option linter.style.commandStart false open Subgroup Pointwise Finset open scoped Pointwise Finset @@ -23,8 +21,36 @@ open scoped commutatorElement IsMulCommutative attribute [local implicit_reducible] FreshInnerProduct -set_option maxHeartbeats 800000 in -set_option synthInstance.maxHeartbeats 500000 in +private lemma unitary_of_faithful_inner_representation + {K W : Type*} [Group K] [NormedAddCommGroup W] + [InnerProductSpace ℂ W] [FiniteDimensional ℂ W] + (ρ : K →* Module.End ℂ W) (hρ : Function.Injective ρ) + (hinner : ∀ g x y, ⟪ρ g x, ρ g y⟫ = ⟪x, y⟫) : + ∃ S : Subgroup (Matrix.unitaryGroup (Fin (Module.finrank ℂ W)) ℂ), + Nonempty (S ≃* K) := by + let b := stdOrthonormalBasis ℂ W + have hu (g : K) : LinearMap.toMatrix b.toBasis b.toBasis (ρ g) ∈ + Matrix.unitaryGroup (Fin (Module.finrank ℂ W)) ℂ := by + let i : W →ₗᵢ[ℂ] W := { + toLinearMap := ρ g + norm_map' := (LinearMap.norm_map_iff_inner_map_map (ρ g)).mpr (hinner g) } + let e := LinearIsometryEquiv.ofSurjective i + ((LinearMap.injective_iff_surjective).mp i.injective) + exact e.toMatrix_mem_unitaryGroup b b + let f : K →* Matrix.unitaryGroup (Fin (Module.finrank ℂ W)) ℂ := { + toFun := fun g => ⟨LinearMap.toMatrix b.toBasis b.toBasis (ρ g), hu g⟩ + map_one' := by apply Subtype.ext; simp + map_mul' := by + intro g h + apply Subtype.ext + simp [LinearMap.toMatrix_mul] } + have hf : Function.Injective f := by + intro g h heq + apply hρ + apply (LinearMap.toMatrix b.toBasis b.toBasis).injective + exact congrArg Subtype.val heq + exact ⟨f.range, ⟨(MonoidHom.ofInjective hf).symm⟩⟩ + lemma new_weyl_unitarian_trick {V : Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] [FiniteDimensional ℂ V] (H : Subgroup (V →L[ℂ] V)ˣ) [LocallyCompactSpace H] [CompactSpace H]: ∃ S : Subgroup ↥(Matrix.unitaryGroup (Fin (Module.finrank ℂ V)) ℂ), Nonempty (S ≃* H) := by let integrand := fun (v w : FreshInnerProduct V) (h : H) => ⟪(h.val.val v), (h.val.val w)⟫ have continuous_integrand : ∀ v w : FreshInnerProduct V, Continuous fun h : H => integrand v w h := by @@ -133,7 +159,7 @@ lemma new_weyl_unitarian_trick {V : Type*} [NormedAddCommGroup V] [InnerProductS simp at inner_q_zero have map_iff_zero := LinearMap.map_eq_zero_iff (f := q.val.val.toLinearMap) (x := x) ?_ · exact map_iff_zero.mp inner_q_zero - · -- TODO - find a better way of doing this + · let my_map := (ContinuousLinearMap.toLinearMapRingHom (R₁ := ℂ) (M₁ := V)).toMonoidHom let f_map := (Units.map my_map) q.val let f_as_equiv := fun f => (LinearMap.GeneralLinearGroup.toLinearEquiv (R := ℂ) (M := V) f) @@ -143,13 +169,12 @@ lemma new_weyl_unitarian_trick {V : Type*} [NormedAddCommGroup V] [InnerProductS exact injective_f · have foo := integrable_on x x simp [integrand] at foo - norm_cast norm_cast at foo apply MeasureTheory.Integrable.re at foo norm_cast at foo · rw [Pi.le_def] intro y - simpa using inner_self_nonneg (𝕜 := ℂ) (x := (y.val.val x)) + simp } · exact Ne.symm (NeZero.ne' (MeasureTheory.Measure.haar.inv Set.univ)) @@ -173,190 +198,21 @@ lemma new_weyl_unitarian_trick {V : Type*} [NormedAddCommGroup V] [InnerProductS rfl rw [hpt] exact MeasureTheory.integral_mul_right_eq_self (integrand v w) h - · -- finDimVectorspaceEquiv - have rank_eq := Module.finrank_eq_rank' ℂ (FreshInnerProduct V) - have V_equiv := (finDimVectorspaceEquiv (Module.finrank ℂ (FreshInnerProduct V)) rank_eq.symm).toContinuousLinearEquiv - let V_equiv_fresh : V ≃L[ℂ] (FreshInnerProduct V) := ContinuousLinearEquiv.ofFinrankEq ?_ - let V_fresh_arrow := ContinuousLinearEquiv.arrowCongr V_equiv_fresh V_equiv_fresh - - let new_H_matrix := ContinuousLinearMap.toLinearMap '' (Units.val '' H.carrier) - -- Deliberate defeq abuse, so that things line up with our integral (which is over plain V) - let new_H_coe : Set ((FreshInnerProduct V) →ₗ[ℂ] (FreshInnerProduct V)) := new_H_matrix - - - - have V_basis := stdOrthonormalBasis ℂ (FreshInnerProduct V) - - let H_matrix := (LinearMap.toMatrix V_basis.toBasis V_basis.toBasis) '' new_H_coe - - - have H_mem_unitary : ∀ h ∈ H_matrix, h ∈ Matrix.unitaryGroup (Fin (Module.finrank ℂ (FreshInnerProduct V))) ℂ := by - intro h h_mem - simp [H_matrix, new_H_coe, new_H_matrix] at h_mem - obtain ⟨u, u_mem, hu⟩ := h_mem - let a : FreshInnerProduct V →ₗ[ℂ] FreshInnerProduct V := (↑↑u : V →ₗ[ℂ] V) - have ha : (LinearMap.toMatrix V_basis.toBasis V_basis.toBasis) a = h := hu - rw [← ha, Matrix.mem_unitaryGroup_iff'] - -- `a` is the linear map underlying an element of `H`, so it preserves the new inner product. - have preserves_inner : ∀ (x y : FreshInnerProduct V), ⟪a x, a y⟫ = ⟪x, y⟫ := by - intro x y - exact v_preserves_inner ⟨u, u_mem⟩ x y - -- Preservation of the inner product means `adjoint a ∘ a = id`. - have adj : a.adjoint ∘ₗ a = LinearMap.id := by - apply LinearMap.ext - intro x - rw [LinearMap.comp_apply, LinearMap.id_apply] - apply ext_inner_right ℂ - intro y - rw [LinearMap.adjoint_inner_left] - exact preserves_inner x y - have hmat : star (LinearMap.toMatrix V_basis.toBasis V_basis.toBasis a) * - (LinearMap.toMatrix V_basis.toBasis V_basis.toBasis a) = 1 := by - rw [Matrix.star_eq_conjTranspose, ← LinearMap.toMatrix_adjoint, ← LinearMap.toMatrix_comp, - adj, LinearMap.toMatrix_id] - exact hmat - - - let H_matrix_subgroup : Subgroup (Matrix.unitaryGroup (Fin (Module.finrank ℂ V)) ℂ) := { - carrier := Set.range (fun (h : H_matrix) => ⟨h.val, H_mem_unitary h (by simp)⟩), - mul_mem' := by - intro X Y hx hy - simp - use (X * Y).val - simp - simp at hx - simp at hy - simp [H_matrix] - simp [H_matrix] at hx - simp [H_matrix] at hy - obtain ⟨a, ⟨p, p_mem, p_eq_a⟩, a_eq_x⟩ := hx - obtain ⟨b, ⟨q, q_mem, q_eq_b⟩, b_eq_y⟩ := hy - simp [new_H_coe, new_H_matrix] at q_mem - simp [new_H_coe, new_H_matrix] at p_mem - obtain ⟨y, y_mem, y_eq_q⟩ := q_mem - obtain ⟨x, x_mem, x_eq_p⟩ := p_mem - simp [new_H_coe, new_H_matrix] - refine ⟨?_, rfl⟩ - have hX : X.val = a := by rw [← a_eq_x] - have hY : Y.val = b := by rw [← b_eq_y] - refine ⟨x * y, H.mul_mem x_mem y_mem, ?_⟩ - rw [hX, hY, ← p_eq_a, ← q_eq_b, ← LinearMap.toMatrix_mul, ← x_eq_p, ← y_eq_q] - rfl - one_mem' := by - simp [H_matrix, new_H_coe, new_H_matrix] - refine ⟨1, H.one_mem, ?_⟩ - exact LinearMap.toMatrix_one _ - inv_mem' := by - simp - intro a ha b hb a_eq_b - refine ⟨a⁻¹, ?_, ?_⟩ - · simp [H_matrix, new_H_coe, new_H_matrix] at ⊢ hb - obtain ⟨u, u_mem, hz₀⟩ := hb - refine ⟨u⁻¹, H.inv_mem u_mem, ?_⟩ - rw [← a_eq_b, ← hz₀] - refine (Matrix.inv_eq_left_inv ?_).symm - rw [← LinearMap.toMatrix_mul] - convert LinearMap.toMatrix_one (R := ℂ) V_basis.toBasis using 2 - ext v - change (↑(u⁻¹) : V →L[ℂ] V) ((↑u : V →L[ℂ] V) v) = v - rw [← mul_apply_eq_comp, ← Units.val_mul, inv_mul_cancel, Units.val_one, - one_apply_eq_self] - · rw [Matrix.mem_unitaryGroup_iff] at ha - apply Matrix.inv_eq_right_inv at ha - rw [Subtype.ext_iff] - show a⁻¹ = star a - exact ha - } - - let remove_fresh (h : FreshInnerProduct V →ₗ[ℂ] FreshInnerProduct V): (V →ₗ[ℂ] V) := h - - · use H_matrix_subgroup - apply Nonempty.intro - exact { - toFun := fun h => ⟨{ - val := ((remove_fresh (h.val.val.toLin V_basis.toBasis V_basis.toBasis)).toContinuousLinearMap), - inv := ((remove_fresh (h.val.val⁻¹.toLin V_basis.toBasis V_basis.toBasis)).toContinuousLinearMap), - val_inv := by - simp [remove_fresh] - ext a - simp - conv => - lhs - equals Matrix.toLin V_basis.toBasis V_basis.toBasis (h.val.val * h.val.val⁻¹) a => - rw [eq_comm] - exact Matrix.toLin_mul_apply (v₁ := V_basis.toBasis) (v₂ := V_basis.toBasis) (v₃ := V_basis.toBasis) _ _ _ - rw [Matrix.mul_nonsing_inv] - · exact LinearMap.congr_fun (Matrix.toLin_one (v₁ := V_basis.toBasis)) a - · apply Matrix.UnitaryGroup.det_isUnit - inv_val := by - simp [remove_fresh] - ext a - simp - conv => - lhs - equals Matrix.toLin V_basis.toBasis V_basis.toBasis (h.val.val⁻¹ * h.val.val) a => - rw [eq_comm] - exact Matrix.toLin_mul_apply (v₁ := V_basis.toBasis) (v₂ := V_basis.toBasis) (v₃ := V_basis.toBasis) _ _ _ - rw [Matrix.nonsing_inv_mul] - · exact LinearMap.congr_fun (Matrix.toLin_one (v₁ := V_basis.toBasis)) a - · apply Matrix.UnitaryGroup.det_isUnit - }, by ( - simp [remove_fresh] - have h_prop := h.property - simp only [H_matrix_subgroup] at h_prop - rw [← Subgroup.mem_carrier] at h_prop - simp only [] at h_prop - rw [Set.mem_range] at h_prop - obtain ⟨a, ha⟩ := h_prop - have a_prop := a.property - simp only [H_matrix, new_H_coe, new_H_matrix] at a_prop - rw [Set.mem_image] at a_prop - obtain ⟨b, b_mem, b_eq_a⟩ := a_prop - obtain ⟨c, ⟨d, d_mem, d_eq_c⟩, c_eq_b⟩ := b_mem - simp_rw [← ha, ← b_eq_a] - simp - simp_rw [← c_eq_b, ← d_eq_c] - conv => - arg 2 - arg 1 - equals d.val => - rfl - - simp - rw [Subgroup.mem_carrier] at d_mem - exact d_mem - )⟩ - invFun := fun h => ⟨⟨(LinearMap.toMatrix V_basis.toBasis V_basis.toBasis) h.val.val.toLinearMap, by ( - apply H_mem_unitary - exact ⟨h.val.val.toLinearMap, ⟨h.val.val, ⟨h.val, h.property, rfl⟩, rfl⟩, rfl⟩ - )⟩, by ( - refine ⟨⟨_, ⟨h.val.val.toLinearMap, ⟨h.val.val, ⟨h.val, h.property, rfl⟩, rfl⟩, rfl⟩⟩, rfl⟩ - )⟩, - left_inv := by - intro h - simp - rw [Subtype.ext_iff] - simp [remove_fresh] - right_inv := by - intro h - simp - simp [remove_fresh] - ext a - simp - map_mul' := by - intro x y - simp [remove_fresh] - ext a - simp - exact Matrix.toLin_mul_apply (v₁ := V_basis.toBasis) (v₂ := V_basis.toBasis) - (v₃ := V_basis.toBasis) _ _ _ - } - · rfl + let ρ : H →* Module.End ℂ (FreshInnerProduct V) := { + toFun := fun h => h.val.val.toLinearMap + map_one' := rfl + map_mul' := fun _ _ => rfl } + have hρ : Function.Injective ρ := by + intro g h heq + apply Subtype.ext + apply Units.ext + ext v + exact DFunLike.congr_fun heq v + exact @unitary_of_faithful_inner_representation H (FreshInnerProduct V) + inferInstance normed_add new_inner finite_dimensional_fresh ρ hρ v_preserves_inner -#print axioms new_weyl_unitarian_trick -- A product of k unitary groups U(n_1) × U(n_2) × ... × U(n_k), where n_i < n for each n_i -#check Pi.commSemigroup diff --git a/Gromov/Unitary/Words.lean b/Gromov/Unitary/Words.lean index a8e8c75..5d00a13 100644 --- a/Gromov/Unitary/Words.lean +++ b/Gromov/Unitary/Words.lean @@ -14,8 +14,6 @@ public section open scoped Matrix.Norms.L2Operator ComplexInnerProductSpace -set_option linter.style.longLine false -set_option linter.style.commandStart false open Subgroup Pointwise Finset open scoped Pointwise Finset @@ -26,8 +24,6 @@ namespace HnEpsData variable [h_n_eps_data: HnEpsData] -set_option synthInstance.maxHeartbeats 80000 in -set_option maxHeartbeats 900000 in lemma words_distinct {m : ℕ} (k: Fin m) (c : ℝ) (c_pos : 0 < c) (c_lt : c < 1 / 40) (data : HnData) (pows_i : Fin m → ℕ) @@ -43,7 +39,6 @@ lemma words_distinct {m : ℕ} (k: Fin m) (c : ℝ) (c_pos : 0 < c) (c_lt : c < nth_rw 2 [← List.prod_take_mul_prod_drop (i := k)] at this rw [← List.prod_take_mul_prod_drop (i := k)] at this - -- TODO - generalize this and PR to mathlib conv at this => lhs lhs @@ -55,11 +50,11 @@ lemma words_distinct {m : ℕ} (k: Fin m) (c : ℝ) (c_pos : 0 < c) (c_lt : c < rw [List.getElem?_take] simp by_cases i_lt_k: i < k - . + · simp [i_lt_k] have i_lt_m: i < m := by omega simp [i_lt_m] - . simp [i_lt_k] + · simp [i_lt_k] conv at this => rhs @@ -72,11 +67,11 @@ lemma words_distinct {m : ℕ} (k: Fin m) (c : ℝ) (c_pos : 0 < c) (c_lt : c < rw [List.getElem?_take] simp by_cases i_lt_k: i < k - . + · simp [i_lt_k] have i_lt_m: i < m := by omega simp [i_lt_m] - . simp [i_lt_k] + · simp [i_lt_k] conv at this => @@ -156,7 +151,6 @@ lemma words_distinct {m : ℕ} (k: Fin m) (c : ℝ) (c_pos : 0 < c) (c_lt : c < rw [SubmonoidClass.coe_pow] grw [H_n_single_pow_lower_bound] - -- TODO : figure out why we can't use 'simp_rw' here conv => lhs rhs @@ -191,17 +185,17 @@ lemma words_distinct {m : ℕ} (k: Fin m) (c : ℝ) (c_pos : 0 < c) (c_lt : c < group grw [H_n_prod_le_k (c := c)] - . linarith - . + · linarith + · rw [add_assoc] rw [m_minus_k] simp - . exact c_pos - . exact c_lt - . exact pows_i_le - . + · exact c_pos + · exact c_lt + · exact pows_i_le + · linarith - . + · conv => lhs equals (-((pows_j k) : ℝ) + ((pows_i k) : ℝ)) => @@ -221,34 +215,34 @@ lemma words_distinct {m : ℕ} (k: Fin m) (c : ℝ) (c_pos : 0 < c) (c_lt : c < simp grw [c_lt] apply mul_le_mul - . norm_num - . + · norm_num + · rw [inv_le_inv₀] - . + · have my_prop := (theorem_3_8_h_n data k).g_dist exact my_prop - . apply H_n_eps_pos - . have my_prop := (theorem_3_8_h_n data k).g_dist_nonzero + · apply H_n_eps_pos + · have my_prop := (theorem_3_8_h_n data k).g_dist_nonzero positivity - . simp + · simp exact (H_n_eps_pos data.hd).le - . norm_num - . simp + · norm_num + · simp have foo := H_n_eps_pos data.hd linarith - . simp [-SubmonoidClass.coe_list_prod] + · simp [-SubmonoidClass.coe_list_prod] rw [ge_iff_le] at lhs_ge have one_tenth_lt: 1 / 10 * ‖(theorem_3_8_h_n data ↑k).g.val.val - 1‖ < (9 / 10) * ‖(theorem_3_8_h_n data ↑k).g.val.val - 1‖ := by apply mul_lt_mul - . norm_num - . simp - . + · norm_num + · simp + · have ne_zero := (theorem_3_8_h_n data ↑k).g_dist_nonzero positivity - . norm_num + · norm_num have add_swap (a b : ℕ): 1 + a + b = 1 + b + a := by @@ -281,7 +275,6 @@ lemma words_distinct {m : ℕ} (k: Fin m) (c : ℝ) (c_pos : 0 < c) (c_lt : c < simp at one_tenth_lt -#print axioms words_distinct -- ContinuousLinearMap.norm_id @@ -327,13 +320,13 @@ lemma H_n_pows_mem_ball_G {m : ℕ} simp [nested_list, replicate_pow] simp [Fin.sum_ofFn] grw [Finset.sum_le_card_nsmul (n := ⌊ (c * (H_n_eps data.hd)⁻¹)⌋₊)] - . simp - . intro x _ + · simp + · intro x _ apply pows_le use (fun i => full_list (i.cast (by omega))) - . + · conv => @@ -360,11 +353,10 @@ lemma H_n_pows_mem_ball_G {m : ℕ} dsimp [nested_list, replicate_pow] rw [List.prod_append] - . simp [-List.prod_flatten] - . omega + · simp [-List.prod_flatten] + · omega -#print axioms H_n_pows_mem_ball_G -- Unfold the commutators from theorem_3_8_h_n as a list of elements @[expose] @@ -380,8 +372,6 @@ noncomputable def theorem_3_8_h_n_list (data: HnData) (m: ℕ): List (data.S) := ++ (List.map (fun s => ⟨s.val⁻¹, by apply data.S_inv; simp⟩) (theorem_3_8_h_n_list data a)).reverse -set_option synthInstance.maxHeartbeats 80000 in -set_option maxHeartbeats 900000 in lemma theorem_3_8_h_n_list_prod_eq (data: HnData) (m: ℕ): (theorem_3_8_h_n_list data m).unattach.prod = (theorem_3_8_h_n data m).g := by induction m with | zero => @@ -409,7 +399,6 @@ lemma theorem_3_8_h_n_list_prod_eq (data: HnData) (m: ℕ): (theorem_3_8_h_n_lis group -- Note - this is (2^(m - 1)) in Vikman, since the list in indexed starting at 1 in the paper -set_option synthInstance.maxHeartbeats 1000000 in lemma theorem_3_8_h_n_list_length_initial_upper_bound (data: HnData) (m: ℕ): (theorem_3_8_h_n_list data (m)).length ≤ (3 * (2 ^ (m))) - 2 := by induction m with | zero => @@ -417,26 +406,25 @@ lemma theorem_3_8_h_n_list_length_initial_upper_bound (data: HnData) (m: ℕ): simp | succ a ih => unfold theorem_3_8_h_n_list - -- TODO - can grind somehow solve all of this? simp grw [ih] - ring + ring_nf rw [Nat.sub_mul] - ring + ring_nf zify rw [Nat.cast_sub] - . + · push_cast - ring + ring_nf rw [Nat.cast_sub] - . push_cast - ring + · push_cast + ring_nf linarith - . + · by_cases a_eq_zero: a = 0 - . + · simp [a_eq_zero] - . + · have a_eq_sub_succ: a = (a - 1) + 1 := by omega rw [a_eq_sub_succ] rw [Nat.pow_succ] @@ -445,18 +433,17 @@ lemma theorem_3_8_h_n_list_length_initial_upper_bound (data: HnData) (m: ℕ): rw [mul_assoc] apply Nat.le_mul_of_pos_right positivity - . + · rw [← ge_iff_le] grw [(Nat.one_le_pow _ _ ?_).ge] - . norm_num - . norm_num + · norm_num + · norm_num -- The c' constant from Vikman @[expose] def c' := 3 --- TODO - figure out how to merge this with 'theorem_3_8_h_n_list_length_initial_upper_bound' lemma theorem_3_8_h_n_list_length_upper_bound (data: HnData) (m: ℕ): (theorem_3_8_h_n_list data (m)).length ≤ c' * (2 ^ m) := by grw [theorem_3_8_h_n_list_length_initial_upper_bound data m] simp [c'] @@ -468,10 +455,10 @@ lemma list_concat_unattach {T: Type*} {p: T → Prop} (l: List { x: T // p x}) ( lemma H_n_pows_mem_ball_S {m : ℕ} - (m_gt: 0 < m) (data : HnData) (pows : Fin m → ℕ) + (_m_gt: 0 < m) (data : HnData) (pows : Fin m → ℕ) (c: ℝ) - (c_pos: 0 < c) - (c_lt: c < 1 / 40) + (_c_pos: 0 < c) + (_c_lt: c < 1 / 40) (pows_le : ∀ i : Fin m, (pows i) ≤ ⌊c * (H_n_eps data.hd)⁻¹⌋₊): (List.ofFn (fun (i : Fin (m)) => (theorem_3_8_h_n data i).g^(pows i))).prod.val ∈ Subtype.val '' (data.S ^ ( c' * (Nat.floor (c * (H_n_eps data.hd)⁻¹)) * m * (2 ^ m))) := by @@ -486,7 +473,7 @@ lemma H_n_pows_mem_ball_S {m : ℕ} have g_as_list_prod_eq_pow: g_as_s_list.unattach.prod = (List.ofFn (fun (i: Fin m) => (List.replicate (pows i) (theorem_3_8_h_n_list data i)).flatten.unattach.prod)).unattach.prod := by dsimp [g_as_s_list] - clear m_gt + clear _m_gt induction m with | zero => simp @@ -544,27 +531,26 @@ lemma H_n_pows_mem_ball_S {m : ℕ} rw [List.sum_ofFn] simp grw [Finset.sum_le_sum (g := fun i => (pows i) * c' * (2 ^ m))] - . + · grw [Finset.sum_le_card_nsmul (n := ⌊c * (H_n_eps data.hd)⁻¹⌋₊ * c' * (2^m))] - . + · simp - ring + ring_nf rfl - . + · intro i _ grw [pows_le] - . intro i _ + · intro i _ grw [theorem_3_8_h_n_list_length_upper_bound] - ring + ring_nf grw [i.isLt] - simp let padded_list := Fin.append (fun (i: Fin (g_as_s_list.length)) => g_as_s_list[i]) (fun (i: Fin (((c' * (Nat.floor (c * (H_n_eps data.hd)⁻¹)) * m * (2 ^ m)) - g_as_s_list.length))) => ⟨1, data.S_one⟩) refine ⟨?_, rfl⟩ - . + · use (fun i => padded_list (i.cast (by omega))) conv => lhs @@ -573,8 +559,8 @@ lemma H_n_pows_mem_ball_S {m : ℕ} apply congr (rfl) ext i g nth_rw 2 [List.ofFn_congr (n := (c' * ⌊c * (H_n_eps data.hd)⁻¹⌋₊ * m * 2 ^ m))] - . simp - . omega + · simp + · omega rw [List.ofFn_fin_append] @@ -589,7 +575,6 @@ lemma H_n_pows_mem_ball_S {m : ℕ} simp rw [g_list_prod] -#print axioms H_n_pows_mem_ball_S -- In Vikman, this is (1 + ⌊c * (H_n_eps data.hd)⁻¹⌋₊) (since the powers include the upper bound of c*ε ⁻¹) @@ -613,20 +598,19 @@ lemma H_n_ball_S_card {m : ℕ} rw [← my_card] apply Finset.card_le_card_of_injOn (f := fun pows => (List.ofFn (fun (i : Fin (m)) => (theorem_3_8_h_n data (i)).g^((pows i).val))).prod) - . + · intro pows _ simp - -- TODO - modify H_n_pows_mem_ball_S so that this can just be 'apply' have my_pows := H_n_pows_mem_ball_S m_gt data (fun i => (pows i).val) c c_pos c_lt ?_ - . + · rw [Set.mem_image] at my_pows obtain ⟨g, g_mem, g_eq⟩ := my_pows rw [← Subtype.ext_iff] at g_eq rw [← g_eq] exact g_mem - . intro i + · intro i simp - . + · intro pows_i _ pows_j _ contrapose intro pows_neq @@ -635,10 +619,9 @@ lemma H_n_ball_S_card {m : ℕ} have exists_minimal_k := exists_minimal_of_wellFoundedLT (fun (i: Fin m) => pows_i i ≠ pows_j i) pows_neq obtain ⟨k, k_minimal⟩ := exists_minimal_k - -- TODO - figure out why this pushes a goal of 'False' if we don't use 'generalizing' wlog pow_j_lt_i: (pows_j k).val < (pows_i k).val generalizing pows_i pows_j - . + · conv at k_minimal => arg 1 intro i @@ -646,42 +629,41 @@ lemma H_n_ball_S_card {m : ℕ} have words_neq := this (pows_j := pows_i) (pows_i := pows_j) (by simp) (by simp) ?_ k_minimal ?_ - . + · rw [eq_comm] exact words_neq - . + · obtain ⟨x, hx⟩ := pows_neq use x exact fun a ↦ hx (id (Eq.symm a)) - . + · have k_neq := k_minimal.prop omega - . + · simp at k_minimal have eps_pos := H_n_eps_pos data.hd have prods_neq := words_distinct (m := m) k c c_pos c_lt data (fun i => pows_i i) (fun i => pows_j i) ?_ ?_ ?_ ?_ - . simpa using prods_neq - . + · simpa using prods_neq + · intro i rw [← Nat.le_floor_iff] omega positivity - . intro i + · intro i rw [← Nat.le_floor_iff] omega positivity - . + · intro j hk have foo := Minimal.not_prop_of_lt k_minimal hk simp at foo exact congrArg Fin.val foo - . + · simpa using pow_j_lt_i -#print axioms H_n_ball_S_card abbrev swap_le {a b: ℝ} (_: a ≤ b): Prop := b < a diff --git a/Gromov/UnitaryGromov.lean b/Gromov/UnitaryGromov.lean index 2becf72..68e5e46 100644 --- a/Gromov/UnitaryGromov.lean +++ b/Gromov/UnitaryGromov.lean @@ -16,15 +16,238 @@ public section open scoped Matrix.Norms.L2Operator ComplexInnerProductSpace set_option linter.style.longLine false -set_option linter.style.commandStart false open Subgroup Pointwise Finset open scoped Pointwise Finset open scoped commutatorElement IsMulCommutative -set_option synthInstance.maxHeartbeats 100000 in -set_option maxHeartbeats 2000000 in +private noncomputable def image_growth_data + {X Y : Type*} [Group X] [DecidableEq X] [Group Y] [DecidableEq Y] + {P : Subgroup X} (D : SPolyData P) (f : P →* Y) : SPolyData f.range where + S := f.rangeRestrict '' D.S + S_one := ⟨1, D.S_one, map_one _⟩ + S_inv := by rw [← Set.image_inv, ← D.S_inv] + S_finite := D.S_finite.image _ + S_generates := by + rw [← MonoidHom.map_closure, D.S_generates] + exact Subgroup.map_top_of_surjective _ f.rangeRestrict_surjective + S_poly_const := D.S_poly_const + S_poly_const_pos := D.S_poly_const_pos + S_poly_deg := D.S_poly_deg + S_poly := by + intro r hr + rw [Set.Finite.toFinset_image, ← Finset.image_pow] + · exact Finset.card_image_le.trans (D.S_poly r hr) + · exact D.S_finite + +@[expose] +def map_S_data {G H: Type*} [Group G] [Group H] [DecidableEq G] [DecidableEq H] (A: Subgroup G) {f: G →* H} (S_data: SPolyData A): SPolyData (Subgroup.map f A) := { + S := f.subgroupMap A '' S_data.S + S_finite := by + apply Set.Finite.image + apply S_data.S_finite + S_one := by + simp only [Set.mem_image] + use 1 + simp + apply S_data.S_one + S_inv := by + rw [← Set.image_inv] + rw [← S_data.S_inv] + S_generates := by + rw [← MonoidHom.map_closure] + rw [S_data.S_generates] + rw [Subgroup.map_top_of_surjective] + apply MonoidHom.subgroupMap_surjective + S_poly_const := S_data.S_poly_const + S_poly_const_pos := S_data.S_poly_const_pos + S_poly_deg := S_data.S_poly_deg + S_poly := by + intro r hr + rw [Set.Finite.toFinset_image] + rw [← Finset.image_pow] + grw [Finset.card_image_le] + . + apply S_data.S_poly r hr + . exact S_data.S_finite +} + + +private noncomputable def subgroup_growth_data + {X : Type*} [Group X] [DecidableEq X] {P : Subgroup X} + (D : SPolyData P) (H : Subgroup P) (S : Finset H) + (hS : Subgroup.closure (S : Set H) = ⊤) : SPolyData H := by + let T := S ∪ S⁻¹ ∪ {1} + have hsym : D.S_finite.toFinset = D.S_finite.toFinset⁻¹ := by + ext x + simp + nth_rw 1 [D.S_inv] + simp + let growth := poly_growth_equiv D.S_poly_const D.S_poly_deg + (Nat.pos_of_ne_zero D.S_poly_const_pos.symm) D.S_finite.toFinset + (T.image H.subtype) hsym (by simpa using D.S_one) + (by simpa using D.S_generates) D.S_poly + let b := growth.choose + have hb := growth.choose_spec.1 + have hg := growth.choose_spec.2 + refine { + S := (T : Set H) + S_finite := T.finite_toSet + S_one := by simp [T] + S_inv := by simp [T, Set.union_comm] + S_generates := by simp [T, Subgroup.closure_union, hS] + S_poly_const := b + S_poly_const_pos := by omega + S_poly_deg := D.S_poly_deg + S_poly := ?_ } + intro r hr + simpa only [b, Finset.finite_toSet_toFinset, ← Finset.image_pow, + Finset.card_image_of_injective _ H.subtype_injective] using hg r hr + +private lemma central_element_virtually_abelian (n : ℕ) (hn : n ≠ 0) + (n_eq_one : n ≠ 1) + (ih : ∀ m, m < n → m ≠ 0 → ∀ H : Subgroup (Matrix.unitaryGroup (Fin m) ℂ), + H.FG → SPolyData H → ∃ N : Subgroup H, IsMulCommutative N ∧ N.FiniteIndex) + (G : Subgroup (Matrix.unitaryGroup (Fin n) ℂ)) (G_FG : G.FG) + (S_data : SPolyData G) + (nontrivial_central : ∃ g : G, (∀ z : ℂ, g.val.val ≠ z • 1) ∧ g ∈ Set.center G) : + ∃ N : Subgroup G, IsMulCommutative N ∧ N.FiniteIndex := by + obtain ⟨g, g_not_multiple_I, g_central⟩ := nontrivial_central + + + have all_mem_central : ∀ a : G, a ∈ Subgroup.centralizer {g} := by + intro a b b_mem + simp at b_mem + rw [b_mem] + rw [Set.mem_center_iff] at g_central + have g_comm := g_central.comm a + exact g_comm + + have n_ge_two : 2 ≤ n := by + omega + + have n_ne_zero: NeZero n := by + exact { out := hn } + obtain ⟨data⟩ := centralizer_iso G g g_not_multiple_I + + + -- The abelian subgroup of G_i. + -- TODO - we need to construct a generating set for the smaller subgroup + -- TODO - is there existing API for this in mathlib? + let g_to_central: G →* (Subgroup.centralizer {g.val}) := { + toFun := fun a => ⟨a, by + rw [Subgroup.mem_centralizer_iff] + simp + rw [Set.mem_center_iff] at g_central + rw [isMulCentral_iff] at g_central + have foo := (g_central.1) a + rw [commute_iff_eq] at foo + rw [Subtype.ext_iff] at foo + simpa using foo + ⟩, + map_one' := by + simp + map_mul' := by + simp + } + + have ha := data.ha + + let new_A_map := (Subgroup.subtype _).comp ((MonoidHom.fst _ _).comp (data.iso.toMonoidHom.comp g_to_central)) + let new_B_map := (Subgroup.subtype _).comp ((MonoidHom.snd _ _).comp (data.iso.toMonoidHom.comp g_to_central)) + + let first_new_data := image_growth_data S_data new_A_map + + have data_b_pos: 0 < data.b := by + have hab := data.hb + omega + + -- TODO - deduplicate 'first_new_data' and 'second_new_data' + let second_new_data := image_growth_data S_data new_B_map + + obtain ⟨first_subgroup, first_subgroup_abelian, first_subgroup_finite_index⟩ := ih data.a (by have hab := data.hab; omega) (by grind) (new_A_map.range) (by + rw [← Group.fg_iff_subgroup_fg] + rw [← Group.fg_iff_subgroup_fg] at G_FG + apply Group.fg_range + ) (first_new_data) + obtain ⟨second_subgroup, second_subgroup_abelian, second_subgroup_finite_index⟩ := ih data.b (by have hab := data.hab; omega) (by grind) (new_B_map.range) (by + rw [← Group.fg_iff_subgroup_fg] + rw [← Group.fg_iff_subgroup_fg] at G_FG + apply Group.fg_range + ) (second_new_data) + + let iso := Subgroup.map data.iso.symm.toMonoidHom + + let G_1 := (Subgroup.comap new_A_map.rangeRestrict first_subgroup) + let G_2 := (Subgroup.comap new_B_map.rangeRestrict second_subgroup) + + have g_1_finite_index: G_1.FiniteIndex := by + unfold G_1 + rw [Subgroup.finiteIndex_iff] + rw [Subgroup.index_comap_of_surjective] + . + rw [← Subgroup.finiteIndex_iff] + apply first_subgroup_finite_index + . exact MonoidHom.rangeRestrict_surjective new_A_map + + have g_2_finite_index: G_2.FiniteIndex := by + unfold G_2 + rw [Subgroup.finiteIndex_iff] + rw [Subgroup.index_comap_of_surjective] + . + rw [← Subgroup.finiteIndex_iff] + apply second_subgroup_finite_index + . exact MonoidHom.rangeRestrict_surjective new_B_map + + + let G' := G_1 ⊓ G_2 + + have G'_finite_index : G'.FiniteIndex := by + unfold G' + infer_instance + + + have G'_abeliean : IsMulCommutative G' := by + unfold G' + refine { is_comm := ?_ } + refine { comm := ?_ } + intro a b + have a_mem := a.property + have b_mem := b.property + rw [Subgroup.mem_inf] at a_mem b_mem + have a_first := a_mem.1 + have b_first := b_mem.1 + have a_second := a_mem.2 + have b_second := b_mem.2 + unfold G_1 at a_first b_first + unfold G_2 at a_second b_second + + rw [Subgroup.mem_comap] at a_first b_first + + have first_comm := first_subgroup_abelian.is_comm.comm ⟨_, a_first⟩ ⟨_, b_first⟩ + have second_comm := second_subgroup_abelian.is_comm.comm ⟨_, a_second⟩ ⟨_, b_second⟩ + + apply Subtype.ext + have hcentral : Function.Injective g_to_central := by + intro (x : G) (y : G) h + exact Subtype.ext (congrArg (fun z : ↥(centralizer {g.val}) => z.val) h) + apply hcentral + apply data.iso.injective + apply Prod.ext + · apply Subtype.ext + change new_A_map (a.val * b.val) = new_A_map (b.val * a.val) + have h := congrArg (fun x : ↥first_subgroup => x.val.val) first_comm + change new_A_map a.val * new_A_map b.val = new_A_map b.val * new_A_map a.val at h + simpa only [map_mul] using h + · apply Subtype.ext + change new_B_map (a.val * b.val) = new_B_map (b.val * a.val) + have h := congrArg (fun x : ↥second_subgroup => x.val.val) second_comm + change new_B_map a.val * new_B_map b.val = new_B_map b.val * new_B_map a.val at h + simpa only [map_mul] using h + + use G' + lemma compact_lie_virtually_abelian (n : ℕ) (hn : n ≠ 0) (G : Subgroup (Matrix.unitaryGroup (Fin n) ℂ)) (G_FG : G.FG) (S_data: SPolyData G): ∃ N : Subgroup G, IsMulCommutative N ∧ N.FiniteIndex := by @@ -70,203 +293,8 @@ lemma compact_lie_virtually_abelian (n : ℕ) (hn : n ≠ 0) (G : Subgroup (Matr } } · exact Subgroup.instFiniteIndexTop - · have nontrivial_centrer_implies_virtual (G : Subgroup ↥(Matrix.unitaryGroup (Fin n) ℂ)) (G_FG : G.FG) (S_data: SPolyData G) (nontrivial_central : ∃ g : G, (∀ z : ℂ, g.val.val ≠ z • 1) ∧ g ∈ Set.center G): ∃ N : Subgroup G, IsMulCommutative ↥N ∧ N.FiniteIndex := by - obtain ⟨g, g_not_multiple_I, g_central⟩ := nontrivial_central - - - have all_mem_central : ∀ a : G, a ∈ Subgroup.centralizer {g} := by - intro a b b_mem - simp at b_mem - rw [b_mem] - rw [Set.mem_center_iff] at g_central - have g_comm := g_central.comm a - exact g_comm - - have n_ge_two : 2 ≤ n := by - omega - - have n_ne_zero: NeZero n := by - exact { out := hn } - obtain ⟨data⟩ := centralizer_iso G g g_not_multiple_I - - - -- The abelian subgroup of G_i. - -- TODO - we need to construct a generating set for the smaller subgroup - -- TODO - is there existing API for this in mathlib? - let g_to_central: G →* (Subgroup.centralizer {g.val}) := { - toFun := fun a => ⟨a, by - rw [Subgroup.mem_centralizer_iff] - simp - rw [Set.mem_center_iff] at g_central - rw [isMulCentral_iff] at g_central - have foo := (g_central.1) a - rw [commute_iff_eq] at foo - rw [Subtype.ext_iff] at foo - simpa using foo - ⟩, - map_one' := by - simp - map_mul' := by - simp - } - - have ha := data.ha - - let new_A_map := (Subgroup.subtype _).comp ((MonoidHom.fst _ _).comp (data.iso.toMonoidHom.comp g_to_central)) - let new_B_map := (Subgroup.subtype _).comp ((MonoidHom.snd _ _).comp (data.iso.toMonoidHom.comp g_to_central)) - - let first_new_data: SPolyData (new_A_map.range) := { - S := new_A_map.rangeRestrict '' S_data.S, - S_one := by - simp only [Set.mem_image] - use 1 - refine ⟨?_, ?_⟩ - . apply S_data.S_one - . exact map_one _ - S_inv := by - rw [← Set.image_inv] - rw [← S_data.S_inv] - S_finite := by - apply Set.Finite.image - apply S_data.S_finite - S_generates := by - rw [← MonoidHom.map_closure] - rw [S_data.S_generates] - rw [Subgroup.map_top_of_surjective] - exact MonoidHom.rangeRestrict_surjective new_A_map - S_poly_const := S_data.S_poly_const - S_poly_const_pos := S_data.S_poly_const_pos - S_poly_deg := S_data.S_poly_deg - S_poly := by - intro r hr - rw [Set.Finite.toFinset_image] - rw [← Finset.image_pow] - grw [Finset.card_image_le] - . - apply S_data.S_poly r hr - . exact S_data.S_finite - } - - have data_b_pos: 0 < data.b := by - have hab := data.hb - omega - - -- TODO - deduplicate 'first_new_data' and 'second_new_data' - let second_new_data: SPolyData (new_B_map.range) := { - S := new_B_map.rangeRestrict '' S_data.S, - S_one := by - simp only [Set.mem_image] - use 1 - refine ⟨?_, ?_⟩ - . apply S_data.S_one - . exact map_one _ - S_inv := by - rw [← Set.image_inv] - rw [← S_data.S_inv] - S_finite := by - apply Set.Finite.image - apply S_data.S_finite - S_generates := by - rw [← MonoidHom.map_closure] - rw [S_data.S_generates] - rw [Subgroup.map_top_of_surjective] - exact MonoidHom.rangeRestrict_surjective new_B_map - S_poly_const := S_data.S_poly_const - S_poly_const_pos := S_data.S_poly_const_pos - S_poly_deg := S_data.S_poly_deg - S_poly := by - intro r hr - rw [Set.Finite.toFinset_image] - rw [← Finset.image_pow] - grw [Finset.card_image_le] - . - apply S_data.S_poly r hr - . exact S_data.S_finite - } - - obtain ⟨first_subgroup, first_subgroup_abelian, first_subgroup_finite_index⟩ := compact_lie_virtually_abelian (data.a) (by grind) (new_A_map.range) (by - rw [← Group.fg_iff_subgroup_fg] - rw [← Group.fg_iff_subgroup_fg] at G_FG - apply Group.fg_range - ) (first_new_data) - obtain ⟨second_subgroup, second_subgroup_abelian, second_subgroup_finite_index⟩ := compact_lie_virtually_abelian (data.b) (by grind) (new_B_map.range) (by - rw [← Group.fg_iff_subgroup_fg] - rw [← Group.fg_iff_subgroup_fg] at G_FG - apply Group.fg_range - ) (second_new_data) - - let iso := Subgroup.map data.iso.symm.toMonoidHom - - let G_1 := (Subgroup.comap new_A_map.rangeRestrict first_subgroup) - let G_2 := (Subgroup.comap new_B_map.rangeRestrict second_subgroup) - - have g_1_finite_index: G_1.FiniteIndex := by - unfold G_1 - rw [Subgroup.finiteIndex_iff] - rw [Subgroup.index_comap_of_surjective] - . - rw [← Subgroup.finiteIndex_iff] - apply first_subgroup_finite_index - . exact MonoidHom.rangeRestrict_surjective new_A_map - - have g_2_finite_index: G_2.FiniteIndex := by - unfold G_2 - rw [Subgroup.finiteIndex_iff] - rw [Subgroup.index_comap_of_surjective] - . - rw [← Subgroup.finiteIndex_iff] - apply second_subgroup_finite_index - . exact MonoidHom.rangeRestrict_surjective new_B_map - - - let G' := G_1 ⊓ G_2 - - have G'_finite_index : G'.FiniteIndex := by - unfold G' - infer_instance - - - have G'_abeliean : IsMulCommutative G' := by - unfold G' - refine { is_comm := ?_ } - refine { comm := ?_ } - intro a b - have a_mem := a.property - have b_mem := b.property - rw [Subgroup.mem_inf] at a_mem b_mem - have a_first := a_mem.1 - have b_first := b_mem.1 - have a_second := a_mem.2 - have b_second := b_mem.2 - unfold G_1 at a_first b_first - unfold G_2 at a_second b_second - - rw [Subgroup.mem_comap] at a_first b_first - - have first_comm := first_subgroup_abelian.is_comm.comm ⟨_, a_first⟩ ⟨_, b_first⟩ - have second_comm := second_subgroup_abelian.is_comm.comm ⟨_, a_second⟩ ⟨_, b_second⟩ - - rw [Subtype.ext_iff] - simp - apply_fun g_to_central - simp - apply_fun data.iso - . - simp - apply Prod.ext - . simp - rw [Subtype.ext_iff] - simp - exact congrArg (fun x : ↥first_subgroup => x.val.val) first_comm - . simp - rw [Subtype.ext_iff] - simp - exact congrArg (fun x : ↥second_subgroup => x.val.val) second_comm - . intro a b hab - simp [g_to_central] at hab - simpa using hab - - use G' + · have nontrivial_centrer_implies_virtual := central_element_virtually_abelian n hn + n_eq_one (fun m hm hm0 H hH D => compact_lie_virtually_abelian m hm0 H hH D) by_cases nontrivial_central : ∃ g : G, (∀ z : ℂ, g.val.val ≠ z • 1) ∧ g ∈ Set.center G · exact nontrivial_centrer_implies_virtual G G_FG S_data nontrivial_central · -- Case two - we have no non-trivial central elements @@ -290,80 +318,11 @@ lemma compact_lie_virtually_abelian (n : ℕ) (hn : n ≠ 0) (G : Subgroup (Matr obtain ⟨pre_S, h_pre_S⟩ := G'_fg - have pos := S_data.S_poly_const_pos - have my_equiv := poly_growth_equiv S_data.S_poly_const S_data.S_poly_deg (by omega) - S_data.S_finite.toFinset (Finset.image (Subgroup.subtype _) (pre_S ∪ pre_S⁻¹ ∪ {1})) ?_ ?_ (by simp [S_data.S_generates]) S_data.S_poly - - obtain ⟨b, hb, new_poly⟩ := my_equiv - - let S_data_G': SPolyData ((G' n ε G)) := { - S := pre_S ∪ pre_S⁻¹ ∪ {1}, - S_finite := by simp, - S_generates := by - rw [Subgroup.closure_union] - rw [Subgroup.closure_union] - simp [h_pre_S] - S_one := by - simp - S_inv := by - simp - rw [Set.union_comm] - S_poly_const := b - S_poly_const_pos := by omega - S_poly_deg := S_data.S_poly_deg - S_poly := by - intro r hr - unfold Set.Finite.toFinset - specialize new_poly r hr - rw [← Finset.image_pow] at new_poly - rw [Finset.card_image_of_injective] at new_poly - -- TODO(mathlib) - figure out what @[norm_cast] attribute to apply to make 'norm_cast' work with the {1} set - have one_eq: ({1}: Set (G' n ε G)) = ({1}: Finset (G' n ε G)) := by simp - norm_cast - simp_rw [one_eq] - norm_cast - . simpa using new_poly - . exact subtype_injective (G' n ε G) - } - - let map_set (Q: Finset (G' n ε G)) := Finset.image (fun a => (⟨a.val, by simp⟩ : (Subgroup.map G.subtype (G' n ε G)))) Q - let other := G.subtype '' (((G' n ε G).subtype) '' (pre_S)) - + let S_data_G' := subgroup_growth_data S_data (G' n ε G) pre_S h_pre_S by_cases G'_nontrivial_central : ∃ g : (G' n ε G), (∀ z : ℂ, g.val.val.val ≠ z • 1) ∧ g ∈ Set.center (G' n ε G) · - let foo := S_data_G'.S - let bar := G.subtype.subgroupMap (G' n ε G) - have subtype_S_data: SPolyData (Subgroup.map G.subtype (G' n ε G)) := { - S := (G.subtype.subgroupMap (G' n ε G)) '' S_data_G'.S - S_finite := by - apply Set.Finite.image - apply S_data_G'.S_finite - S_one := by - simp only [Set.mem_image] - use 1 - simp - apply S_data_G'.S_one - S_inv := by - rw [← Set.image_inv] - rw [← S_data_G'.S_inv] - S_generates := by - rw [← MonoidHom.map_closure] - rw [S_data_G'.S_generates] - rw [Subgroup.map_top_of_surjective] - exact MonoidHom.subgroupMap_surjective G.subtype (G' n ε G) - S_poly_const := S_data_G'.S_poly_const - S_poly_const_pos := S_data_G'.S_poly_const_pos - S_poly_deg := S_data_G'.S_poly_deg - S_poly := by - intro r hr - rw [Set.Finite.toFinset_image] - rw [← Finset.image_pow] - grw [Finset.card_image_le] - . - apply S_data_G'.S_poly r hr - . exact S_data_G'.S_finite - } + let subtype_S_data := map_S_data (f := G.subtype) (G' n ε G) S_data_G' have G'_virtual := nontrivial_centrer_implies_virtual (Subgroup.map G.subtype (G' n ε G)) (by have G'_finite := G_eps.1 @@ -415,59 +374,12 @@ lemma compact_lie_virtually_abelian (n : ℕ) (hn : n ≠ 0) (G : Subgroup (Matr have target := HnEpsData.central_trivial_virtually_abelian n (by omega) G G_FG ?_ G_eps.1 S_data_G' ?_ · exact target · intro g hg - simp only [ne_eq, not_exists, not_and] at G'_nontrivial_central - specialize G'_nontrivial_central g - rw [← not_imp_not] at G'_nontrivial_central - simp at G'_nontrivial_central - exact G'_nontrivial_central hg - . rfl - . - ext a - simp - nth_rw 1 [S_data.S_inv] - simp - . simp - apply S_data.S_one -termination_by (n, G.index) -decreasing_by - · apply Prod.Lex.left - have hab := data.hab - grind - . apply Prod.Lex.left - have hab := data.hab - grind -#print axioms compact_lie_virtually_abelian - -@[expose] -def map_S_data {G H: Type*} [Group G] [Group H] [DecidableEq G] [DecidableEq H] (A: Subgroup G) {f: G →* H} (S_data: SPolyData A): SPolyData (Subgroup.map f A) := { - S := f.subgroupMap A '' S_data.S - S_finite := by - apply Set.Finite.image - apply S_data.S_finite - S_one := by - simp only [Set.mem_image] - use 1 - simp - apply S_data.S_one - S_inv := by - rw [← Set.image_inv] - rw [← S_data.S_inv] - S_generates := by - rw [← MonoidHom.map_closure] - rw [S_data.S_generates] - rw [Subgroup.map_top_of_surjective] - apply MonoidHom.subgroupMap_surjective - S_poly_const := S_data.S_poly_const - S_poly_const_pos := S_data.S_poly_const_pos - S_poly_deg := S_data.S_poly_deg - S_poly := by - intro r hr - rw [Set.Finite.toFinset_image] - rw [← Finset.image_pow] - grw [Finset.card_image_le] - . - apply S_data.S_poly r hr - . exact S_data.S_finite -} - -#print axioms HnEpsData.central_trivial_virtually_abelian + by_contra hc + apply G'_nontrivial_central + refine ⟨g, ?_, hg⟩ + intro z hz + exact hc ⟨z, hz⟩ + · simp only [S_data_G', subgroup_growth_data] + rfl +termination_by n +decreasing_by exact hm diff --git a/Gromov/VWrapper.lean b/Gromov/VWrapper.lean index c37f7e3..847b5f4 100644 --- a/Gromov/VWrapper.lean +++ b/Gromov/VWrapper.lean @@ -12,11 +12,6 @@ used to locate a scale at which the growth of `V` is almost multiplicative. public section -set_option linter.style.cdot false -set_option linter.style.whitespace false -set_option linter.style.longLine false -set_option linter.flexible false -set_option linter.style.emptyLine false open scoped Finset open scoped Pointwise @@ -99,80 +94,82 @@ lemma f_monotone_on (bas : Module.Basis ι ℝ V): MonotoneOn (f bas) (Set.Ici intro x hx y hy hxy unfold f grw [Finset.pow_subset_pow_right (n := y)] - . + · rw [mul_le_mul_iff_right₀] - . + · rw [Real.rpow_le_rpow_iff] - . + · apply matrix_det_montone - . + · apply Q_R_matrix_pos_def bas x (by simp [R'] at hx; exact hx) - . + · unfold Q_R_matrix rw [← map_sub] rw [← LinearMap.isPosSemidef_iff_posSemidef_toMatrix] apply Q_R_lin_sub_pos_semi_def simpa using hxy - . + · have foo := Q_R_matrix_pos_def bas x (by simp [R'] at hx; exact hx) grind [foo.det_pos] - . + · have foo := Q_R_matrix_pos_def bas y (by simp [R'] at hy; exact hy) grind [foo.det_pos] - . simp [dim] + · simp [dim] exact Module.finrank_pos - . + · simp apply Finset.Nonempty.pow apply S_nonempty - . apply Real.rpow_nonneg + · apply Real.rpow_nonneg have foo := Q_R_matrix_pos_def bas x (by simp [R'] at hx; exact hx) grind [foo.det_pos] - . apply hGS.one_mem - . exact hxy + · apply hGS.one_mem + · exact hxy -lemma h_montone_on (bas : Module.Basis ι ℝ V): MonotoneOn (h bas) (Set.Ici i₀) := by +omit [Nonempty ι] in +lemma h_montone_on [_nonempty : Nonempty ι] (bas : Module.Basis ι ℝ V): MonotoneOn (h bas) (Set.Ici i₀) := by unfold h rw [← Function.comp_def] apply MonotoneOn.comp - . apply Real.strictMonoOn_log.monotoneOn - . + · apply Real.strictMonoOn_log.monotoneOn + · rw [← Function.comp_def] apply MonotoneOn.comp - . apply f_monotone_on bas - . + · apply f_monotone_on bas + · conv => arg 1 equals fun n => 16 ^ n => simp apply (pow_right_monotone (by simp)).monotoneOn - . intro a ha + · intro a ha simp [i₀] at ha simp rw [Nat.clog_le_iff_le_pow] at ha - . + · rify at ha grw [Nat.le_ceil (a := R')] exact ha - . simp - . + · simp + · intro a ha simp simp at ha simp [f] apply mul_pos - . simp + · simp apply Finset.Nonempty.pow apply S_nonempty - . + · apply Real.rpow_pos_of_pos apply (Q_R_matrix_pos_def_i₀ bas _ ?_).det_pos rw [pow_le_pow_iff_right₀] - . exact ha - . simp + · exact ha + · simp -lemma growth_implies_lim_h (b : Module.Basis ι ℝ V) (d: ℕ) (h_growth: growth_bound b d): Filter.Tendsto (fun (i: ℕ) => (h b i - d * i * Real.log 16)) Filter.atTop Filter.atBot := by +omit [Nonempty ι] in +lemma growth_implies_lim_h [_nonempty : Nonempty ι] (b : Module.Basis ι ℝ V) (d: ℕ) (h_growth: growth_bound b d): Filter.Tendsto (fun (i: ℕ) => (h b i - d * i * Real.log 16)) Filter.atTop Filter.atBot := by unfold growth_bound my_expr at h_growth have pow_tendsto: Filter.Tendsto (fun n => 16 ^ n) Filter.atTop Filter.atTop := by apply StrictMono.tendsto_atTop @@ -191,9 +188,9 @@ lemma growth_implies_lim_h (b : Module.Basis ι ℝ V) (d: ℕ) (h_growth: growt rw [Real.log_div (by rw [mul_ne_zero_iff] refine ⟨?_, ?_⟩ - . simp + · simp grind [S_nonempty] - . + · have det_pos := (Q_R_matrix_pos_def_i₀ b (16 ^ (x + i₀)) (by rw [add_comm] rw [pow_add] @@ -204,9 +201,9 @@ lemma growth_implies_lim_h (b : Module.Basis ι ℝ V) (d: ℕ) (h_growth: growt )).det_pos rw [Real.rpow_ne_zero] - . grind - . grind - . + · grind + · grind + · norm_cast rw [inv_eq_zero] norm_cast @@ -220,7 +217,6 @@ lemma growth_implies_lim_h (b : Module.Basis ι ℝ V) (d: ℕ) (h_growth: growt simp exact comp_log -#print axioms growth_implies_lim_h @[expose] noncomputable def a (d: ℕ) := 4 * d * Real.log 16 @@ -234,11 +230,11 @@ lemma exists_j_0_for_h (b : Module.Basis ι ℝ V) (w d: ℕ) (hw: 0 < w) (hd: 0 have h_gt (N: ℕ): h b (i₀ + (3 * w * N)) ≥ 4 * d * w * N * (Real.log 16) + h b i₀ := by rw [h_sum] grw [← Finset.card_nsmul_le_sum (n := w * (a d))] - . + · simp simp [a] grind - . intro n hn + · intro n hn apply this have h_diff_ge (N: ℕ): h b (i₀ + (3 * w * N)) - d * (i₀ + 3 * w * N) * Real.log 16 ≥ d * (w * N - i₀) * (Real.log 16) + h b i₀ := by @@ -276,14 +272,14 @@ lemma exists_j_0_for_h (b : Module.Basis ι ℝ V) (w d: ℕ) (hw: 0 < w) (hd: 0 lhs equals 0 + negative_start => simp apply Nat.add_le_add - . simp - . + · simp + · conv => lhs equals 1 * negative_start => simp apply Nat.mul_le_mul - . grind - . simp + · grind + · simp ) have h_ge_one := h_diff_ge (max ⌈positive_start⌉₊ negative_start) @@ -316,17 +312,17 @@ lemma lemma_3_24 (b : Module.Basis ι ℝ V) (w d: ℕ) (hw: 0 < w) (hd: 0 < d) have h_m_diff_le: h b (m + w) - h b (m) ≤ h b (i₀ + 3 * w * (j_0 + 1)) - h b (i₀ + 3 * w * (j_0)) := by apply sub_le_sub - . + · apply h_montone_on b - . simp [m] + · simp [m] grind - . simp - . simp [m] + · simp + · simp [m] grind - . apply h_montone_on b - . simp [m] - . simp [m] - . simp [m] + · apply h_montone_on b + · simp + · simp [m] + · simp [m] have h_le_w_a_d : h b (m + w) - h b m ≤ w * (a d) := by grw [h_m_diff_le] @@ -335,8 +331,8 @@ lemma lemma_3_24 (b : Module.Basis ι ℝ V) (w d: ℕ) (hw: 0 < w) (hd: 0 < d) have w_a_le_h : w * (a d) ≤ h b (m + w) - h b m := by rw [h_sum.symm] grw [← Finset.card_nsmul_le_sum (n := (a d))] - . simp - . intro x hx + · simp + · intro x hx apply this simpa using hx grind @@ -346,22 +342,22 @@ lemma lemma_3_24 (b : Module.Basis ι ℝ V) (w d: ℕ) (hw: 0 < w) (hd: 0 < d) by_contra! have h_sum (N: ℕ) := Finset.sum_Ico_sub (f := fun n => h b (m + n)) (m := (2 * w)) (n := (3 * w)) (by grind) - simp only [Nat.Ico_zero_eq_range, add_zero, forall_const] at h_sum + simp only [forall_const] at h_sum have h_m_diff_le: h b (m + 3 * w) - h b (m + 2 * w) ≤ h b (i₀ + 3 * w * (j_0 + 1)) - h b (i₀ + 3 * w * (j_0)) := by apply sub_le_sub - . + · apply h_montone_on b - . simp [m] + · simp [m] grind - . simp - . simp [m] + · simp + · simp [m] grind - . apply h_montone_on b - . simp [m] - . simp [m] + · apply h_montone_on b + · simp + · simp [m] grind - . simp [m] + · simp [m] have h_le_w_a_d : h b (m + 3 * w) - h b (m + 2 * w) ≤ w * (a d) := by grw [h_m_diff_le] @@ -371,10 +367,10 @@ lemma lemma_3_24 (b : Module.Basis ι ℝ V) (w d: ℕ) (hw: 0 < w) (hd: 0 < d) rw [h_sum.symm] grw [← Finset.card_nsmul_le_sum (n := (a d))] - . simp + · simp rw [← Nat.sub_mul] simp - . intro x hx + · intro x hx apply this simp simp at hx @@ -385,20 +381,20 @@ lemma lemma_3_24 (b : Module.Basis ι ℝ V) (w d: ℕ) (hw: 0 < w) (hd: 0 < d) obtain ⟨i_2, h_i_2⟩ := exists_i2 have diff_i_lt: h b (i_2 + 1) - h b i_1 < w * (a d) := by grw [h_montone_on b _ _ (b := i₀ + 3 * w * (j_0 + 1))] - . + · apply LE.le.trans_lt ?_ h_j_0 apply sub_le_sub_left apply h_montone_on b - . simp - . simp + · simp + · simp grind - . grind - . simp at h_i_2 + · grind + · simp at h_i_2 grind - . simp + · simp simp at h_i_2 grind - . simp [m] + · simp have foo := h_i_1.1 simp at foo @@ -407,8 +403,8 @@ lemma lemma_3_24 (b : Module.Basis ι ℝ V) (w d: ℕ) (hw: 0 < w) (hd: 0 < d) have i_0_pos: 0 < i₀ := by simp [i₀] apply Nat.clog_pos - . simp - . simp [R'] + · simp + · simp [R'] rw [Nat.lt_ceil] simp [R'_] have r_pos := R'_pos V diff --git a/Gromov/Vendor/Carleson/ToMathlib/Analysis/Convolution.lean b/Gromov/Vendor/Carleson/ToMathlib/Analysis/Convolution.lean index dd8200d..cc1fba1 100644 --- a/Gromov/Vendor/Carleson/ToMathlib/Analysis/Convolution.lean +++ b/Gromov/Vendor/Carleson/ToMathlib/Analysis/Convolution.lean @@ -52,12 +52,13 @@ lemma lintegral_enorm_convolution_integrand_le_eLpNorm_mul_eLpNorm [AddGroup G] hg.comp_quasiMeasurePreserving <| quasiMeasurePreserving_sub_left μ x₀ have hL' : ∀ᵐ (x : G) ∂μ, ‖L (f x) (g (x₀ - x))‖ ≤ (1 : NNReal) * ‖f x‖ * ‖g (x₀ - x)‖ := by simpa using Filter.Eventually.of_forall (fun x ↦ hL x (x₀ - x)) - simpa [eLpNorm, eLpNorm', Function.comp_def] using - eLpNorm_le_eLpNorm_mul_eLpNorm'_of_norm hf hg' (L ·) _ hL' (hpqr := hpq) + have bound := eLpNorm_le_eLpNorm_mul_eLpNorm_of_norm + (L ·) 1 (by fun_prop) hf hg' hL' (hpqr := hpq) + exact lintegral_enorm_le_eLpNorm_one.trans (by simpa only [Function.comp_def, ENNReal.coe_one, one_mul] using bound) /-- If `MemLp f p μ` and `MemLp g q μ`, where `p` and `q` are Hölder conjugates, then the convolution of `f` and `g` exists everywhere. -/ -theorem ConvolutionExists.of_memLp_memLp [AddGroup G] [MeasurableAdd₂ G] +theorem ConvolutionExists.of_memLp_memLp_legacy [AddGroup G] [MeasurableAdd₂ G] [MeasurableNeg G] (μ : Measure G) [SFinite μ] [μ.IsNegInvariant] [μ.IsAddLeftInvariant] [μ.IsAddRightInvariant] {p q : ENNReal} (hpq : p.HolderConjugate q) (hL : ∀ (x y : G), ‖L (f x) (g y)‖ ≤ ‖f x‖ * ‖g y‖) (hf : AEStronglyMeasurable f μ) diff --git a/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Function/LpSeminorm/Basic.lean b/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Function/LpSeminorm/Basic.lean index df0289c..b18f60f 100644 --- a/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Function/LpSeminorm/Basic.lean +++ b/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Function/LpSeminorm/Basic.lean @@ -25,6 +25,10 @@ set_option linter.style.header false open MeasureTheory open scoped ENNReal +-- On the countable discrete groups used below, the new measurability guard +-- in Mathlib's eLpNorm is discharged by this existing theorem. +attribute [simp] AEStronglyMeasurable.of_discrete + variable {α ε E F G : Type*} {m m0 : MeasurableSpace α} {p : ℝ≥0∞} {q : ℝ} {μ ν : Measure α} [NormedAddCommGroup E] [NormedAddCommGroup F] [NormedAddCommGroup G] [ENorm ε] @@ -34,25 +38,18 @@ section MapMeasure variable {β : Type*} {mβ : MeasurableSpace β} {f : α → β} {g : β → E} -theorem eLpNormEssSup_map_measure' [MeasurableSpace E] [OpensMeasurableSpace E] +theorem eLpNormEssSup_map_measure' [MeasurableSpace E] [OpensMeasurableSpace E] [SecondCountableTopology E] (hg : AEMeasurable g (Measure.map f μ)) (hf : AEMeasurable f μ) : eLpNormEssSup g (Measure.map f μ) = eLpNormEssSup (g ∘ f) μ := essSup_map_measure hg.enorm hf -theorem eLpNorm_map_measure' [MeasurableSpace E] [OpensMeasurableSpace E] +theorem eLpNorm_map_measure' [MeasurableSpace E] [OpensMeasurableSpace E] [SecondCountableTopology E] (hg : AEMeasurable g (Measure.map f μ)) (hf : AEMeasurable f μ) : eLpNorm g p (Measure.map f μ) = eLpNorm (g ∘ f) p μ := by - by_cases hp_zero : p = 0 - · aesop - by_cases hp_top : p = ∞ - · rw [hp_top, eLpNorm_exponent_top] - exact eLpNormEssSup_map_measure' hg hf - simp_rw [eLpNorm_eq_lintegral_rpow_enorm hp_zero hp_top] - rw [lintegral_map' (hg.enorm.pow_const p.toReal) hf] - rfl + exact eLpNorm_map_measure hg.aestronglyMeasurable hf theorem eLpNorm_comp_measurePreserving' {ν : Measure β} [MeasurableSpace E] - [OpensMeasurableSpace E] (hg : AEMeasurable g ν) (hf : MeasurePreserving f μ ν) : + [OpensMeasurableSpace E] [SecondCountableTopology E] (hg : AEMeasurable g ν) (hf : MeasurePreserving f μ ν) : eLpNorm (g ∘ f) p μ = eLpNorm g p ν := Eq.symm <| hf.map_eq ▸ eLpNorm_map_measure' (hf.map_eq ▸ hg) hf.aemeasurable diff --git a/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Integral/MeanInequalities.lean b/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Integral/MeanInequalities.lean index 40fc8a4..fb8ba6c 100644 --- a/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Integral/MeanInequalities.lean +++ b/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Integral/MeanInequalities.lean @@ -13,19 +13,13 @@ public import Gromov.Vendor.Carleson.ToMathlib.MeasureTheory.Measure.Haar.Unique public import Gromov.Vendor.Carleson.ToMathlib.MeasureTheory.Measure.Prod /-! -# Vendored from the Carleson project +# Young's convolution inequality -Port of `Carleson/ToMathlib/MeasureTheory/Integral/MeanInequalities.lean` from - (branch `young-add-group`, commit `3b35c86`), which is -the non-abelian generalization of Young's convolution inequality. - -The `eLpNorm_Ioc_convolution_le_*` theorems at the end of the upstream file are omitted: they are -unused here and would drag in the whole `Carleson/ToMathlib/MeasureTheory/Integral/Periodic.lean` -(`liftIoc`) development. +Non-abelian convolution inequalities, including Hölder and Minkowski estimates. +Based on the Carleson project contributors' formalization of Young's inequality, +, commit `3b35c86`. -/ -set_option linter.style.header false - @[expose] public section open NNReal ENNReal MeasureTheory Finset @@ -51,7 +45,6 @@ theorem Lp_add_le_sum Lp_add_le _ _ _ hp _ ≤ _ := by gcongr --- Add after `lintegral_prod_norm_pow_le` /-- A version of Hölder with multiple arguments, allowing `∞` as an exponent. -/ theorem lintegral_prod_norm_pow_le' {α ι : Type*} [MeasurableSpace α] {μ : Measure α} {s : Finset ι} {f : ι → α → ℝ≥0∞} (hf : ∀ i ∈ s, AEMeasurable (f i) μ) @@ -69,7 +62,8 @@ theorem lintegral_prod_norm_pow_le' {α ι : Type*} [MeasurableSpace α] {μ : M lintegral_congr (fun a ↦ (Finset.mul_prod_erase s (f · a) hi₀).symm) _ ≤ eLpNorm (f i₀) (p i₀) μ * ∫⁻ (a : α), ∏ i ∈ s.erase i₀, f i a ∂μ := by rw [← lintegral_const_mul'', pi₀_eq_top] - · exact lintegral_mono_ae <| (ae_le_essSup (f i₀)).mono (fun a ha ↦ mul_le_mul_left ha _) + · rw [eLpNorm_exponent_top (hf i₀ hi₀).aestronglyMeasurable] + exact lintegral_mono_ae <| (ae_le_essSup (f i₀)).mono (fun a ha ↦ mul_le_mul_left ha _) · exact Finset.aemeasurable_fun_prod _ (fun i hi ↦ hf i (Finset.mem_of_mem_erase hi)) _ ≤ eLpNorm (f i₀) (p i₀) μ * ∏ i ∈ s.erase i₀, eLpNorm (f i) (p i) μ := by apply mul_right_mono @@ -91,15 +85,15 @@ theorem lintegral_prod_norm_pow_le' {α ι : Type*} [MeasurableSpace α] {μ : M convert ENNReal.lintegral_prod_norm_pow_le s hf' hp₁ hp₂ with a i₀ hi₀ i hi · rw [← ENNReal.rpow_mul, mul_inv_cancel₀, rpow_one] exact ENNReal.toReal_ne_zero.mpr ⟨p_ne_0 i₀ hi₀, (exists_top ⟨i₀, hi₀, ·⟩)⟩ - · simp [eLpNorm, eLpNorm', p_ne_0 i hi, p_ne_top i hi] + · simp [eLpNorm, eLpNorm', p_ne_0 i hi, p_ne_top i hi, (hf i hi).aestronglyMeasurable] /-- **Hölder's inequality** for functions `α → ℝ≥0∞`, using exponents in `ℝ≥0∞` -/ theorem lintegral_mul_le_eLpNorm_mul_eLqNorm {p q : ℝ≥0∞} (hpq : p.HolderConjugate q) {f g : α → ENNReal} (hf : AEMeasurable f μ) (hg : AEMeasurable g μ) : ∫⁻ (a : α), (f * g) a ∂μ ≤ eLpNorm f p μ * eLpNorm g q μ := by - -- adaptation note: `ENNReal.HolderConjugate` is now a class (`HolderTriple p q 1`), so the - -- upstream dot-notation API (`hpq.symm`, `hpq.conj_eq`, `hpq.toReal_of_ne_top`) is gone. - haveI := hpq + have := hpq + have hfm := hf.aestronglyMeasurable + have hgm := hg.aestronglyMeasurable simp_rw [Pi.mul_apply] have hp0 : p ≠ 0 := HolderConjugate.ne_zero p q have hq0 : q ≠ 0 := HolderConjugate.ne_zero q p @@ -109,14 +103,14 @@ theorem lintegral_mul_le_eLpNorm_mul_eLqNorm {p q : ℝ≥0∞} (hpq : p.HolderC _ ≤ ∫⁻ a, essSup f μ * g a ∂μ := lintegral_mono_ae <| (ae_le_essSup f).mono fun a ha ↦ mul_le_mul_left ha _ _ = essSup f μ * ∫⁻ a, g a ∂μ := lintegral_const_mul'' _ hg - _ = _ := by simp [eLpNorm, eLpNorm', eLpNormEssSup, hp, hq1] + _ = _ := by simp [eLpNorm, eLpNorm', eLpNormEssSup, hp, hq1, hfm, hgm] rcases eq_or_ne q ∞ with hq | hq · have hp1 : p = 1 := (HolderConjugate.eq_top_iff_eq_one q p).mp hq calc ∫⁻ a, f a * g a ∂μ _ ≤ ∫⁻ a, f a * essSup g μ ∂μ := lintegral_mono_ae <| (ae_le_essSup g).mono fun a ha ↦ mul_le_mul_right ha _ _ = (∫⁻ a, f a ∂μ) * essSup g μ := lintegral_mul_const'' _ hf - _ = _ := by simp [eLpNorm, eLpNorm', eLpNormEssSup, hp1, hq] + _ = _ := by simp [eLpNorm, eLpNorm', eLpNormEssSup, hp1, hq, hfm, hgm] -- Both exponents are finite: reduce to the real-exponent version. have hpt : 0 < p.toReal := ENNReal.toReal_pos hp0 hp have hqt : 0 < q.toReal := ENNReal.toReal_pos hq0 hq @@ -129,7 +123,7 @@ theorem lintegral_mul_le_eLpNorm_mul_eLqNorm {p q : ℝ≥0∞} (hpq : p.HolderC have : 0 < q.toReal⁻¹ := by positivity linarith convert ENNReal.lintegral_mul_le_Lp_mul_Lq μ hpq' hf hg - all_goals simp [eLpNorm, eLpNorm', hp, hq, hp0, hq0] + all_goals simp [eLpNorm, eLpNorm', hp, hq, hp0, hq0, hfm, hgm] /-- **Cauchy–Schwarz inequality** for functions `α → ℝ≥0∞` (Hölder's inequality squared). -/ theorem sq_lintegral_mul_le_mul_lintegral_sq {f g : α → ℝ≥0∞} @@ -168,15 +162,21 @@ universe u𝕜 uG uE uE' uF variable {𝕜 : Type u𝕜} {G : Type uG} [MeasurableSpace G] {μ : Measure G} {E : Type uE} {E' : Type uE'} {F : Type uF} +variable [Countable G] [MeasurableSingletonClass G] + +private theorem discrete_aestronglyMeasurable {Y : Type*} [TopologicalSpace Y] + (f : G → Y) : AEStronglyMeasurable f μ := AEStronglyMeasurable.of_discrete + +attribute [local simp] discrete_aestronglyMeasurable + variable [NormedAddCommGroup E] [NormedAddCommGroup E'] [NormedAddCommGroup F] {f : G → E} {g : G → E'} /-- If `MemLp f p μ` and `MemLp g q μ`, where `p` and `q` are Hölder conjugates, then the convolution of `f` and `g` exists everywhere. -This is `MeasureTheory.ConvolutionExists.of_memLp_memLp`, re-exported into the `ENNReal` -namespace to match the name used elsewhere in this development. -/ -alias ConvolutionExists.of_memLp_memLp := MeasureTheory.ConvolutionExists.of_memLp_memLp +This follows from Hölder's inequality with the conjugate exponents. -/ +alias ConvolutionExists.of_memLp_memLp := MeasureTheory.ConvolutionExists.of_memLp_memLp_legacy -- Used in the proof of `enorm_convolution_le_eLpNorm_mul_eLpNorm_mul_eLpNorm` open ENNReal in @@ -191,9 +191,8 @@ private lemma eLpNorm_eq_eLpNorm_rpow (h : G → E) {r e : ℝ} (r0 : 0 < r) (e0 have lt_top : ENNReal.ofReal (e * r) / ENNReal.ofReal (r - e) < ∞ := div_lt_top ofReal_ne_top <| (not_iff_not.mpr ofReal_eq_zero).mpr r_sub_e_pos.not_ge simp only [eLpNorm, eLpNorm', reduceIte, div_eq_zero_iff, ofReal_eq_zero, ofReal_ne_top, - lt_top.ne, er_pos.not_ge, e0.not_ge, or_self, enorm_eq_self, ← rpow_mul] - -- adaptation note: `field_simp` no longer sees through the `ENNReal.toReal` of the exponents, - -- so we compute them by hand first. + lt_top.ne, er_pos.not_ge, e0.not_ge, or_self, enorm_eq_self, ← rpow_mul, + discrete_aestronglyMeasurable, ite_true] have hrne : r - e ≠ 0 := r_sub_e_pos.ne' have hene : e ≠ 0 := e0.ne' have hrne0 : r ≠ 0 := r0.ne' @@ -215,6 +214,7 @@ variable {L : E →L[𝕜] E' →L[𝕜] F} -- Used to handle trivial case `c ≤ 0` when proving versions of Young's convolution inequality -- assuming `∀ (x y : G), ‖L (f x) (g y)‖ ≤ c * ‖f x‖ * ‖g y‖)` +omit [Countable G] [MeasurableSingletonClass G] in private theorem convolution_zero_of_c_nonpos [AddGroup G] {f : G → E} {g : G → E'} {c : ℝ} (hL : ∀ (x y : G), ‖L (f x) (g y)‖ ≤ c * ‖f x‖ * ‖g y‖) (hc : c ≤ 0) : f ⋆[L, μ] g = 0 := by have : ∀ (x y : G), L (f x) (g y) = 0 := @@ -233,13 +233,13 @@ private theorem eLpNorm_top_convolution_le_aux [AddGroup G] {p q : ℝ≥0∞} eLpNorm (f ⋆[L, μ] g) ∞ μ ≤ ENNReal.ofReal c * eLpNorm f p μ * eLpNorm g q μ := by by_cases hc : c ≤ 0 · simp [convolution_zero_of_c_nonpos hL hc] - push_neg at hc - rw [eLpNorm_exponent_top, eLpNormEssSup] + push Not at hc + rw [eLpNorm_exponent_top (discrete_aestronglyMeasurable _), eLpNormEssSup] refine essSup_le_of_ae_le _ (Filter.Eventually.of_forall fun x ↦ ?_) apply le_trans <| enorm_integral_le_lintegral_enorm _ calc ∫⁻ y, ‖(L (f y)) (g (x - y))‖ₑ ∂μ _ ≤ ∫⁻ y, ENNReal.ofReal c * ‖f y‖ₑ * ‖g (x - y)‖ₑ ∂μ := by - simp_rw [← ofReal_norm_eq_enorm, ← ENNReal.ofReal_mul hc.le] + simp_rw [← ofReal_norm, ← ENNReal.ofReal_mul hc.le] refine lintegral_mono (fun y ↦ ?_) rw [← ENNReal.ofReal_mul <| mul_nonneg hc.le (norm_nonneg _)] exact ENNReal.ofReal_le_ofReal <| hL y (x - y) @@ -251,6 +251,7 @@ private theorem eLpNorm_top_convolution_le_aux [AddGroup G] {p q : ℝ≥0∞} variable [AddGroup G] [TopologicalSpace G] [IsTopologicalAddGroup G] [BorelSpace G] [μ.IsAddHaarMeasure] [LocallyCompactSpace G] [SecondCountableTopology G] +omit [LocallyCompactSpace G] in /-- Special case of **Young's convolution inequality** when `r = ∞`. -/ theorem eLpNorm_top_convolution_le [MeasurableSpace E] [OpensMeasurableSpace E] [MeasurableSpace E'] [OpensMeasurableSpace E'] [μ.IsNegInvariant] {p q : ℝ≥0∞} @@ -259,8 +260,9 @@ theorem eLpNorm_top_convolution_le [MeasurableSpace E] [OpensMeasurableSpace E] eLpNorm (f ⋆[L, μ] g) ∞ μ ≤ ENNReal.ofReal c * eLpNorm f p μ * eLpNorm g q μ := by refine eLpNorm_top_convolution_le_aux hpq hf.enorm ?_ ?_ c hL · intro x; exact (hg.comp_quasiMeasurePreserving (quasiMeasurePreserving_sub_left μ x)).enorm - · intro x; exact eLpNorm_comp_measurePreserving' hg (μ.measurePreserving_sub_left x) + · intro x; exact eLpNorm_comp_measurePreserving hg.enorm.aestronglyMeasurable (μ.measurePreserving_sub_left x) +omit [LocallyCompactSpace G] in /-- Special case of **Young's convolution inequality** when `r = ∞`. -/ theorem eLpNorm_top_convolution_le' [μ.IsNegInvariant] {p q : ℝ≥0∞} (hpq : p.HolderConjugate q) {f : G → E} {g : G → E'} @@ -269,7 +271,7 @@ theorem eLpNorm_top_convolution_le' [μ.IsNegInvariant] {p q : ℝ≥0∞} eLpNorm (f ⋆[L, μ] g) ∞ μ ≤ ENNReal.ofReal c * eLpNorm f p μ * eLpNorm g q μ := by refine eLpNorm_top_convolution_le_aux hpq hf.enorm ?_ ?_ c hL · intro x; exact (hg.comp_quasiMeasurePreserving (quasiMeasurePreserving_sub_left μ x)).enorm - · intro x; apply eLpNorm_comp_measurePreserving hg (Measure.measurePreserving_sub_left μ x) + · intro x; exact eLpNorm_comp_measurePreserving hg.enorm.aestronglyMeasurable (Measure.measurePreserving_sub_left μ x) -- Auxiliary inequality used to prove versions with simpler conditions on `f` and `g` open ENNReal in @@ -285,10 +287,10 @@ private theorem enorm_convolution_le_eLpNorm_mul_eLpNorm_mul_eLpNorm_aux (eLpNorm g (.ofReal q) μ) ^ ((r - q) / r)) := by by_cases hc : c ≤ 0 · simp [convolution_zero_of_c_nonpos hL hc] - push_neg at hc + push Not at hc by_cases μ0 : μ = 0 · simp [μ0, convolution] - push_neg at μ0 + push Not at μ0 let F (i : Fin 3) : G → ℝ≥0∞ := match i with | 0 => fun y ↦ (‖f y‖ₑ ^ p * ‖g (x - y)‖ₑ ^ q) ^ (1 / r) @@ -363,6 +365,7 @@ private theorem enorm_convolution_le_eLpNorm_mul_eLpNorm_mul_eLpNorm_aux simp [eLpNorm, eLpNorm', lintegral_sub_left_eq_self (‖g ·‖ₑ ^ (ENNReal.ofReal q).toReal) x] open ENNReal in +omit [LocallyCompactSpace G] in /-- This inequality is used in the proof of Young's convolution inequality `eLpNorm_convolution_le_ofReal`. See `enorm_convolution_le_eLpNorm_mul_eLpNorm_mul_eLpNorm'` for a version assuming a.e. strong measurability instead. -/ @@ -380,6 +383,7 @@ theorem enorm_convolution_le_eLpNorm_mul_eLpNorm_mul_eLpNorm [MeasurableSpace E] (fun x ↦ (hg.comp_quasiMeasurePreserving <| quasiMeasurePreserving_sub_left μ x).enorm) c hL x open ENNReal in +omit [LocallyCompactSpace G] in /-- This inequality is used in the proof of Young's convolution inequality `eLpNorm_convolution_le_ofReal'`. -/ theorem enorm_convolution_le_eLpNorm_mul_eLpNorm_mul_eLpNorm' @@ -520,7 +524,7 @@ theorem eLpNorm_convolution_le_of_norm_le_mul [MeasurableSpace E] [OpensMeasurab eLpNorm (f ⋆[L, μ] g) r μ ≤ .ofReal c * eLpNorm f p μ * eLpNorm g q μ := by refine eLpNorm_convolution_le_of_norm_le_mul_aux hp hq hr hpqr hf.enorm ?_ ?_ ?_ c hL · intro x; exact hg.enorm.comp_quasiMeasurePreserving (quasiMeasurePreserving_sub_left μ x) - · intro x; exact eLpNorm_comp_measurePreserving' hg (μ.measurePreserving_sub_left x) + · intro x; exact eLpNorm_comp_measurePreserving hg.enorm.aestronglyMeasurable (μ.measurePreserving_sub_left x) · exact hg.comp_quasiMeasurePreserving (quasiMeasurePreserving_sub μ μ) |>.enorm.pow_const _ /-- **Young's convolution inequality**: the `L^r` seminorm of a convolution `(f ⋆[L, μ] g)` is @@ -535,7 +539,7 @@ theorem eLpNorm_convolution_le_of_norm_le_mul' eLpNorm (f ⋆[L, μ] g) r μ ≤ .ofReal c * eLpNorm f p μ * eLpNorm g q μ := by refine eLpNorm_convolution_le_of_norm_le_mul_aux hp hq hr hpqr hf.enorm ?_ ?_ ?_ c hL · intro x; exact hg.enorm.comp_quasiMeasurePreserving (quasiMeasurePreserving_sub_left μ x) - · intro x; apply eLpNorm_comp_measurePreserving hg (μ.measurePreserving_sub_left x) + · intro x; exact eLpNorm_comp_measurePreserving hg.enorm.aestronglyMeasurable (μ.measurePreserving_sub_left x) · exact hg.comp_quasiMeasurePreserving (quasiMeasurePreserving_sub μ μ) |>.enorm.pow_const _ /-- **Young's convolution inequality**: the `L^r` seminorm of a convolution `(f ⋆[L, μ] g)` is diff --git a/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Measure/Haar/Unique.lean b/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Measure/Haar/Unique.lean index 3cd8144..cfa394d 100644 --- a/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Measure/Haar/Unique.lean +++ b/Gromov/Vendor/Carleson/ToMathlib/MeasureTheory/Measure/Haar/Unique.lean @@ -40,7 +40,7 @@ instance (priority := 100) IsHaarMeasure.isInvInvariant_of_isMulRightInvariant ( let c : ℝ≥0∞ := haarScalarFactor μ.inv μ have hc : μ.inv = c • μ := isMulLeftInvariant_eq_smul_of_regular μ.inv μ have : map Inv.inv (map Inv.inv μ) = c ^ 2 • μ := by - rw [← inv_def μ, hc, Measure.map_smul, ← inv_def μ, hc, smul_smul, pow_two] + rw [← inv_def μ, hc, Measure.map_smul c (by fun_prop), ← inv_def μ, hc, smul_smul, pow_two] have μeq : μ = c ^ 2 • μ := by simpa [map_map continuous_inv.measurable continuous_inv.measurable] using this have K : TopologicalSpace.PositiveCompacts G := Classical.arbitrary _ diff --git a/lake-manifest.json b/lake-manifest.json index d526394..69de6ca 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -1,96 +1,117 @@ -{"version": "1.2.0", +{ + "version": "1.2.0", "packagesDir": ".lake/packages", - "packages": - [{"url": "https://github.com/leanprover-community/mathlib4", + "packages": [ + { + "url": "https://github.com/leanprover-community/mathlib4.git", "type": "git", "subDir": null, - "scope": "leanprover-community", - "rev": "a6180e1994004a7c705114bcbebaf5fff4b8384d", + "scope": "", + "rev": "d13f23b723b8a846827a245b89c10fc7d3f11612", "name": "mathlib", "manifestFile": "lake-manifest.json", - "inputRev": "a6180e1994004a7c705114bcbebaf5fff4b8384d", + "inputRev": "d13f23b723b8a846827a245b89c10fc7d3f11612", "inherited": false, - "configFile": "lakefile.lean"}, - {"url": "https://github.com/leanprover-community/plausible", + "configFile": "lakefile.lean" + }, + { + "url": "https://github.com/leanprover-community/plausible", "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "123d15766ba49356c02ebad2a4462dfe12d79899", + "rev": "118aa17ee84656b8bd727fef7c458ee8c833385c", "name": "plausible", "manifestFile": "lake-manifest.json", "inputRev": "main", "inherited": true, - "configFile": "lakefile.toml"}, - {"url": "https://github.com/leanprover-community/LeanSearchClient", + "configFile": "lakefile.toml" + }, + { + "url": "https://github.com/leanprover-community/LeanSearchClient", "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "f5c090429dff3cf66cb65562526c9ea6e8edfbcb", + "rev": "ddf04cf3949fa556442341e87d47f9f6e6074707", "name": "LeanSearchClient", "manifestFile": "lake-manifest.json", "inputRev": "main", "inherited": true, - "configFile": "lakefile.toml"}, - {"url": "https://github.com/leanprover-community/import-graph", + "configFile": "lakefile.toml" + }, + { + "url": "https://github.com/leanprover-community/import-graph", "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "bb3469a87774349fe01898d8bf2fc6a1ce6411ca", + "rev": "e928b72544873815af278d38681b31c0293588e3", "name": "importGraph", "manifestFile": "lake-manifest.json", "inputRev": "main", "inherited": true, - "configFile": "lakefile.toml"}, - {"url": "https://github.com/leanprover-community/ProofWidgets4", + "configFile": "lakefile.toml" + }, + { + "url": "https://github.com/leanprover-community/ProofWidgets4", "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "222c58dad7706a6e7cae46c0edd65ea881d3ee27", + "rev": "106ff4fafc74ef4ac99d81dbf3ab399118f497a5", "name": "proofwidgets", "manifestFile": "lake-manifest.json", "inputRev": "main", "inherited": true, - "configFile": "lakefile.lean"}, - {"url": "https://github.com/leanprover-community/aesop", + "configFile": "lakefile.lean" + }, + { + "url": "https://github.com/leanprover-community/aesop", "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "7db8190085343afde2f5d2cdcc9bac719b6ec02c", + "rev": "355695d523e41d0554926416cba2a2b3544fbbc9", "name": "aesop", "manifestFile": "lake-manifest.json", "inputRev": "master", "inherited": true, - "configFile": "lakefile.toml"}, - {"url": "https://github.com/leanprover-community/quote4", + "configFile": "lakefile.toml" + }, + { + "url": "https://github.com/leanprover-community/quote4", "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "ef42f8944eaf5b6cbfbe75d1917d824c7dd6cf33", + "rev": "6a489d9af5d0c47e5b259e2e8bcdfc1811b5a259", "name": "Qq", "manifestFile": "lake-manifest.json", "inputRev": "master", "inherited": true, - "configFile": "lakefile.toml"}, - {"url": "https://github.com/leanprover-community/batteries", + "configFile": "lakefile.toml" + }, + { + "url": "https://github.com/leanprover-community/batteries", "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "76e1c118b0700b4ceafe99532e887d6431625e1a", + "rev": "f2effa3d803fda822b1f97b806c47cf2adfbcbc2", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", "inherited": true, - "configFile": "lakefile.toml"}, - {"url": "https://github.com/leanprover/lean4-cli", + "configFile": "lakefile.toml" + }, + { + "url": "https://github.com/leanprover/lean4-cli", "type": "git", "subDir": null, "scope": "leanprover", - "rev": "1319485273bf87833fa472afbcefdedecb16b45f", + "rev": "e92c9f15fdfacc8536f31cfb3b7ad26c3c8cd204", "name": "Cli", "manifestFile": "lake-manifest.json", - "inputRev": "v4.33.0-rc2", + "inputRev": "v4.34.0", "inherited": true, - "configFile": "lakefile.toml"}], + "configFile": "lakefile.toml" + } + ], "name": "gromov", "lakeDir": ".lake", - "fixedToolchain": false} + "fixedToolchain": false +} diff --git a/lakefile.toml b/lakefile.toml index 1faeb69..893e40a 100644 --- a/lakefile.toml +++ b/lakefile.toml @@ -9,8 +9,8 @@ autoImplicit = false [[require]] name = "mathlib" -scope = "leanprover-community" -rev = "a6180e1994004a7c705114bcbebaf5fff4b8384d" +git = "https://github.com/leanprover-community/mathlib4.git" +rev = "d13f23b723b8a846827a245b89c10fc7d3f11612" [[lean_lib]] name = "Gromov" diff --git a/lean-toolchain b/lean-toolchain index c084c7f..ba8ebf2 100644 --- a/lean-toolchain +++ b/lean-toolchain @@ -1 +1 @@ -leanprover/lean4:v4.33.0-rc2 +leanprover/lean4:v4.34.1